diff --git a/spring-js/src/main/java/org/springframework/js/ajax/AjaxRedirectView.java b/spring-js/src/main/java/org/springframework/js/ajax/AjaxRedirectView.java new file mode 100644 index 00000000..4687ccfc --- /dev/null +++ b/spring-js/src/main/java/org/springframework/js/ajax/AjaxRedirectView.java @@ -0,0 +1,31 @@ +package org.springframework.js.ajax; + +import java.io.IOException; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.support.RequestContextUtils; +import org.springframework.web.servlet.view.RedirectView; + +public class AjaxRedirectView extends RedirectView implements View { + + private AjaxHandler ajaxHandler = new SpringJavascriptAjaxHandler(); + + public AjaxRedirectView(String redirectUrl, boolean redirectContextRelative, boolean redirectHttp10Compatible) { + super(redirectUrl, redirectContextRelative, redirectHttp10Compatible); + } + + protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String targetUrl, + boolean http10Compatible) throws IOException { + ServletContext context = RequestContextUtils.getWebApplicationContext(request).getServletContext(); + if (ajaxHandler.isAjaxRequest(context, request, response)) { + ajaxHandler.sendAjaxRedirect(context, request, response, targetUrl, false); + } else { + super.sendRedirect(request, response, targetUrl, http10Compatible); + } + } + +} diff --git a/spring-js/src/main/java/org/springframework/js/ajax/AjaxUrlBasedViewResolver.java b/spring-js/src/main/java/org/springframework/js/ajax/AjaxUrlBasedViewResolver.java new file mode 100644 index 00000000..8ac873bc --- /dev/null +++ b/spring-js/src/main/java/org/springframework/js/ajax/AjaxUrlBasedViewResolver.java @@ -0,0 +1,28 @@ +package org.springframework.js.ajax; + +import java.util.Locale; + +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.view.UrlBasedViewResolver; + +public class AjaxUrlBasedViewResolver extends UrlBasedViewResolver { + + /** + * Overridden to implement check for "redirect:" prefix. + *

+ * Redirect requires special behavior on an Ajax request. + */ + protected View createView(String viewName, Locale locale) throws Exception { + // If this resolver is not supposed to handle the given view, + // return null to pass on to the next resolver in the chain. + if (!canHandle(viewName, locale)) { + return null; + } + // Check for special "redirect:" prefix. + if (viewName.startsWith(REDIRECT_URL_PREFIX)) { + String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length()); + return new AjaxRedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible()); + } + return super.createView(viewName, locale); + } +} diff --git a/spring-js/src/main/java/org/springframework/js/ajax/tiles2/AjaxTilesView.java b/spring-js/src/main/java/org/springframework/js/ajax/tiles2/AjaxTilesView.java index 9fdd9377..69989f0c 100644 --- a/spring-js/src/main/java/org/springframework/js/ajax/tiles2/AjaxTilesView.java +++ b/spring-js/src/main/java/org/springframework/js/ajax/tiles2/AjaxTilesView.java @@ -17,13 +17,14 @@ import org.apache.tiles.context.TilesRequestContext; import org.apache.tiles.impl.BasicTilesContainer; import org.springframework.js.ajax.AjaxHandler; import org.springframework.js.ajax.SpringJavascriptAjaxHandler; +import org.springframework.util.StringUtils; import org.springframework.web.servlet.support.JstlUtils; import org.springframework.web.servlet.support.RequestContext; import org.springframework.web.servlet.view.tiles2.TilesView; public class AjaxTilesView extends TilesView { - public static final String FRAGMENTS_PARAM = "fragments"; + private static final String FRAGMENTS_PARAM = "fragments"; private AjaxHandler ajaxHandler = new SpringJavascriptAjaxHandler(); @@ -48,16 +49,22 @@ public class AjaxTilesView extends TilesView { 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 }); + String[] attrNames = getRenderFragments(model, request, response); + response.flushBuffer(); + for (int i = 0; i < attrNames.length; i++) { + Attribute attributeToRender = (Attribute) flattenedAttributeMap.get(attrNames[i]); + container.render(attributeToRender, response.getWriter(), new Object[] { request, response }); + } } else { super.renderMergedOutputModel(model, request, response); } } + protected String[] getRenderFragments(Map model, HttpServletRequest request, HttpServletResponse response) { + String attrName = request.getParameter(FRAGMENTS_PARAM); + return StringUtils.commaDelimitedListToStringArray(attrName); + } + private void flattenAttributeMap(BasicTilesContainer container, TilesRequestContext requestContext, Map resultMap, Definition compositeDefinition) throws Exception { Iterator i = compositeDefinition.getAttributes().keySet().iterator(); 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 733bf158..33bcfd33 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. */ -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 +dojo.declare("Spring.DefaultEquals",null,{equals:function(_1){if(_1.declaredClass&&_1.declaredClass==this.declaredClass){return true;}else{return false;}}});dojo.declare("Spring.ElementDecoration",[Spring.AbstractElementDecoration,Spring.DefaultEquals],{constructor:function(_2){this.copyFields=new Array("name","value","type","checked","selected","readOnly","disabled","alt","maxLength");dojo.mixin(this,_2);if(this.widgetModule==""){this.widgetModule=this.widgetType;}},apply:function(){if(dijit.byId(this.elementId)){dijit.byId(this.elementId).destroyRecursive(false);}var _3=dojo.byId(this.elementId);if(!_3){console.error("Could not apply "+this.widgetType+" decoration. Element with id '"+this.elementId+"' not found in the DOM.");}else{for(var _4 in this.copyFields){_4=this.copyFields[_4];if(!this.widgetAttrs[_4]&&_3[_4]&&(typeof _3[_4]!="number"||(typeof _3[_4]=="number"&&_3[_4]>=0))){this.widgetAttrs[_4]=_3[_4];}}dojo.require(this.widgetModule);var _5=dojo.eval(this.widgetType);this.widget=new _5(this.widgetAttrs,_3);this.widget.startup();}return this;},validate:function(){if(!this.widget.isValid){return true;}var _6=this.widget.isValid(false);if(!_6){this.widget.state="Error";this.widget._setStateClass();}return _6;}});dojo.declare("Spring.ValidateAllDecoration",[Spring.AbstractValidateAllDecoration,Spring.DefaultEquals],{constructor:function(_7){this.originalHandler=null;this.connection=null;dojo.mixin(this,_7);},apply:function(){var _8=dojo.byId(this.elementId);this.originalHandler=_8[this.event];var _9=this;_8[this.event]=function(_a){_9.handleEvent(_a,_9);};return this;},cleanup:function(){dojo.disconnect(this.connection);},handleEvent:function(_b,_c){if(!Spring.validateAll()){dojo.stopEvent(_b);}else{if(dojo.isFunction(_c.originalHandler)){var _d=_c.originalHandler(_b);if(_d==false){dojo.stopEvent(_b);}}}}});dojo.declare("Spring.AjaxEventDecoration",[Spring.AbstractAjaxEventDecoration,Spring.DefaultEquals],{constructor:function(_e){this.connection=null;dojo.mixin(this,_e);},apply:function(){this.connection=dojo.connect(dojo.byId(this.elementId),this.event,this,"submit");return this;},cleanup:function(){dojo.disconnect(this.connection);},submit:function(_f){if(this.sourceId==""){this.sourceId=this.elementId;}if(this.formId==""){Spring.remoting.getLinkedResource(this.sourceId,this.params,this.popup);}else{Spring.remoting.submitForm(this.sourceId,this.formId,this.params);}dojo.stopEvent(_f);}});dojo.declare("Spring.RemotingHandler",Spring.AbstractRemotingHandler,{constructor:function(){},submitForm:function(_10,_11,_12){var _13=new Object();for(var key in _12){_13[key]=_12[key];}var _15=dojo.byId(_10);if(_15!=null){if(_15.value!=undefined&&_15.type&&("button,submit,reset").indexOf(_15.type)<0){_13[_10]=_15.value;}else{if(_15.name!=undefined){_13[_15.name]=_15.name;}else{_13[_10]=_10;}}}if(!_13["ajaxSource"]){_13["ajaxSource"]=_10;}dojo.xhrPost({content:_13,form:_11,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError});},getLinkedResource:function(_16,_17,_18){this.getResource(dojo.byId(_16).href,_17,_18);},getResource:function(_19,_1a,_1b){dojo.xhrGet({url:_19,content:_1a,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError,modal:_1b});},handleResponse:function(_1c,_1d){var _1e=_1d.xhr.getResponseHeader("Spring-Redirect-URL");var _1f=_1d.xhr.getResponseHeader("Spring-Modal-View");var _20=((dojo.isString(_1f)&&_1f.length>0)||_1d.args.modal);if(dojo.isString(_1e)&&_1e.length>0){if(_20){Spring.remoting.renderURLToModalDialog(_1e,_1d);return _1c;}else{if(_1e.indexOf("/")>=0){window.location=window.location.protocol+"//"+window.location.host+_1e;}else{var _21=window.location.protocol+"//"+window.location.host+window.location.pathname;var _22=_21.lastIndexOf("/");_21=_21.substr(0,_22+1)+_1e;if(_21==window.location){Spring.remoting.getResource(_21,_1d.args.content,false);}else{window.location=_21;}}return _1c;}}var _23="(?:)((\n|\r|.)*?)(?:)";var _24=[];var _25=new RegExp(_23,"img");var _26=new RegExp(_23,"im");var _27=_1c.match(_25);if(_27!=null){for(var i=0;i<_27.length;i++){var _29=(_27[i].match(_26)||["",""])[1];_29=_29.replace(//mg,"");_24.push(_29);}}_1c=_1c.replace(_25,"");var _2a=dojo.doc.createElement("div");_2a.id="ajaxResponse";_2a.style.visibility="hidden";document.body.appendChild(_2a);var _2b=new dojo.NodeList(_2a);var _2c=_2b.addContent(_1c,"first").query("#ajaxResponse > *").orphan();_2b.orphan();if(_20){Spring.remoting.renderNodeListToModalDialog(_2c);}else{_2c.forEach(function(_2d){if(_2d.id!=null&&_2d.id!=""){var _2e=dojo.byId(_2d.id);if(!_2e){console.error("An existing DOM elment with id '"+_2d.id+"' could not be found for replacement.");}else{_2e.parentNode.replaceChild(_2d,_2e);}}});}dojo.forEach(_24,function(_2f){dojo.eval(_2f);});return _1c;},handleError:function(_30,_31){console.error("HTTP status code: ",_31.xhr.status);return _30;},renderURLToModalDialog:function(url,_33){url=url+"&"+dojo.objectToQuery(_33.args.content);Spring.remoting.getResource(url,{},true);},renderNodeListToModalDialog:function(_34){dojo.require("dijit.Dialog");var _35=new dijit.Dialog({});_35.setContent(_34);dojo.connect(_35,"hide",_35,function(){this.destroyRecursive(false);});_35.show();}});dojo.declare("Spring.CommandLinkDecoration",[Spring.AbstractCommandLinkDecoration,Spring.DefaultEquals],{constructor:function(_36){dojo.mixin(this,_36);},apply:function(){var _37=dojo.byId(this.elementId);if(!dojo.hasClass(_37,"progressiveLink")){var _38=new dojo.NodeList(_37);_38.addContent(this.linkHtml,"after").orphan("*");_37=dojo.byId(this.elementId);}_37.submitFormFromLink=this.submitFormFromLink;return this;},submitFormFromLink:function(_39,_3a,_3b){var _3c=[];var _3d=dojo.byId(_39);var _3e=document.createElement("input");_3e.name=_3a;_3e.value="submitted";_3c.push(_3e);dojo.forEach(_3b,function(_3f){var _40=document.createElement("input");_40.name=_3f.name;_40.value=_3f.value;_3c.push(_40);});dojo.forEach(_3c,function(_41){dojo.addClass(_41,"SpringLinkInput");dojo.place(_41,_3d,"last");});if((_3d.onsubmit?!_3d.onsubmit():false)||!_3d.submit()){dojo.forEach(_3c,function(_42){_3d.removeChild(_42);});}}});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 f39af88c..67a97ae9 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,8 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +dojo.declare("Spring.DefaultEquals", null, { + equals : function(/*Object*/other){ + if (other.declaredClass && other.declaredClass == this.declaredClass) { + return true; + }else{ + return false; + } + } +}); -dojo.declare("Spring.ElementDecoration", Spring.AbstractElementDecoration, { +dojo.declare("Spring.ElementDecoration", [Spring.AbstractElementDecoration, Spring.DefaultEquals], { constructor : function(config) { this.copyFields = new Array('name', 'value', 'type', 'checked', 'selected', 'readOnly', 'disabled', 'alt', 'maxLength'); dojo.mixin(this, config); @@ -28,17 +37,23 @@ dojo.declare("Spring.ElementDecoration", Spring.AbstractElementDecoration, { 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]; - } + if (!element) { + console.error("Could not apply " + this.widgetType + " decoration. Element with id '" + this.elementId + "' not found in the DOM."); + } + else { + 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(); } - 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; }, @@ -54,10 +69,10 @@ dojo.declare("Spring.ElementDecoration", Spring.AbstractElementDecoration, { this.widget._setStateClass(); } return isValid; - } + } }); -dojo.declare("Spring.ValidateAllDecoration", Spring.AbstractValidateAllDecoration, { +dojo.declare("Spring.ValidateAllDecoration", [Spring.AbstractValidateAllDecoration, Spring.DefaultEquals], { constructor : function(config) { this.originalHandler = null; this.connection = null; @@ -90,7 +105,7 @@ dojo.declare("Spring.ValidateAllDecoration", Spring.AbstractValidateAllDecoratio } }); -dojo.declare("Spring.AjaxEventDecoration", Spring.AbstractAjaxEventDecoration, { +dojo.declare("Spring.AjaxEventDecoration", [Spring.AbstractAjaxEventDecoration, Spring.DefaultEquals], { constructor : function(config){ this.connection = null; dojo.mixin(this, config); @@ -110,7 +125,7 @@ dojo.declare("Spring.AjaxEventDecoration", Spring.AbstractAjaxEventDecoration, { this.sourceId = this.elementId; } if(this.formId == ""){ - Spring.remoting.getLinkedResource(this.sourceId, this.params, false); + Spring.remoting.getLinkedResource(this.sourceId, this.params, this.popup); } else { Spring.remoting.submitForm(this.sourceId, this.formId, this.params); } @@ -130,8 +145,11 @@ dojo.declare("Spring.RemotingHandler", Spring.AbstractRemotingHandler, { var sourceComponent = dojo.byId(sourceId); if (sourceComponent != null){ - if(sourceComponent.value != undefined) { - content[sourceId] = sourceComponent.value; + if(sourceComponent.value != undefined && sourceComponent.type && ("button,submit,reset").indexOf(sourceComponent.type) < 0) { + content[sourceId] = sourceComponent.value; + } + else if(sourceComponent.name != undefined) { + content[sourceComponent.name] = sourceComponent.name; } else { content[sourceId] = sourceId; } @@ -198,7 +216,19 @@ dojo.declare("Spring.RemotingHandler", Spring.AbstractRemotingHandler, { return response; } else { - window.location = window.location.protocol + "//" + window.location.host + redirectURL; + if (redirectURL.indexOf("/") >= 0) { + window.location = window.location.protocol + "//" + window.location.host + redirectURL; + } else { + var location = window.location.protocol + "//" + window.location.host + window.location.pathname; + var appendIndex = location.lastIndexOf("/"); + location = location.substr(0,appendIndex+1) + redirectURL; + if (location == window.location) { + Spring.remoting.getResource(location, ioArgs.args.content, false); + } + else { + window.location = location; + } + } return response; } } @@ -240,7 +270,11 @@ dojo.declare("Spring.RemotingHandler", Spring.AbstractRemotingHandler, { newNodes.forEach(function(item){ if (item.id != null && item.id != "") { var target = dojo.byId(item.id); - target.parentNode.replaceChild(item, target); + if (!target) { + console.error("An existing DOM elment with id '" + item.id + "' could not be found for replacement."); + } else { + target.parentNode.replaceChild(item, target); + } } }); } @@ -276,7 +310,7 @@ dojo.declare("Spring.RemotingHandler", Spring.AbstractRemotingHandler, { } }); -dojo.declare("Spring.CommandLinkDecoration", Spring.AbstractCommandLinkDecoration, { +dojo.declare("Spring.CommandLinkDecoration", [Spring.AbstractCommandLinkDecoration, Spring.DefaultEquals], { constructor : function(config){ dojo.mixin(this, config); }, 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 633368de..45f4c9d9 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.decorations=[];Spring.decorations.applied=false;Spring.initialize=function(){Spring.applyDecorations();Spring.remoting=new Spring.RemotingHandler();};Spring.addDecoration=function(_1){Spring.decorations.push(_1);if(Spring.decorations.applied){_1.apply();}};Spring.applyDecorations=function(){if(!Spring.decorations.applied){for(var x=0;x - + + + diff --git a/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/HotelsController.java b/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/HotelsController.java index 3d12b38b..ff5e5956 100644 --- a/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/HotelsController.java +++ b/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/HotelsController.java @@ -37,12 +37,14 @@ public class HotelsController { } @RequestMapping(method = RequestMethod.GET) - public Hotel show(@RequestParam("id") Long id) { + public Hotel show(@RequestParam("id") + Long id) { return bookingService.findHotelById(id); } @RequestMapping(method = RequestMethod.GET) - public String deleteBooking(@RequestParam("id") Long id) { + public String deleteBooking(@RequestParam("id") + Long id) { bookingService.cancelBooking(id); return "redirect:index"; } diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/config/webmvc-config.xml b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/config/webmvc-config.xml index 4a9bdcc5..12a6c5d0 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/config/webmvc-config.xml +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/config/webmvc-config.xml @@ -45,8 +45,8 @@ - - + + diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/bookingForm.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/bookingForm.jsp new file mode 100644 index 00000000..aa4ab1ea --- /dev/null +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/bookingForm.jsp @@ -0,0 +1,160 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + +

+
+
Name:
+
${booking.hotel.name}
+
+
+
Address:
+
${booking.hotel.address}
+
+
+
City, State:
+
${booking.hotel.city}, ${booking.hotel.state}
+
+
+
Zip:
+
${booking.hotel.zip}
+
+
+
Country:
+
${booking.hotel.country}
+
+
+
Nightly rate:
+
+ ${status.value} +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + + + + +
+
+
+
+ Smoking Preference: +
+
+ + + + +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+   + +   + +
+
+ \ No newline at end of file diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/enterBookingDetails.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/enterBookingDetails.jsp index 840629cb..2e9eae23 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/enterBookingDetails.jsp +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/enterBookingDetails.jsp @@ -1,165 +1,13 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> -
+

Book Hotel

-
- - -
-
-
Name:
-
${booking.hotel.name}
-
-
-
Address:
-
${booking.hotel.address}
-
-
-
City, State:
-
${booking.hotel.city}, ${booking.hotel.state}
-
-
-
Zip:
-
${booking.hotel.zip}
-
-
-
Country:
-
${booking.hotel.country}
-
-
-
Nightly rate:
-
- ${status.value} -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - - - - -
-
-
-
- Smoking Preference: -
-
- - - - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - -
-
-
-   -   - -
-
-
+
+ +
diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/messages.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/messages.jsp new file mode 100644 index 00000000..f414f2ae --- /dev/null +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/messages.jsp @@ -0,0 +1,4 @@ +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +
+ +
\ No newline at end of file diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/views.xml b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/views.xml index 88f2facc..023f6a3c 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/views.xml +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/booking/views.xml @@ -6,7 +6,11 @@ - + + + + + diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/bookingsTable.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/bookingsTable.jsp new file mode 100644 index 00000000..a4c6eff9 --- /dev/null +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/bookingsTable.jsp @@ -0,0 +1,53 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> + +
+ +

Current Hotel Bookings

+ + + + No bookings found + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameAddressCity, StateCheck in DateCheck out DateConfirmation NumberAction
${booking.hotel.name}${booking.hotel.address}${booking.hotel.city}, ${booking.hotel.state}${booking.checkinDate}${booking.checkoutDate}${booking.id} + Cancel + +
+
+
+ +
\ No newline at end of file diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/hotelResults.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/hotelResults.jsp deleted file mode 100644 index 83e040f9..00000000 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/hotelResults.jsp +++ /dev/null @@ -1,56 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameAddressCity, StateZipAction
${hotel.name}${hotel.address}${hotel.city}, ${hotel.state}, ${hotel.country}${hotel.zip}View Hotel
No hotels found
-
- - Previous Results - - - - More Results - - -
-
-
\ No newline at end of file diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/hotelSearchForm.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/hotelSearchForm.jsp new file mode 100644 index 00000000..a84866a9 --- /dev/null +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/hotelSearchForm.jsp @@ -0,0 +1,41 @@ +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + +
+ + + +

Search Hotels

+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + + + + +
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/index.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/index.jsp index 5b974f14..6c11411f 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/index.jsp +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/index.jsp @@ -1,87 +1,5 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> -<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> -<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> +<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> - -
- - - -

Search Hotels

-
-
-
- -
-
- - -
-
-
-
- -
-
- - - - - -
-
-
- -
-
-
-
+ - -
-

Current Hotel Bookings

- - - - No bookings found - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameAddressCity, StateCheck in DateCheck out DateConfirmation NumberAction
${booking.hotel.name}${booking.hotel.address}${booking.hotel.city}, ${booking.hotel.state}${booking.checkinDate}${booking.checkoutDate}${booking.id} - Cancel -
-
- -
-
\ No newline at end of file + diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/search.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/search.jsp index f1f2eb99..93c0571b 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/search.jsp +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/search.jsp @@ -1,8 +1,72 @@ <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

Hotel Results

- - +

+Change Search + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameAddressCity, StateZipAction
${hotel.name}${hotel.address}${hotel.city}, ${hotel.state}, ${hotel.country}${hotel.zip}View Hotel
No hotels found
+
+ + Previous Results + + + + More Results + + +
+
+
diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/views.xml b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/views.xml index 78142c4f..cb4e1b20 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/views.xml +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/hotels/views.xml @@ -6,17 +6,17 @@ - + + + + + - + - - - - diff --git a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/layouts/standard.jsp b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/layouts/standard.jsp index 9ee281a2..fb082982 100644 --- a/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/layouts/standard.jsp +++ b/spring-webflow-samples/booking-mvc/src/main/webapp/WEB-INF/layouts/standard.jsp @@ -7,6 +7,7 @@ Spring Travel: Spring MVC and Web Flow Reference Application + " /> - + - " />
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTilesView.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTilesView.java new file mode 100644 index 00000000..3038d6f5 --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTilesView.java @@ -0,0 +1,43 @@ +/* + * Copyright 2004-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.webflow.mvc.view; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.js.ajax.tiles2.AjaxTilesView; +import org.springframework.webflow.execution.RequestContext; +import org.springframework.webflow.execution.RequestContextHolder; +import org.springframework.webflow.execution.View; + +public class FlowAjaxTilesView extends AjaxTilesView { + + protected String[] getRenderFragments(Map model, HttpServletRequest request, HttpServletResponse response) { + RequestContext context = RequestContextHolder.getRequestContext(); + if (context == null) { + return super.getRenderFragments(model, request, response); + } else { + String[] fragments = (String[]) context.getFlashScope().get(View.RENDER_FRAGMENTS_ATTRIBUTE); + if (fragments == null) { + return super.getRenderFragments(model, request, response); + } + return fragments; + } + } + +} \ No newline at end of file