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    
015    package org.apache.tapestry5.services.javascript;
016    
017    import org.apache.tapestry5.*;
018    import org.apache.tapestry5.annotations.Environmental;
019    import org.apache.tapestry5.json.JSONArray;
020    import org.apache.tapestry5.json.JSONObject;
021    import 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     */
045    public 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    }