Tom
2014-11-12 bae957cd80e59f16fe011dda45ce2624e2ffd4d2
Support for adding bottom scripts

Needed if we want to have opacity changes in image diffs because
jQuery is bottom-loaded, so we must ensure that any scripts using
jQuery are run later.

I'm not a Wicket expert; maybe there's a cleverer or cleaner way to do
this. There is a JavascriptUtils class in Wicket, but that writes to
the response -- I don't quite see how that would give me control over
the precise placement of the scripts to ensure they come after that
bottom-loaded jQuery.
2 files modified
40 ■■■■■ changed files
src/main/java/com/gitblit/wicket/pages/BasePage.html 1 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/BasePage.java 39 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/BasePage.html
@@ -51,5 +51,6 @@
        <!-- Include scripts at end for faster page loading -->
        <script type="text/javascript" src="bootstrap/js/jquery.js"></script>
        <script type="text/javascript" src="bootstrap/js/bootstrap.js"></script>        
        <wicket:container wicket:id="bottomScripts"></wicket:container>
    </body>
</html>
src/main/java/com/gitblit/wicket/pages/BasePage.java
@@ -35,6 +35,7 @@
import org.apache.commons.io.IOUtils;
import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RedirectToUrlException;
@@ -42,6 +43,8 @@
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.resources.JavascriptResourceReference;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.protocol.http.RequestUtils;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
@@ -75,11 +78,13 @@
    public BasePage() {
        super();
        add(new RepeatingView("bottomScripts").setRenderBodyOnly(true));
        customizeHeader();
    }
    public BasePage(PageParameters params) {
        super(params);
        add(new RepeatingView("bottomScripts").setRenderBodyOnly(true));
        customizeHeader();
    }
@@ -506,4 +511,38 @@
        return sb.toString();
    }
    /**
     * Adds a HTML script element loading the javascript designated by the given path.
     *
     * @param scriptPath
     *            page-relative path to the Javascript resource; normally starts with "script/"
     */
    protected void addBottomScript(String scriptPath) {
        Component bottomScriptContainer = get("bottomScripts");
        if (bottomScriptContainer instanceof RepeatingView) {
            // Always true.
            RepeatingView bottomScripts = (RepeatingView) bottomScriptContainer;
            Label script = new Label(bottomScripts.newChildId(), "<script type='text/javascript' src='"
                    + urlFor(new JavascriptResourceReference(this.getClass(), scriptPath)) + "'></script>\n");
            bottomScripts.add(script.setEscapeModelStrings(false).setRenderBodyOnly(true));
        }
    }
    /**
     * Adds a HTML script element containing the given code.
     *
     * @param code
     *            inline script code
     */
    protected void addBottomScriptInline(String code) {
        Component bottomScriptContainer = get("bottomScripts");
        if (bottomScriptContainer instanceof RepeatingView) {
            // Always true.
            RepeatingView bottomScripts = (RepeatingView) bottomScriptContainer;
            Label script = new Label(bottomScripts.newChildId(),
                    "<script type='text/javascript'>/*<![CDATA[*/\n" + code + "\n//]]>\n</script>\n");
            bottomScripts.add(script.setEscapeModelStrings(false).setRenderBodyOnly(true));
        }
    }
}