diff --git a/spring-faces/.classpath b/spring-faces/.classpath index 44873627..41a2ed77 100644 --- a/spring-faces/.classpath +++ b/spring-faces/.classpath @@ -27,5 +27,6 @@ + diff --git a/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java b/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java index c9f4aeb2..94f00fb1 100644 --- a/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java +++ b/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java @@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletResponse; import org.ajax4jsf.context.AjaxContext; import org.springframework.faces.webflow.FlowLifecycle; -import org.springframework.webflow.mvc.servlet.SpringJavascriptAjaxHandler; +import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler; /** * Ajax handler that works with Rich Faces, allowing support for Web Flow ajax features with the Rich Faces toolkit. diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java index 442af4e0..7117491b 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java @@ -17,12 +17,12 @@ package org.springframework.faces.ui; import java.io.IOException; +import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.event.ActionEvent; -import org.springframework.faces.webflow.JsfUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -38,32 +38,37 @@ public class AjaxEventInterceptorRenderer extends DojoRenderer { writer.writeAttribute("type", "text/javascript", null); String processIds = (String) component.getAttributes().get("processIds"); - String renderIds = (String) component.getAttributes().get("renderIds"); if (StringUtils.hasText(processIds) && !processIds.contains(component.getClientId(context))) { processIds = component.getClientId(context) + ", " + processIds; } else if (!StringUtils.hasText(processIds)) { processIds = component.getClientId(context); } - if (!StringUtils.hasText(renderIds)) { - renderIds = processIds; - } + String childId = getElementId(context, component); StringBuffer script = new StringBuffer(); - script.append("Spring.advisors.push(new Spring.RemoteEventAdvisor({"); + script.append("Spring.addDecoration(new Spring.AjaxEventDecoration({"); script.append("event:'" + event + "'"); - script.append(", targetId: '" + ((UIComponent) component.getChildren().get(0)).getClientId(context) + "'"); - script.append(", sourceId : '" + component.getClientId(context) + "'"); + script.append(", elementId: '" + childId + "'"); script.append(", formId : '" + RendererUtils.getFormId(context, component) + "'"); - script.append(", processIds : '" + processIds + "'"); - script.append(", renderIds : '" + renderIds + "'})"); - if (JsfUtils.isAsynchronousFlowRequest()) { - script.append(".apply()"); - } - script.append(");"); + script.append(", params: {processIds : '" + processIds + "'"); + script.append(", ajaxSource : '" + component.getClientId(context) + "'} }));"); writer.writeText(script.toString(), null); writer.endElement("script"); } + private String getElementId(FacesContext context, UIComponent component) { + if (component.getChildCount() > 0) { + UIComponent child = (UIComponent) component.getChildren().get(0); + if (!(child instanceof DojoAdvisor)) { + return child.getClientId(context); + } else { + return getElementId(context, child); + } + } else { + throw new FacesException("Could not locate a proper child element to trigger the ajax event."); + } + } + public void decode(FacesContext context, UIComponent component) { if (context.getExternalContext().getRequestParameterMap().containsKey("ajaxSource") && context.getExternalContext().getRequestParameterMap().get("ajaxSource").equals( diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java index b0be9932..ae279c0a 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java @@ -25,7 +25,6 @@ import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import org.springframework.faces.ui.resource.ResourceHelper; -import org.springframework.faces.webflow.JsfUtils; import org.springframework.util.StringUtils; public class DojoAdvisorRenderer extends DojoRenderer { @@ -48,11 +47,10 @@ public class DojoAdvisorRenderer extends DojoRenderer { writer.startElement(SCRIPT_ELEMENT, component); writer.writeAttribute("type", "text/javascript", null); StringBuffer script = new StringBuffer(); - script.append(" Spring.advisors.push(new Spring.ValidatingFieldAdvisor({ "); - script.append(" targetElId : '" + advisedChild.getClientId(context) + "', "); - script.append(" msgElId : '" + advisedChild.getClientId(context) + ":msg', "); - script.append(" decoratorType : '" + ((DojoAdvisor) component).getDojoComponentType() + "', "); - script.append(" decoratorAttrs : \"{ "); + script.append(" Spring.addDecoration(new Spring.ElementDecoration({ "); + script.append(" elementId : '" + advisedChild.getClientId(context) + "', "); + script.append(" widgetType : '" + ((DojoAdvisor) component).getDojoComponentType() + "', "); + script.append(" widgetAttrs : { "); String nodeAttrs = getNodeAttributesAsString(context, advisedChild); String dojoAttrs = getDojoAttributesAsString(context, component); @@ -63,13 +61,7 @@ public class DojoAdvisorRenderer extends DojoRenderer { } script.append(dojoAttrs); - script.append(" }\"})"); - - if (JsfUtils.isAsynchronousFlowRequest()) { - script.append(".apply()"); - } - - script.append("); "); + script.append(" }}));"); writer.writeText(script, null); writer.endElement(SCRIPT_ELEMENT); diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java index 6f0d7f35..8216a1fc 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java @@ -69,20 +69,16 @@ public class ProgressiveCommandButtonRenderer extends BaseDojoParentComponentRen Boolean ajaxEnabled = (Boolean) component.getAttributes().get("ajaxEnabled"); String processIds = (String) component.getAttributes().get("processIds"); - String renderIds = (String) component.getAttributes().get("renderIds"); if (Boolean.TRUE.equals(ajaxEnabled)) { if (StringUtils.hasText(processIds) && !processIds.contains(component.getClientId(context))) { processIds = component.getClientId(context) + ", " + processIds; } else if (!StringUtils.hasText(processIds)) { processIds = component.getClientId(context); } - if (!StringUtils.hasText(renderIds)) { - renderIds = processIds; - } - onclick.append("Spring.RemotingHandler.submitForm('" + component.getClientId(context) + "', "); + onclick.append("Spring.remoting.submitForm('" + component.getClientId(context) + "', "); onclick.append("'" + RendererUtils.getFormId(context, component) + "', "); - onclick.append("'" + processIds + "', '" + renderIds + "', " + encodeParams(context, component) - + "); return false;"); + onclick.append("{processIds: '" + processIds + "'" + encodeParams(context, component) + + "}); return false;"); } else { onclick.append(getOnClickNoAjax(context, component)); } @@ -142,20 +138,15 @@ public class ProgressiveCommandButtonRenderer extends BaseDojoParentComponentRen protected String encodeParams(FacesContext context, UIComponent component) { StringBuffer paramArray = new StringBuffer(); - paramArray.append("["); for (int i = 0; i < component.getChildCount(); i++) { if (component.getChildren().get(i) instanceof UIParameter) { UIParameter param = (UIParameter) component.getChildren().get(i); Assert.hasText(param.getName(), "UIParameter requires a name when used as a child of a UICommand component"); - if (paramArray.length() > 1) { - paramArray.append(", "); - } - paramArray.append("{name : '" + param.getName() + "'"); - paramArray.append(", value : '" + param.getValue() + "'}"); + + paramArray.append(", " + param.getName() + ": '" + param.getValue() + "'"); } } - paramArray.append("]"); return paramArray.toString(); } diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java index e36db99f..a9503511 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java @@ -101,9 +101,9 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend public void encodeEnd(FacesContext context, UIComponent component) throws IOException { super.encodeEnd(context, component); - StringBuffer advisorParams = new StringBuffer(); - advisorParams.append("{"); - advisorParams.append("targetElId : '" + component.getClientId(context) + "'"); + StringBuffer decorationParams = new StringBuffer(); + decorationParams.append("{"); + decorationParams.append("elementId : '" + component.getClientId(context) + "'"); ResponseWriter writer = context.getResponseWriter(); // Close the script variable started in encodeBegin if this is not an AJAX request @@ -117,18 +117,14 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend String scriptVarEnd = "\";\n"; writer.writeText(scriptVarEnd, null); - advisorParams.append(", linkHtml : " + component.getClientId(context).replaceAll(":", "_") + "_link"); + decorationParams.append(", linkHtml : " + component.getClientId(context).replaceAll(":", "_") + "_link"); writer.endElement("script"); } - advisorParams.append("}"); + decorationParams.append("}"); StringBuffer advisorScript = new StringBuffer(); - advisorScript.append("Spring.advisors.push(new Spring.CommandLinkAdvisor(" + advisorParams.toString() + ")"); - // Apply the advisor immediately if this is an AJAX request - if (JsfUtils.isAsynchronousFlowRequest()) { - advisorScript.append(".apply()"); - } - advisorScript.append(");"); + advisorScript.append("Spring.addDecoration(new Spring.CommandLinkDecoration(" + decorationParams.toString() + + "));"); writer.startElement("script", component); writer.writeText(advisorScript, null); writer.endElement("script"); diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java index 5ccea918..72b960ce 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java @@ -44,8 +44,8 @@ public class ValidateAllRenderer extends SpringFacesRenderer { writer.startElement(SCRIPT_ELEMENT, component); writer.writeAttribute("type", "text/javascript", null); StringBuffer script = new StringBuffer(); - script.append("Spring.advisors.push(new Spring.ValidateAllAdvisor({" + "event : 'onclick', " + "targetId : '" - + advisedChild.getClientId(context) + "'}));"); + script.append("Spring.addDecoration(new Spring.ValidateAllDecoration({" + "event : 'onclick', " + + "elementId : '" + advisedChild.getClientId(context) + "'}));"); writer.writeText(script, null); writer.endElement(SCRIPT_ELEMENT); } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java index 588ee9ee..6c9e7e4d 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java @@ -35,12 +35,12 @@ import org.springframework.context.ApplicationContext; import org.springframework.core.io.ContextResource; import org.springframework.core.io.Resource; import org.springframework.faces.ui.AjaxViewRoot; +import org.springframework.js.mvc.servlet.AjaxHandler; +import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler; import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.View; import org.springframework.webflow.execution.ViewFactory; -import org.springframework.webflow.mvc.servlet.AjaxHandler; -import org.springframework.webflow.mvc.servlet.SpringJavascriptAjaxHandler; /** * JSF-specific {@link ViewFactory} implementation. diff --git a/spring-js/.classpath b/spring-js/.classpath index 0447daa0..8546b382 100644 --- a/spring-js/.classpath +++ b/spring-js/.classpath @@ -5,7 +5,6 @@ - @@ -14,5 +13,12 @@ + + + + + + + diff --git a/spring-js/ivy.xml b/spring-js/ivy.xml index 8ca7c976..d25a89e4 100644 --- a/spring-js/ivy.xml +++ b/spring-js/ivy.xml @@ -23,9 +23,15 @@ + + + + + + diff --git a/spring-js/src/main/java/org/springframework/js/ajax/view/TilesAjaxView.java b/spring-js/src/main/java/org/springframework/js/ajax/view/TilesAjaxView.java new file mode 100644 index 00000000..3a4d489c --- /dev/null +++ b/spring-js/src/main/java/org/springframework/js/ajax/view/TilesAjaxView.java @@ -0,0 +1,77 @@ +package org.springframework.js.ajax.view; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.Attribute; +import org.apache.tiles.Definition; +import org.apache.tiles.Attribute.AttributeType; +import org.apache.tiles.access.TilesAccess; +import org.apache.tiles.context.TilesRequestContext; +import org.apache.tiles.impl.BasicTilesContainer; +import org.springframework.js.mvc.servlet.AjaxHandler; +import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler; +import org.springframework.web.servlet.support.JstlUtils; +import org.springframework.web.servlet.support.RequestContext; +import org.springframework.web.servlet.view.tiles2.TilesView; + +public class TilesAjaxView extends TilesView { + + public static final String FRAGMENTS_PARAM = "fragments"; + + private AjaxHandler ajaxHandler = new SpringJavascriptAjaxHandler(); + + protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) + throws Exception { + + ServletContext servletContext = getServletContext(); + if (ajaxHandler.isAjaxRequest(servletContext, request, response)) { + BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(servletContext); + if (container == null) { + throw new ServletException("Tiles container is not initialized. " + + "Have you added a TilesConfigurer to your web application context?"); + } + + exposeModelAsRequestAttributes(model, request); + JstlUtils.exposeLocalizationContext(new RequestContext(request, servletContext)); + + TilesRequestContext tilesRequestContext = container.getContextFactory().createRequestContext( + container.getApplicationContext(), new Object[] { request, response }); + Definition compositeDefinition = container.getDefinitionsFactory().getDefinition(getUrl(), + tilesRequestContext); + Map flattenedAttributeMap = new HashMap(); + flattenAttributeMap(container, tilesRequestContext, flattenedAttributeMap, compositeDefinition); + + String attrName = request.getParameter(FRAGMENTS_PARAM); + + Attribute attributeToRender = (Attribute) flattenedAttributeMap.get(attrName); + + container.render(attributeToRender, response.getWriter(), new Object[] { request, response }); + } else { + super.renderMergedOutputModel(model, request, response); + } + } + + private void flattenAttributeMap(BasicTilesContainer container, TilesRequestContext requestContext, Map resultMap, + Definition compositeDefinition) throws Exception { + Iterator i = compositeDefinition.getAttributes().keySet().iterator(); + while (i.hasNext()) { + Object key = i.next(); + Attribute attr = (Attribute) compositeDefinition.getAttributes().get(key); + if (attr.getType() == AttributeType.DEFINITION) { + Definition nestedDefinition = container.getDefinitionsFactory().getDefinition( + attr.getValue().toString(), requestContext); + flattenAttributeMap(container, requestContext, resultMap, nestedDefinition); + } else { + resultMap.put(key, attr); + } + } + } + +} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AjaxHandler.java b/spring-js/src/main/java/org/springframework/js/mvc/servlet/AjaxHandler.java similarity index 97% rename from spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AjaxHandler.java rename to spring-js/src/main/java/org/springframework/js/mvc/servlet/AjaxHandler.java index c7152bd1..3c752571 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AjaxHandler.java +++ b/spring-js/src/main/java/org/springframework/js/mvc/servlet/AjaxHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.webflow.mvc.servlet; +package org.springframework.js.mvc.servlet; import java.io.IOException; diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/SpringJavascriptAjaxHandler.java b/spring-js/src/main/java/org/springframework/js/mvc/servlet/SpringJavascriptAjaxHandler.java similarity index 82% rename from spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/SpringJavascriptAjaxHandler.java rename to spring-js/src/main/java/org/springframework/js/mvc/servlet/SpringJavascriptAjaxHandler.java index f0989a26..fe79f05f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/SpringJavascriptAjaxHandler.java +++ b/spring-js/src/main/java/org/springframework/js/mvc/servlet/SpringJavascriptAjaxHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.webflow.mvc.servlet; +package org.springframework.js.mvc.servlet; import java.io.IOException; @@ -34,22 +34,22 @@ public class SpringJavascriptAjaxHandler implements AjaxHandler { /** * The response header to be set on an Ajax redirect */ - private static final String FLOW_REDIRECT_URL_HEADER = "Flow-Redirect-URL"; + public static final String REDIRECT_URL_HEADER = "Spring-Redirect-URL"; /** * The response header to be set on an redirect that should be issued from a popup window. */ - private static final String POPUP_VIEW_HEADER = "Flow-Modal-View"; + public static final String POPUP_VIEW_HEADER = "Spring-Modal-View"; /** * The accept header value that signifies an Ajax request. */ - private static final String AJAX_ACCEPT_CONTENT_TYPE = "text/html;type=ajax"; + public static final String AJAX_ACCEPT_CONTENT_TYPE = "text/html;type=ajax"; /** * Alternate request parameter to indicate an Ajax request for cases when control of the header is not available. */ - private static final String AJAX_SOURCE_PARAM = "ajaxSource"; + public static final String AJAX_SOURCE_PARAM = "ajaxSource"; public boolean isAjaxRequest(ServletContext context, HttpServletRequest request, HttpServletResponse response) { String acceptHeader = request.getHeader("Accept"); @@ -66,7 +66,7 @@ public class SpringJavascriptAjaxHandler implements AjaxHandler { if (popup) { response.setHeader(POPUP_VIEW_HEADER, "true"); } - response.setHeader(FLOW_REDIRECT_URL_HEADER, response.encodeRedirectURL(targetUrl)); + response.setHeader(REDIRECT_URL_HEADER, response.encodeRedirectURL(targetUrl)); } } \ No newline at end of file diff --git a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js index b973fb81..733bf158 100644 --- a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js +++ b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -Spring.DojoValidatingFieldAdvisor=function(_1){dojo.mixin(this,_1);};Spring.DojoValidatingFieldAdvisor.prototype={targetElId:"",decoratorType:"",decorator:null,decoratorAttrs:"",apply:function(){if(dijit.byId(this.targetElId)){dijit.byId(this.targetElId).destroyRecursive(false);}this.decorator=eval("new "+this.decoratorType+"("+this.decoratorAttrs+", dojo.byId('"+this.targetElId+"'));");this.decorator.startup();return this;},validate:function(){var _2=this.decorator.isValid(false);if(!_2){this.decorator.state="Error";this.decorator._setStateClass();}return _2;}};Spring.ValidatingFieldAdvisor=Spring.DojoValidatingFieldAdvisor;Spring.DojoRemoteEventAdvisor=function(_3){dojo.mixin(this,_3);};Spring.DojoRemoteEventAdvisor.prototype={event:"",targetId:"",sourceId:"",formId:"",processIds:"",renderIds:"",params:[],connection:null,apply:function(){this.connection=dojo.connect(dojo.byId(this.targetId),this.event,this,"submit");return this;},cleanup:function(){dojo.disconnect(this.connection);},submit:function(){Spring.RemotingHandler.submitForm(this.sourceId,this.formId,this.processIds,this.renderIds,this.params);}};Spring.RemoteEventAdvisor=Spring.DojoRemoteEventAdvisor;Spring.DojoValidateAllAdvisor=function(_4){dojo.mixin(this,_4);};Spring.DojoValidateAllAdvisor.prototype={event:"",targetId:"",originalHandler:null,connection:null,apply:function(){var _5=dojo.byId(this.targetId);this.originalHandler=_5[this.event];var _6=this;_5[this.event]=function(_7){_6.handleEvent(_7,_6);};return this;},cleanup:function(){dojo.disconnect(this.connection);},handleEvent:function(_8,_9){if(!Spring.validateAll()){dojo.stopEvent(_8);}else{var _a=_9.originalHandler(_8);if(_a==false){dojo.stopEvent(_8);}}}};Spring.ValidateAllAdvisor=Spring.DojoValidateAllAdvisor;Spring.DojoRemotingHandler=function(){};Spring.DojoRemotingHandler.prototype={submitForm:function(_b,_c,_d,_e,_f){var _10=new Object();var _11=dojo.byId(_b);_10["processIds"]=_d;_10["renderIds"]=_e;if(_11!=null){if(_11.value){_10[_b]=_11.value;}else{_10[_b]=_b;}}dojo.forEach(_f,function(_12){_10[_12.name]=_12.value;});_10["ajaxSource"]=_b;dojo.xhrPost({content:_10,form:_c,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError});},getLinkedResource:function(_13,_14){this.getResource(dojo.byId(_13).href,_14);},getResource:function(_15,_16){dojo.xhrGet({url:_15,handleAs:"text",load:this.handleResponse,error:this.handleError,modal:_16});},handleResponse:function(_17,_18){var _19=_18.xhr.getResponseHeader("Flow-Redirect-URL");var _1a=_18.xhr.getResponseHeader("Flow-Modal-View");var _1b=((dojo.isString(_1a)&&_1a.length>0)||_18.args.modal);if(dojo.isString(_19)&&_19.length>0){if(_1b){Spring.RemotingHandler.renderURLToModalDialog(_19,_18);return _17;}else{window.location=window.location.protocol+"//"+window.location.host+_19;return _17;}}var _1c="(?:)((\n|\r|.)*?)(?:)";var _1d=[];var _1e=new RegExp(_1c,"img");var _1f=new RegExp(_1c,"im");var _20=_17.match(_1e);if(_20!=null){for(var i=0;i<_20.length;i++){var _22=(_20[i].match(_1f)||["",""])[1];_22=_22.replace(//mg,"");_1d.push(_22);}}_17=_17.replace(_1e,"");var _23=dojo.doc.createElement("div");_23.id="ajaxResponse";_23.style.visibility="hidden";document.body.appendChild(_23);var _24=new dojo.NodeList(_23);var _25=_24.addContent(_17,"first").query("#ajaxResponse > *").orphan();_24.orphan();if(_1b){Spring.RemotingHandler.renderNodeListToModalDialog(_25);}else{_25.forEach(function(_26){if(_26.id!=null&&_26.id!=""){var _27=dojo.byId(_26.id);_27.parentNode.replaceChild(_26,_27);}});}dojo.forEach(_1d,function(_28){dojo.eval(_28);});return _17;},handleError:function(_29,_2a){console.error("HTTP status code: ",_2a.xhr.status);return _29;},renderURLToModalDialog:function(url,_2c){url=url+"&"+dojo.objectToQuery(_2c.args.content);Spring.RemotingHandler.getResource(url,true);},renderNodeListToModalDialog:function(_2d){dojo.require("dijit.Dialog");var _2e=new dijit.Dialog({});_2e.setContent(_2d);dojo.connect(_2e,"hide",_2e,function(){this.destroyRecursive(false);});_2e.show();}};Spring.RemotingHandler=new Spring.DojoRemotingHandler();Spring.DojoCommandLinkAdvisor=function(_2f){dojo.mixin(this,_2f);};Spring.DojoCommandLinkAdvisor.prototype={targetElId:"",linkHtml:"",apply:function(){var _30=dojo.byId(this.targetElId);if(!dojo.hasClass(_30,"progressiveLink")){var _31=new dojo.NodeList(_30);_31.addContent(this.linkHtml,"after").orphan("*");_30=dojo.byId(this.targetElId);}_30.submitFormFromLink=this.submitFormFromLink;return this;},submitFormFromLink:function(_32,_33,_34){var _35=[];var _36=dojo.byId(_32);var _37=document.createElement("input");_37.name=_33;_37.value="submitted";_35.push(_37);dojo.forEach(_34,function(_38){var _39=document.createElement("input");_39.name=_38.name;_39.value=_38.value;_35.push(_39);});dojo.forEach(_35,function(_3a){dojo.addClass(_3a,"SpringLinkInput");dojo.place(_3a,_36,"last");});if((_36.onsubmit?!_36.onsubmit():false)||!_36.submit()){dojo.forEach(_35,function(_3b){_36.removeChild(_3b);});}}};Spring.CommandLinkAdvisor=Spring.DojoCommandLinkAdvisor;dojo.addOnLoad(Spring.applyAdvisors); \ No newline at end of file +dojo.declare("Spring.ElementDecoration",Spring.AbstractElementDecoration,{constructor:function(_1){this.copyFields=new Array("name","value","type","checked","selected","readOnly","disabled","alt","maxLength");dojo.mixin(this,_1);if(this.widgetModule==""){this.widgetModule=this.widgetType;}},apply:function(){if(dijit.byId(this.elementId)){dijit.byId(this.elementId).destroyRecursive(false);}var _2=dojo.byId(this.elementId);for(var _3 in this.copyFields){_3=this.copyFields[_3];if(!this.widgetAttrs[_3]&&_2[_3]&&(typeof _2[_3]!="number"||(typeof _2[_3]=="number"&&_2[_3]>=0))){this.widgetAttrs[_3]=_2[_3];}}dojo.require(this.widgetModule);var _4=dojo.eval(this.widgetType);this.widget=new _4(this.widgetAttrs,_2);this.widget.startup();return this;},validate:function(){if(!this.widget.isValid){return true;}var _5=this.widget.isValid(false);if(!_5){this.widget.state="Error";this.widget._setStateClass();}return _5;}});dojo.declare("Spring.ValidateAllDecoration",Spring.AbstractValidateAllDecoration,{constructor:function(_6){this.originalHandler=null;this.connection=null;dojo.mixin(this,_6);},apply:function(){var _7=dojo.byId(this.elementId);this.originalHandler=_7[this.event];var _8=this;_7[this.event]=function(_9){_8.handleEvent(_9,_8);};return this;},cleanup:function(){dojo.disconnect(this.connection);},handleEvent:function(_a,_b){if(!Spring.validateAll()){dojo.stopEvent(_a);}else{if(dojo.isFunction(_b.originalHandler)){var _c=_b.originalHandler(_a);if(_c==false){dojo.stopEvent(_a);}}}}});dojo.declare("Spring.AjaxEventDecoration",Spring.AbstractAjaxEventDecoration,{constructor:function(_d){this.connection=null;dojo.mixin(this,_d);},apply:function(){this.connection=dojo.connect(dojo.byId(this.elementId),this.event,this,"submit");return this;},cleanup:function(){dojo.disconnect(this.connection);},submit:function(_e){if(this.sourceId==""){this.sourceId=this.elementId;}if(this.formId==""){Spring.remoting.getLinkedResource(this.sourceId,this.params,false);}else{Spring.remoting.submitForm(this.sourceId,this.formId,this.params);}dojo.stopEvent(_e);}});dojo.declare("Spring.RemotingHandler",Spring.AbstractRemotingHandler,{constructor:function(){},submitForm:function(_f,_10,_11){var _12=new Object();for(var key in _11){_12[key]=_11[key];}var _14=dojo.byId(_f);if(_14!=null){if(_14.value!=undefined){_12[_f]=_14.value;}else{_12[_f]=_f;}}if(!_12["ajaxSource"]){_12["ajaxSource"]=_f;}dojo.xhrPost({content:_12,form:_10,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError});},getLinkedResource:function(_15,_16,_17){this.getResource(dojo.byId(_15).href,_16,_17);},getResource:function(_18,_19,_1a){dojo.xhrGet({url:_18,content:_19,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError,modal:_1a});},handleResponse:function(_1b,_1c){var _1d=_1c.xhr.getResponseHeader("Spring-Redirect-URL");var _1e=_1c.xhr.getResponseHeader("Spring-Modal-View");var _1f=((dojo.isString(_1e)&&_1e.length>0)||_1c.args.modal);if(dojo.isString(_1d)&&_1d.length>0){if(_1f){Spring.remoting.renderURLToModalDialog(_1d,_1c);return _1b;}else{window.location=window.location.protocol+"//"+window.location.host+_1d;return _1b;}}var _20="(?:)((\n|\r|.)*?)(?:)";var _21=[];var _22=new RegExp(_20,"img");var _23=new RegExp(_20,"im");var _24=_1b.match(_22);if(_24!=null){for(var i=0;i<_24.length;i++){var _26=(_24[i].match(_23)||["",""])[1];_26=_26.replace(//mg,"");_21.push(_26);}}_1b=_1b.replace(_22,"");var _27=dojo.doc.createElement("div");_27.id="ajaxResponse";_27.style.visibility="hidden";document.body.appendChild(_27);var _28=new dojo.NodeList(_27);var _29=_28.addContent(_1b,"first").query("#ajaxResponse > *").orphan();_28.orphan();if(_1f){Spring.remoting.renderNodeListToModalDialog(_29);}else{_29.forEach(function(_2a){if(_2a.id!=null&&_2a.id!=""){var _2b=dojo.byId(_2a.id);_2b.parentNode.replaceChild(_2a,_2b);}});}dojo.forEach(_21,function(_2c){dojo.eval(_2c);});return _1b;},handleError:function(_2d,_2e){console.error("HTTP status code: ",_2e.xhr.status);return _2d;},renderURLToModalDialog:function(url,_30){url=url+"&"+dojo.objectToQuery(_30.args.content);Spring.remoting.getResource(url,{},true);},renderNodeListToModalDialog:function(_31){dojo.require("dijit.Dialog");var _32=new dijit.Dialog({});_32.setContent(_31);dojo.connect(_32,"hide",_32,function(){this.destroyRecursive(false);});_32.show();}});dojo.declare("Spring.CommandLinkDecoration",Spring.AbstractCommandLinkDecoration,{constructor:function(_33){dojo.mixin(this,_33);},apply:function(){var _34=dojo.byId(this.elementId);if(!dojo.hasClass(_34,"progressiveLink")){var _35=new dojo.NodeList(_34);_35.addContent(this.linkHtml,"after").orphan("*");_34=dojo.byId(this.elementId);}_34.submitFormFromLink=this.submitFormFromLink;return this;},submitFormFromLink:function(_36,_37,_38){var _39=[];var _3a=dojo.byId(_36);var _3b=document.createElement("input");_3b.name=_37;_3b.value="submitted";_39.push(_3b);dojo.forEach(_38,function(_3c){var _3d=document.createElement("input");_3d.name=_3c.name;_3d.value=_3c.value;_39.push(_3d);});dojo.forEach(_39,function(_3e){dojo.addClass(_3e,"SpringLinkInput");dojo.place(_3e,_3a,"last");});if((_3a.onsubmit?!_3a.onsubmit():false)||!_3a.submit()){dojo.forEach(_39,function(_3f){_3a.removeChild(_3f);});}}});dojo.addOnLoad(Spring.initialize); \ No newline at end of file diff --git a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed index 7956c816..f39af88c 100644 --- a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed +++ b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed @@ -13,88 +13,62 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -Spring.DojoValidatingFieldAdvisor = function(config){ - - dojo.mixin(this, config); -}; - -Spring.DojoValidatingFieldAdvisor.prototype = { - - targetElId : "", - decoratorType : "", - decorator : null, - decoratorAttrs : "", - - apply : function(){ - if (dijit.byId(this.targetElId)) { - dijit.byId(this.targetElId).destroyRecursive(false); + +dojo.declare("Spring.ElementDecoration", Spring.AbstractElementDecoration, { + constructor : function(config) { + this.copyFields = new Array('name', 'value', 'type', 'checked', 'selected', 'readOnly', 'disabled', 'alt', 'maxLength'); + dojo.mixin(this, config); + if(this.widgetModule == "") { + this.widgetModule = this.widgetType; } - this.decorator = eval("new "+ this.decoratorType + "(" + this.decoratorAttrs +", dojo.byId('"+this.targetElId+"'));" ); - this.decorator.startup(); - + }, + + apply : function(){ + if (dijit.byId(this.elementId)) { + dijit.byId(this.elementId).destroyRecursive(false); + } + var element = dojo.byId(this.elementId); + for (var copyField in this.copyFields) { + copyField = this.copyFields[copyField]; + if (!this.widgetAttrs[copyField] && element[copyField] && (typeof element[copyField] != 'number' || + (typeof element[copyField] == 'number' && element[copyField] >= 0))) { + this.widgetAttrs[copyField] = element[copyField]; + } + } + dojo.require(this.widgetModule); + var widgetConstructor = dojo.eval(this.widgetType); + this.widget = new widgetConstructor(this.widgetAttrs, element); + this.widget.startup(); //return this to support method chaining return this; }, validate : function(){ - var isValid = this.decorator.isValid(false); + if (!this.widget.isValid) { + // some widgets cannot be validated + return true; + } + var isValid = this.widget.isValid(false); if (!isValid) { - this.decorator.state = "Error"; - this.decorator._setStateClass(); + this.widget.state = "Error"; + this.widget._setStateClass(); } return isValid; } -}; +}); -Spring.ValidatingFieldAdvisor = Spring.DojoValidatingFieldAdvisor; - -Spring.DojoRemoteEventAdvisor = function(config){ - dojo.mixin(this, config); -}; - -Spring.DojoRemoteEventAdvisor.prototype = { - - event : "", - targetId : "", - sourceId : "", - formId : "", - processIds : "", - renderIds : "", - params : [], - connection : null, - - apply : function() { - this.connection = dojo.connect(dojo.byId(this.targetId), this.event, this, "submit"); - return this; +dojo.declare("Spring.ValidateAllDecoration", Spring.AbstractValidateAllDecoration, { + constructor : function(config) { + this.originalHandler = null; + this.connection = null; + dojo.mixin(this, config); }, - cleanup : function(){ - dojo.disconnect(this.connection); - }, - - submit : function(){ - Spring.RemotingHandler.submitForm(this.sourceId, this.formId, this.processIds, this.renderIds, this.params); - } -}; - -Spring.RemoteEventAdvisor = Spring.DojoRemoteEventAdvisor; - -Spring.DojoValidateAllAdvisor = function(config){ - dojo.mixin(this, config); -}; - -Spring.DojoValidateAllAdvisor.prototype = { - - event : "", - targetId : "", - originalHandler : null, - connection : null, - apply : function() { - var targetEl = dojo.byId(this.targetId); - this.originalHandler = targetEl[this.event]; + var element = dojo.byId(this.elementId); + this.originalHandler = element[this.event]; var context = this; - targetEl[this.event] = function(event){ + element[this.event] = function(event){ context.handleEvent(event, context); }; return this; @@ -107,40 +81,65 @@ Spring.DojoValidateAllAdvisor.prototype = { handleEvent : function(event, context){ if (!Spring.validateAll()) { dojo.stopEvent(event); - } else { + } else if(dojo.isFunction(context.originalHandler)) { var result = context.originalHandler(event); if (result == false) { dojo.stopEvent(event); } } } -}; +}); -Spring.ValidateAllAdvisor = Spring.DojoValidateAllAdvisor; - -Spring.DojoRemotingHandler = function(){}; - -Spring.DojoRemotingHandler.prototype = { +dojo.declare("Spring.AjaxEventDecoration", Spring.AbstractAjaxEventDecoration, { + constructor : function(config){ + this.connection = null; + dojo.mixin(this, config); + }, - submitForm : function(/*String */ sourceId, /*String*/formId, /*String*/ processIds, /*String*/renderIds, /*Array*/ params) { + apply : function() { + this.connection = dojo.connect(dojo.byId(this.elementId), this.event, this, "submit"); + return this; + }, + + cleanup : function(){ + dojo.disconnect(this.connection); + }, + + submit : function(event){ + if (this.sourceId == ""){ + this.sourceId = this.elementId; + } + if(this.formId == ""){ + Spring.remoting.getLinkedResource(this.sourceId, this.params, false); + } else { + Spring.remoting.submitForm(this.sourceId, this.formId, this.params); + } + dojo.stopEvent(event); + } +}); + +dojo.declare("Spring.RemotingHandler", Spring.AbstractRemotingHandler, { + constructor : function(){}, + + submitForm : function(/*String */ sourceId, /*String*/formId, /*Object*/ params) { var content = new Object(); + for (var key in params) { + content[key] = params[key]; + } + var sourceComponent = dojo.byId(sourceId); - content['processIds'] = processIds; - content['renderIds'] = renderIds; if (sourceComponent != null){ - if(sourceComponent.value) { + if(sourceComponent.value != undefined) { content[sourceId] = sourceComponent.value; } else { content[sourceId] = sourceId; } } - dojo.forEach(params, function(param){ - content[param.name] = param.value; - }); - - content['ajaxSource'] = sourceId; + if (!content['ajaxSource']) { + content['ajaxSource'] = sourceId; + } dojo.xhrPost({ @@ -161,18 +160,22 @@ Spring.DojoRemotingHandler.prototype = { }, - getLinkedResource: function(/*String */ linkId, /*boolean*/ modal) { - this.getResource(dojo.byId(linkId).href, modal); + getLinkedResource: function(/*String */ linkId, /*Object*/params, /*boolean*/ modal) { + this.getResource(dojo.byId(linkId).href, params, modal); }, - getResource: function(/*String */ resourceUri, /*boolean*/ modal) { + getResource: function(/*String */ resourceUri, /*Object*/params, /*boolean*/ modal) { dojo.xhrGet({ url: resourceUri, + content: params, + handleAs: "text", + headers: {"Accept" : "text/html;type=ajax"}, + load: this.handleResponse, error: this.handleError, @@ -184,14 +187,14 @@ Spring.DojoRemotingHandler.prototype = { handleResponse: function(response, ioArgs) { //First check if this response should redirect - var redirectURL = ioArgs.xhr.getResponseHeader('Flow-Redirect-URL'); - var modalViewHeader = ioArgs.xhr.getResponseHeader('Flow-Modal-View'); + var redirectURL = ioArgs.xhr.getResponseHeader('Spring-Redirect-URL'); + var modalViewHeader = ioArgs.xhr.getResponseHeader('Spring-Modal-View'); var modalView = ((dojo.isString(modalViewHeader) && modalViewHeader.length > 0) || ioArgs.args.modal); if (dojo.isString(redirectURL) && redirectURL.length > 0) { if (modalView) { //render a popup with the new URL - Spring.RemotingHandler.renderURLToModalDialog(redirectURL, ioArgs); + Spring.remoting.renderURLToModalDialog(redirectURL, ioArgs); return response; } else { @@ -229,7 +232,7 @@ Spring.DojoRemotingHandler.prototype = { //For a modal view, just dump the new nodes into a modal dialog if (modalView) { - Spring.RemotingHandler.renderNodeListToModalDialog(newNodes); + Spring.remoting.renderNodeListToModalDialog(newNodes); } else { @@ -258,7 +261,7 @@ Spring.DojoRemotingHandler.prototype = { renderURLToModalDialog: function(url, ioArgs) { url = url + "&"+dojo.objectToQuery(ioArgs.args.content); - Spring.RemotingHandler.getResource(url, true); + Spring.remoting.getResource(url, {}, true); }, renderNodeListToModalDialog: function(nodes) { @@ -271,28 +274,21 @@ Spring.DojoRemotingHandler.prototype = { }); dialog.show(); } -}; +}); -Spring.RemotingHandler = new Spring.DojoRemotingHandler(); - -Spring.DojoCommandLinkAdvisor = function(config){ - dojo.mixin(this, config); -}; - -Spring.DojoCommandLinkAdvisor.prototype = { - - targetElId : "", - - linkHtml : "", +dojo.declare("Spring.CommandLinkDecoration", Spring.AbstractCommandLinkDecoration, { + constructor : function(config){ + dojo.mixin(this, config); + }, apply : function(){ - var advisedNode = dojo.byId(this.targetElId); + var advisedNode = dojo.byId(this.elementId); if (!dojo.hasClass(advisedNode, "progressiveLink")) { //Node must be replaced var nodeToReplace = new dojo.NodeList(advisedNode); nodeToReplace.addContent(this.linkHtml, "after").orphan("*"); //Get the new node - advisedNode = dojo.byId(this.targetElId); + advisedNode = dojo.byId(this.elementId); } advisedNode.submitFormFromLink = this.submitFormFromLink; //return this to support method chaining @@ -325,8 +321,6 @@ Spring.DojoCommandLinkAdvisor.prototype = { }); } } -}; +}); -Spring.CommandLinkAdvisor = Spring.DojoCommandLinkAdvisor; - -dojo.addOnLoad(Spring.applyAdvisors); \ No newline at end of file +dojo.addOnLoad(Spring.initialize); \ No newline at end of file diff --git a/spring-js/src/main/resources/META-INF/spring/Spring.js b/spring-js/src/main/resources/META-INF/spring/Spring.js index 0f7b9c8e..633368de 100644 --- a/spring-js/src/main/resources/META-INF/spring/Spring.js +++ b/spring-js/src/main/resources/META-INF/spring/Spring.js @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -Spring={};Spring.advisors=[];Spring.advisors.applied=false;Spring.applyAdvisors=function(){if(!Spring.advisors.applied){for(var x=0;x + diff --git a/spring-webflow/ivy.xml b/spring-webflow/ivy.xml index 9dd6aefb..9468080d 100644 --- a/spring-webflow/ivy.xml +++ b/spring-webflow/ivy.xml @@ -28,6 +28,7 @@ + diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java index e86bbe0c..4271d784 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java @@ -25,6 +25,8 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.js.mvc.servlet.AjaxHandler; +import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import org.springframework.web.servlet.view.RedirectView; diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java index 80c12707..0f6b3d59 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java @@ -24,6 +24,8 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.js.mvc.servlet.AjaxHandler; +import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler; import org.springframework.web.context.support.WebApplicationObjectSupport; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ModelAndView; diff --git a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java index d14b86f1..66528911 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java @@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import org.easymock.EasyMock; +import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext;