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