001    // Copyright 2007, 2008, 2009, 2010 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.internal.services;
016    
017    import org.apache.tapestry5.Field;
018    import org.apache.tapestry5.Link;
019    import org.apache.tapestry5.corelib.data.InsertPosition;
020    import org.apache.tapestry5.json.JSONArray;
021    import org.apache.tapestry5.json.JSONLiteral;
022    import org.apache.tapestry5.json.JSONObject;
023    import org.apache.tapestry5.services.ClientBehaviorSupport;
024    import org.apache.tapestry5.services.Environment;
025    import org.apache.tapestry5.services.FormSupport;
026    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
027    
028    public class ClientBehaviorSupportImpl implements ClientBehaviorSupport
029    {
030        private final JavaScriptSupport javascriptSupport;
031    
032        private final Environment environment;
033    
034        private final JSONObject validations = new JSONObject();
035    
036        public ClientBehaviorSupportImpl(JavaScriptSupport javascriptSupport, Environment environment)
037        {
038            this.javascriptSupport = javascriptSupport;
039            this.environment = environment;
040        }
041    
042        public void addZone(String clientId, String showFunctionName, String updateFunctionName)
043        {
044            JSONObject spec = new JSONObject("element", clientId);
045    
046            addFunction(spec, "show", showFunctionName);
047            addFunction(spec, "update", updateFunctionName);
048    
049            FormSupport formSupport = environment.peek(FormSupport.class);
050    
051            if (formSupport != null)
052            {
053                JSONObject parameters = new JSONObject(RequestConstants.FORM_CLIENTID_PARAMETER, formSupport.getClientId(),
054                        RequestConstants.FORM_COMPONENTID_PARAMETER, formSupport.getFormComponentId());
055                spec.put("parameters", parameters);
056            }
057    
058            javascriptSupport.addInitializerCall("zone", spec);
059        }
060    
061        private void addFunction(JSONObject spec, String key, String functionName)
062        {
063            if (functionName != null)
064                spec.put(key, functionName.toLowerCase());
065        }
066    
067        public void linkZone(String linkId, String elementId, Link eventLink)
068        {
069            JSONObject spec = new JSONObject("linkId", linkId, "zoneId", elementId, "url", eventLink.toURI());
070    
071            javascriptSupport.addInitializerCall("linkZone", spec);
072        }
073    
074        /**
075         * @deprecated Use {@link #addFormFragment(String,boolean,String,String)} instead
076         */
077        public void addFormFragment(String clientId, String showFunctionName, String hideFunctionName)
078        {
079            addFormFragment(clientId, false, showFunctionName, hideFunctionName, null);
080        }
081    
082        /**
083         * @deprecated Use {@link #addFormFragment(String, boolean, String, String, String)} instead
084         */
085        public void addFormFragment(String clientId, boolean alwaysSubmit, String showFunctionName, String hideFunctionName)
086        {
087            addFormFragment(clientId, false, showFunctionName, hideFunctionName, null);
088        }
089    
090        public void addFormFragment(String clientId, boolean alwaysSubmit, String showFunctionName, String hideFunctionName, String visibilityBoundFunctionName)
091        {
092            JSONObject spec = new JSONObject("element", clientId);
093    
094            addFunction(spec, "show", showFunctionName);
095            addFunction(spec, "hide", hideFunctionName);
096    
097            if (visibilityBoundFunctionName != null)
098                spec.put("bound", new JSONLiteral(visibilityBoundFunctionName));
099    
100            if (alwaysSubmit)
101                spec.put("alwaysSubmit", true);
102    
103            javascriptSupport.addInitializerCall("formFragment", spec);
104        }
105    
106        public void addFormInjector(String clientId, Link link, InsertPosition insertPosition, String showFunctionName)
107        {
108            JSONObject spec = new JSONObject("element", clientId, "url", link.toURI());
109    
110            if (insertPosition == InsertPosition.BELOW)
111                spec.put("below", true);
112    
113            addFunction(spec, "show", showFunctionName);
114    
115            // Always has at least two properties.
116    
117            javascriptSupport.addInitializerCall("formInjector", spec);
118        }
119    
120        public void addValidation(Field field, String validationName, String message, Object constraint)
121        {
122            String fieldId = field.getClientId();
123    
124            JSONArray specs;
125    
126            if (validations.has(fieldId))
127                specs = validations.getJSONArray(fieldId);
128            else
129            {
130                specs = new JSONArray();
131                validations.put(fieldId, specs);
132            }
133    
134            JSONArray thisSpec = new JSONArray();
135    
136            thisSpec.put(validationName);
137            thisSpec.put(message);
138    
139            if (constraint != null)
140                thisSpec.put(constraint);
141    
142            specs.put(thisSpec);
143        }
144    
145        /**
146         * Invoked at the end of rendering to commit (to the {@link JavaScriptSupport}) any accumulated
147         * validations.
148         */
149        public void commit()
150        {
151            if (validations.length() != 0)
152                javascriptSupport.addInitializerCall("validate", validations);
153        }
154    }