001// Copyright 2010, 2011 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.*;
018import org.apache.tapestry5.annotations.Environmental;
019import org.apache.tapestry5.json.JSONArray;
020import org.apache.tapestry5.json.JSONObject;
021import org.apache.tapestry5.services.EnvironmentalShadowBuilder;
022
023/**
024 * An environmental that acts as a replacement for the {@link RenderSupport} environmental, renaming and streamlining
025 * the key methods. JavaScriptSupport is very stateful, accumulating JavaScript stacks, libraries and initialization
026 * code until the end of the main page render; it then updates the rendered DOM (adding <script> tags to the
027 * <head> and <body>) before the document is streamed to the client.
028 * <p/>
029 * JavaScriptSupport is normally accessed within a component by using the {@link Environmental} annotation on a
030 * component field. In addition, JavaScriptSupport may also be accessed as a service (the service
031 * {@linkplain EnvironmentalShadowBuilder internally delegates to the current environmental instance}), which is useful
032 * for service-layer objects.
033 * <p/>
034 * The term "import" is used on many methods to indicate that the indicated resource (stack, library or stylesheet) will
035 * only be added to the final Document once.
036 * <p/>
037 * The name is slightly a misnomer, since there's a side-line of
038 * {@linkplain #importStylesheet(StylesheetLink)} as well.
039 * <p/>
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 the component id from which a unique id will be generated
052     * @return a unique id for this rendering of the page
053     * @see org.apache.tapestry5.ioc.util.IdAllocator
054     */
055    String allocateClientId(String id);
056
057    /**
058     * As with {@link #allocateClientId(String)} but uses the id of the component extracted from the resources.
059     *
060     * @param resources of the component which requires an id
061     * @return a unique id for this rendering of the page
062     */
063    String allocateClientId(ComponentResources resources);
064
065    /**
066     * Adds initialization script at {@link InitializationPriority#NORMAL} priority.
067     *
068     * @param format    format string (as per {@link String#format(String, Object...)}
069     * @param arguments arguments referenced by format specifiers
070     */
071    void addScript(String format, Object... arguments);
072
073    /**
074     * Adds initialization script at the specified priority.
075     *
076     * @param priority  priority to use when adding the script
077     * @param format    format string (as per {@link String#format(String, Object...)}
078     * @param arguments arguments referenced by format specifiers
079     */
080    void addScript(InitializationPriority priority, String format, Object... arguments);
081
082    /**
083     * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this
084     * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at
085     * {@link InitializationPriority#NORMAL} priority.
086     *
087     * @param functionName name of client-side function (within Tapestry.Initializer namespace) to execute
088     * @param parameter    object to pass to the client-side function
089     */
090    void addInitializerCall(String functionName, JSONObject parameter);
091
092    /**
093     * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this
094     * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at
095     * {@link InitializationPriority#NORMAL} priority.
096     *
097     * @param functionName name of client-side function (within Tapestry.Initializer namespace) to execute
098     * @param parameter    array of parameters to pass to the client-side function
099     * @since 5.3
100     */
101    void addInitializerCall(String functionName, JSONArray parameter);
102
103    /**
104     * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this
105     * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at
106     * {@link InitializationPriority#NORMAL} priority.
107     *
108     * @param functionName name of client-side function (within Tapestry.Initializer namespace) to execute
109     * @param parameter    array of parameters to pass to the client-side function
110     * @since 5.3
111     */
112    void addInitializerCall(InitializationPriority priority, String functionName, JSONArray parameter);
113
114    /**
115     * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this
116     * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at
117     * the specified priority.
118     *
119     * @param priority     priority to use when adding the script
120     * @param functionName name of client-side function (within Tapestry.Initializer namespace) to execute
121     * @param parameter    object to pass to the client-side function
122     */
123    void addInitializerCall(InitializationPriority priority, String functionName, JSONObject parameter);
124
125    /**
126     * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this
127     * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at
128     * {@link InitializationPriority#NORMAL} priority.
129     *
130     * @param functionName name of client-side function (within Tapestry.Initializer namespace) to execute
131     * @param parameter    string to pass to function (typically, a client id)
132     */
133    void addInitializerCall(String functionName, String parameter);
134
135    /**
136     * Adds a call to a client-side function inside the Tapestry.Initializer namespace. Calls to this
137     * method are aggregated into a call to the Tapestry.init() function. Initialization occurs at
138     * the specified priority.
139     *
140     * @param priority     priority to use when adding the script
141     * @param functionName name of client-side function (within Tapestry.Initializer namespace) to execute
142     * @param parameter    string to pass to function (typically, a client id)
143     */
144    void addInitializerCall(InitializationPriority priority, String functionName, String parameter);
145
146    /**
147     * Imports a JavaScript library as part of the rendered page. Libraries are added in the order
148     * they are first imported; duplicate imports are ignored.
149     *
150     * @see org.apache.tapestry5.annotations.Import
151     */
152    void importJavaScriptLibrary(Asset asset);
153
154    /**
155     * A convenience method that wraps the Asset as a {@link StylesheetLink}.
156     *
157     * @param stylesheet asset for the stylesheet
158     * @see #importStylesheet(StylesheetLink)
159     */
160    void importStylesheet(Asset stylesheet);
161
162    /**
163     * Imports a Cascading Style Sheet file as part of the rendered page. Stylesheets are added in the
164     * order they are first imported; duplicate imports are ignored.
165     *
166     * @param stylesheetLink encapsulates the link URL plus any additional options
167     */
168    void importStylesheet(StylesheetLink stylesheetLink);
169
170    /**
171     * Imports a {@link JavaScriptStack} by name, a related set of JavaScript libraries and stylesheets.
172     * Stacks are contributions to the {@link JavaScriptStackSource} service. When
173     * {@linkplain SymbolConstants#COMBINE_SCRIPTS JavaScript aggregation} in enabled, the stack will be represented by
174     * a single virtual URL; otherwise the individual asset URLs of the stack
175     * will be added to the document.
176     *
177     * @param stackName the name of the stack (case is ignored); the stack must exist
178     */
179    void importStack(String stackName);
180
181    /**
182     * Import a Javascript library with an arbitrary URL.
183     */
184    void importJavaScriptLibrary(String libraryURL);
185
186    /**
187     * Invoked to set focus on a rendered field. Takes into account priority, meaning that a field with errors will take
188     * precedence over a merely required field, and over a field that is optional. The value
189     * {@link org.apache.tapestry5.FieldFocusPriority#OVERRIDE} can be used to force a particular field to receive
190     * focus.
191     *
192     * @param priority focus is set only if the provided priority is greater than the current priority
193     * @param fieldId  id of client-side element to take focus
194     */
195    void autofocus(FieldFocusPriority priority, String fieldId);
196}