/** * Copyright 2014 55 Minutes (http://www.55minutes.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package fiftyfive.wicket.js; import fiftyfive.wicket.js.JavaScriptDependencySettings; import fiftyfive.wicket.js.locator.DependencyCollection; import fiftyfive.wicket.js.locator.JavaScriptDependencyLocator; import fiftyfive.wicket.resource.MergedResourceBuilder; import org.apache.wicket.Component; import org.apache.wicket.ajax.WicketAjaxReference; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.markup.html.IHeaderResponse; import org.apache.wicket.markup.html.WicketEventReference; import org.apache.wicket.request.resource.ResourceReference; import org.apache.wicket.util.lang.Args; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Instructs Wicket to merge a list of JavaScript resources into a single file. Consider using this * in your application as a performance optimization. * <p> * Note that JavaScript resources included in this builder are scanned for depenencies. Dependencies * will automatically be included, even if they aren't explicitly added to the builder. * Refer to the <a href="package-summary.html#dependency-resolution">dependency * resolution guide</a> for more information on how dependencies are handled. * <p> * Example usage: * <pre class="example"> * public class MyApplication extends WebApplication * { * @Override * protected void init() * { * super.init(); * * new MergedJavaScriptBuilder() * .setPath("/scripts/all.js") * .addJQueryUI() * .addLibrary("jquery.scrollTo") * .addLibrary("jquery.55_utils") * .addLibrary("55_utils") * .addLibrary("strftime") * .addWicketAjaxLibraries() * .install(this); * } * }</pre> * * @since 2.0 */ public class MergedJavaScriptBuilder extends MergedResourceBuilder { private static final Logger LOGGER = LoggerFactory.getLogger( MergedJavaScriptBuilder.class ); private DependencyCollection deps; /** * Creates an empty builder object. See the * {@link MergedJavaScriptBuilder class documentation} for * example usage. */ public MergedJavaScriptBuilder() { super(); this.deps = new DependencyCollection(); } /** * {@inheritDoc} */ public MergedJavaScriptBuilder setPath(String path) { return (MergedJavaScriptBuilder) super.setPath(path); } /** * Adds a JavaScript file to the list of merged resources. The * dependencies of the script will also be added automatically. * Refer to the <a href="package-summary.html#dependency-resolution">dependency * resolution guide</a> for more information. * * @see JavaScriptDependencySettings */ public MergedJavaScriptBuilder addScript(Class<?> scope, String path) { getDependencyLocator().findResourceScripts(scope, path, this.deps); return this; } /** * Adds a JavaScript resource to the list of merged resources. The * dependencies of the script will also be added automatically. * Refer to the <a href="package-summary.html#dependency-resolution">dependency * resolution guide</a> for more information. * * @see JavaScriptDependencySettings */ public MergedJavaScriptBuilder addScript(ResourceReference ref) { getDependencyLocator().findResourceScripts( ref.getScope(), ref.getName(), this.deps ); return this; } /** * Adds a JavaScript resource of the same name and location of the given * class, except with the ".js" extension. These two statements are * equivalent: * <pre class="example"> * addAssociatedScript(MyPanel.class); * addScript(MyPanel.class, "MyPanel.js");</pre> * <p> * The dependencies of the script will also be added automatically. * Refer to the <a href="package-summary.html#dependency-resolution">dependency * resolution guide</a> for more information. * * @see JavaScriptDependencySettings */ public MergedJavaScriptBuilder addAssociatedScript(Class<?> cls) { getDependencyLocator().findAssociatedScripts(cls, this.deps); return this; } /** * Adds jQuery and jQuery UI to the list of merged resources. * * @see JavaScriptDependencySettings */ public MergedJavaScriptBuilder addJQueryUI() { return addLibrary("jquery-ui"); } /** * Adds Wicket's wicket-event.js and wicket-ajax.js files to the list * of merged resources. * * @see JavaScriptDependencySettings */ public MergedJavaScriptBuilder addWicketAjaxLibraries() { addScript(WicketEventReference.INSTANCE); addScript(WicketAjaxReference.INSTANCE); return this; } /** * Adds a JavaScript library to the list of merged resources. * The classpath will be searched to find the JavaScript file * matching {@code libraryName}. Dependencies of that file will * also be added automatically. * <p> * Refer to the <a href="package-summary.html#dependency-resolution">dependency * resolution guide</a> for more information on how fiftyfive-wicket-js * searches the classpath for JavaScript libraries and how dependencies * are handled. * * @see JavaScriptDependencySettings */ public MergedJavaScriptBuilder addLibrary(String libraryName) { Args.notNull(libraryName, "libraryName"); getDependencyLocator().findLibraryScripts(libraryName, this.deps); return this; } /** * {@inheritDoc} */ @Override protected void assertRequiredOptionsAndFreeze() { for(ResourceReference ref : this.deps) { LOGGER.debug("Added script to merged builder: {}", ref); add(ref); } super.assertRequiredOptionsAndFreeze(); } /** * {@inheritDoc} */ protected Behavior newContributor(final ResourceReference ref) { return new Behavior() { @Override public void renderHead(Component comp, IHeaderResponse response) { response.renderJavaScriptReference(ref); } }; } private JavaScriptDependencyLocator getDependencyLocator() { return JavaScriptDependencySettings.get().getLocator(); } }