001// Copyright 2010-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.services.javascript; 016 017import org.apache.tapestry5.Asset; 018import org.apache.tapestry5.ComponentResources; 019import org.apache.tapestry5.FieldFocusPriority; 020import org.apache.tapestry5.SymbolConstants; 021import org.apache.tapestry5.annotations.Environmental; 022import org.apache.tapestry5.internal.services.DocumentLinker; 023import org.apache.tapestry5.json.JSONArray; 024import org.apache.tapestry5.json.JSONObject; 025import org.apache.tapestry5.services.EnvironmentalShadowBuilder; 026 027/** 028 * The JavaScriptSupport environmental is very stateful, accumulating JavaScript stacks, libraries and initialization 029 * code until the end of the main page render; it then updates the rendered DOM (adding <script> tags to the 030 * <head> and <body>) before the document is streamed to the client. 031 * <p/> 032 * JavaScriptSupport is normally accessed within a component by using the {@link Environmental} annotation on a 033 * component field. In addition, JavaScriptSupport may also be accessed as a service (the service 034 * {@linkplain EnvironmentalShadowBuilder internally delegates to the current environmental instance}), which is useful 035 * for service-layer objects. 036 * <p/> 037 * The term "import" is used on many methods to indicate that the indicated resource (stack, library or stylesheet) will 038 * only be added to the final cocument once, even when there are repeated calls. 039 * <p/> 040 * The name is slightly a misnomer, since there's a side-line of {@linkplain #importStylesheet(StylesheetLink)} as well. 041 * <p/> 042 * JavaScriptSupport works equally well inside an Ajax request that produces a JSON-formatted partial page update response. 043 * 044 * @see org.apache.tapestry5.internal.services.DocumentLinker 045 * @since 5.2.0 046 */ 047public interface JavaScriptSupport 048{ 049 /** 050 * Allocates a unique id based on the component's id. In some cases, the return value will not precisely match the 051 * input value (an underscore and a unique index value may be appended). 052 * 053 * @param id 054 * the component id from which a unique id will be generated 055 * @return a unique id for this rendering of the page 056 * @see org.apache.tapestry5.ioc.util.IdAllocator 057 */ 058 String allocateClientId(String id); 059 060 /** 061 * As with {@link #allocateClientId(String)} but uses the id of the component extracted from the resources. 062 * 063 * @param resources 064 * of the component which requires an id 065 * @return a unique id for this rendering of the page 066 */ 067 String allocateClientId(ComponentResources resources); 068 069 /** 070 * Adds initialization script at {@link InitializationPriority#NORMAL} priority. 071 * 072 * @param format 073 * format string (as per {@link String#format(String, Object...)} 074 * @param arguments 075 * arguments referenced by format specifiers 076 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 077 */ 078 void addScript(String format, Object... arguments); 079 080 /** 081 * Adds initialization script at the specified priority. 082 * 083 * @param priority 084 * priority to use when adding the script 085 * @param format 086 * format string (as per {@link String#format(String, Object...)} 087 * @param arguments 088 * arguments referenced by format specifiers 089 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 090 */ 091 void addScript(InitializationPriority priority, String format, Object... arguments); 092 093 /** 094 * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this 095 * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at 096 * {@link InitializationPriority#NORMAL} priority. 097 * 098 * @param functionName 099 * name of client-side function (within Tapestry.Initializer namespace) to execute 100 * @param parameter 101 * object to pass to the client-side function 102 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 103 */ 104 void addInitializerCall(String functionName, JSONObject parameter); 105 106 /** 107 * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this 108 * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at 109 * {@link InitializationPriority#NORMAL} priority. 110 * 111 * @param functionName 112 * name of client-side function (within Tapestry.Initializer namespace) to execute 113 * @param parameter 114 * array of parameters to pass to the client-side function 115 * @since 5.3 116 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 117 */ 118 void addInitializerCall(String functionName, JSONArray parameter); 119 120 /** 121 * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this 122 * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at 123 * {@link InitializationPriority#NORMAL} priority. 124 * 125 * @param functionName 126 * name of client-side function (within Tapestry.Initializer namespace) to execute 127 * @param parameter 128 * array of parameters to pass to the client-side function 129 * @since 5.3 130 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 131 */ 132 void addInitializerCall(InitializationPriority priority, String functionName, JSONArray parameter); 133 134 /** 135 * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this 136 * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at 137 * the specified priority. 138 * 139 * @param priority 140 * priority to use when adding the script 141 * @param functionName 142 * name of client-side function (within Tapestry.Initializer namespace) to execute 143 * @param parameter 144 * object to pass to the client-side function 145 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 146 */ 147 void addInitializerCall(InitializationPriority priority, String functionName, JSONObject parameter); 148 149 /** 150 * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this 151 * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at 152 * {@link InitializationPriority#NORMAL} priority. 153 * 154 * @param functionName 155 * name of client-side function (within Tapestry.Initializer namespace) to execute 156 * @param parameter 157 * string to pass to function (typically, a client id) 158 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 159 */ 160 void addInitializerCall(String functionName, String parameter); 161 162 /** 163 * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this 164 * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at 165 * the specified priority. 166 * 167 * @param priority 168 * priority to use when adding the script 169 * @param functionName 170 * name of client-side function (within Tapestry.Initializer namespace) to execute 171 * @param parameter 172 * string to pass to function (typically, a client id) 173 * @deprecated Deprecated in 5.4; refactor to use {@linkplain #require(String) JavaScript modules} instead 174 */ 175 void addInitializerCall(InitializationPriority priority, String functionName, String parameter); 176 177 /** 178 * Imports a JavaScript library as part of the rendered page. Libraries are added in the order 179 * they are first imported; duplicate imports are ignored. Libraries are added to the page serially 180 * (whereas modules may be loaded in parallel), and all libraries are added before any modules are loaded. 181 * Because of this, it is preferrable to organize your JavaScript into modules, rather than libraries. 182 * 183 * @return this JavaScriptSupport, for further configuration 184 * @see org.apache.tapestry5.annotations.Import 185 */ 186 JavaScriptSupport importJavaScriptLibrary(Asset asset); 187 188 /** 189 * A convenience method that wraps the Asset as a {@link StylesheetLink}. 190 * 191 * @param stylesheet 192 * asset for the stylesheet 193 * @return this JavaScriptSupport, for further configuration 194 * @see #importStylesheet(StylesheetLink) 195 */ 196 JavaScriptSupport importStylesheet(Asset stylesheet); 197 198 /** 199 * Imports a Cascading Style Sheet file as part of the rendered page. Stylesheets are added in the 200 * order they are first imported; duplicate imports are ignored. Starting in 5.4, importing a stylesheet 201 * imports the core stack as well (with its stylesheets); this ensures that the imported stylesheet(s) can 202 * override rules from Tapestry's default stylesheets. 203 * 204 * @param stylesheetLink 205 * encapsulates the link URL plus any additional options 206 * @return this JavaScriptSupport, for further configuration 207 */ 208 JavaScriptSupport importStylesheet(StylesheetLink stylesheetLink); 209 210 /** 211 * Imports a {@link JavaScriptStack} by name, a related set of JavaScript libraries and stylesheets. 212 * Stacks are contributions to the {@link JavaScriptStackSource} service. When 213 * {@linkplain SymbolConstants#COMBINE_SCRIPTS JavaScript aggregation} in enabled, the stack will be represented by 214 * a single virtual URL; otherwise the individual asset URLs of the stack 215 * will be added to the document. 216 * <p/> 217 * Please refer to the {@linkplain #importJavaScriptLibrary(Asset) notes about libraries vs. modules}. 218 * 219 * @param stackName 220 * the name of the stack (case is ignored); the stack must exist 221 * @return this JavaScriptSupport, for further configuration 222 */ 223 JavaScriptSupport importStack(String stackName); 224 225 /** 226 * Import a Javascript library with an arbitrary URL. 227 * <p/> 228 * Please refer to the {@linkplain #importJavaScriptLibrary(Asset) notes about libraries vs. modules}. 229 */ 230 JavaScriptSupport importJavaScriptLibrary(String libraryURL); 231 232 /** 233 * Invoked to set focus on a rendered field. Takes into account priority, meaning that a field with errors will take 234 * precedence over a merely required field, and over a field that is optional. The value 235 * {@link org.apache.tapestry5.FieldFocusPriority#OVERRIDE} can be used to force a particular field to receive 236 * focus. 237 * 238 * @param priority 239 * focus is set only if the provided priority is greater than the current priority 240 * @param fieldId 241 * id of client-side element to take focus 242 */ 243 JavaScriptSupport autofocus(FieldFocusPriority priority, String fieldId); 244 245 246 /** 247 * Requires a JavaScript module by name. On the client, this will <code>require()</code> the module and 248 * (optionally) de-reference a function exported by the module (or, treat the module as exporting a single 249 * implicit function). The function will be invoked. Use the returned {@link Initialization} to specify the function name 250 * to invoke, and the parameters to pass to the function. 251 * <p/> 252 * In some cases, a module exports no functions, but performs some initialization (typically, adding document-level 253 * event handlers), in which case a call to require() is sufficient. In cases where the module, or a function 254 * within the module, are invoked with no parameters, the calls will be collapsed into a single invocation. 255 * <p/> 256 * If the module is part of a {@linkplain org.apache.tapestry5.services.javascript.JavaScriptStack#getModules() JavaScript stack}, 257 * then the stack will be imported; this is important when {@linkplain SymbolConstants#COMBINE_SCRIPTS JavaScript aggregation is enabled}, 258 * but also ensures that libraries in the stack are loaded before the module (for cases where the 259 * module has dependencies on libraries not wrapped as AMD modules). 260 * 261 * @param moduleName 262 * the name of the module to require 263 * @return Initialization instance, used to configure function name, arguments, etc. 264 * @since 5.4 265 */ 266 Initialization require(String moduleName); 267 268 /** 269 * Adds a module configuration callback for this request. 270 * 271 * @param callback 272 * a {@link ModuleConfigurationCallback}. It cannot be null. 273 * @see DocumentLinker#addModuleConfigurationCallback(ModuleConfigurationCallback) 274 * @since 5.4 275 */ 276 void addModuleConfigurationCallback(ModuleConfigurationCallback callback); 277 278}