diff --git a/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js b/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js index b76da745..54dee8ca 100644 --- a/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js +++ b/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js @@ -104,6 +104,23 @@ SpringFaces.DojoAjaxHandler.prototype = { handleResponse: function(response, ioArgs) { //alert("handling the response"); + //First check if this response should redirect + var redirectURL = ioArgs.xhr.getResponseHeader('Flow-Redirect-URL'); + var modalViewHeader = ioArgs.xhr.getResponseHeader('Flow-Modal-View'); + var modalView = dojo.isString(modalViewHeader) && modalViewHeader.length > 0; + + if (dojo.isString(redirectURL) && redirectURL.length > 0) { + if (modalView) { + //render a popup with the new URL + SpringFaces.AjaxHandler.renderURLToModalDialog(redirectURL, ioArgs); + return response; + } + else { + window.location.pathname = redirectURL; + return response; + } + } + //Extract and store all -
-
-
\ No newline at end of file diff --git a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml index 068f9c36..b8084dff 100755 --- a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml +++ b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml @@ -33,7 +33,7 @@
- +
diff --git a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml index 694b5231..125ad4f3 100755 --- a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml +++ b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml @@ -25,7 +25,12 @@ - + + + + + + diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java index 57a2d0b6..610d435d 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java @@ -35,6 +35,7 @@ import org.springframework.webflow.core.collection.SharedAttributeMap; * * @author Keith Donald * @author Erwin Vervaet + * @author Jeremy Grelle */ public interface ExternalContext { @@ -205,4 +206,12 @@ public interface ExternalContext { */ public boolean isResponseCommitted(); + /** + * Returns true if the current request is an Ajax request, determined by the value of the http accept header. + * @return true if the current request is an Ajax request + */ + public boolean isAjaxRequest(); + + public void setResponseHeader(String name, String value); + } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java index 2b49b786..3f440996 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.style.ToStringCreator; +import org.springframework.util.StringUtils; import org.springframework.webflow.context.AbstractFlowRequestInfo; import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.context.ExternalContextHolder; @@ -49,12 +50,22 @@ import org.springframework.webflow.executor.FlowExecutor; * * @author Keith Donald * @author Erwin Vervaet + * @author Jeremy Grelle */ public class ServletExternalContext implements ExternalContext { /** The default encoding scheme: UTF-8 */ private static final String DEFAULT_ENCODING_SCHEME = "UTF-8"; + /** The accept header value that signifies an Ajax request */ + private static final String AJAX_ACCEPT_CONTENT_TYPE = "text/html;type=ajax"; + + /** Alternate request paramater to indicate an ajax request for cases when control of the header is not available */ + private static final String AJAX_SOURCE_PARAM = "ajaxSource"; + + /** The response header to be set on an Ajax redirect */ + private static final String FLOW_REDIRECT_URL_HEADER = "Flow-Redirect-URL"; + /** * The context. */ @@ -412,7 +423,11 @@ public class ServletExternalContext implements ExternalContext { } private void sendRedirect(String targetUrl) throws IOException { - response.sendRedirect(response.encodeRedirectURL(targetUrl)); + if (isAjaxRequest()) { + setResponseHeader(FLOW_REDIRECT_URL_HEADER, response.encodeRedirectURL(targetUrl)); + } else { + response.sendRedirect(response.encodeRedirectURL(targetUrl)); + } } public String toString() { @@ -446,7 +461,7 @@ public class ServletExternalContext implements ExternalContext { public void issueRedirect() throws IOException { FlowExecutionRequestInfo requestInfo = (FlowExecutionRequestInfo) getRequestInfo(); String targetUrl = buildFlowExecutionUrl(requestInfo, true); - response.sendRedirect(response.encodeRedirectURL(targetUrl)); + sendRedirect(targetUrl); } } @@ -458,7 +473,21 @@ public class ServletExternalContext implements ExternalContext { public void issueRedirect() throws IOException { FlowDefinitionRequestInfo requestInfo = (FlowDefinitionRequestInfo) getRequestInfo(); String targetUrl = buildFlowDefinitionUrl(requestInfo); - response.sendRedirect(response.encodeRedirectURL(targetUrl)); + sendRedirect(targetUrl); } } + + public boolean isAjaxRequest() { + String acceptHeader = request.getHeader("Accept"); + String ajaxParam = request.getParameter(AJAX_SOURCE_PARAM); + if (AJAX_ACCEPT_CONTENT_TYPE.equals(acceptHeader) || StringUtils.hasText(ajaxParam)) { + return true; + } else { + return false; + } + } + + public void setResponseHeader(String name, String value) { + response.setHeader(name, value); + } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java index e659f3d1..e2be964b 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java @@ -33,6 +33,10 @@ import org.springframework.webflow.execution.ViewFactory; */ public class ViewState extends TransitionableState { + private static final String FLOW_MODAL_VIEW_HEADER = "Flow-Modal-View"; + + private static final String MODAL_ATTR = "modal"; + /** * The list of actions to be executed when this state is entered. */ @@ -79,6 +83,10 @@ public class ViewState extends TransitionableState { protected void doEnter(RequestControlContext context) throws FlowExecutionException { context.assignFlowExecutionKey(); + if (context.getExternalContext().isAjaxRequest() + && Boolean.TRUE.equals(context.getCurrentState().getAttributes().getBoolean(MODAL_ATTR))) { + context.getExternalContext().setResponseHeader(FLOW_MODAL_VIEW_HEADER, "true"); + } if (shouldRedirect(context)) { context.sendFlowExecutionRedirect(); } else { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java index acb13306..06641fe8 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java @@ -17,6 +17,7 @@ package org.springframework.webflow.test; import java.io.PrintWriter; import java.util.HashMap; +import java.util.Map; import org.springframework.binding.collection.SharedMapDecorator; import org.springframework.webflow.context.ExternalContext; @@ -73,6 +74,10 @@ public class MockExternalContext implements ExternalContext { private FlowException exceptionResult; + private boolean ajaxRequest; + + private Map responseHeaders = new HashMap(); + /** * Creates a mock external context with an empty request parameter map. Allows for bean style usage. */ @@ -302,4 +307,20 @@ public class MockExternalContext implements ExternalContext { public FlowException getExceptionResult() { return exceptionResult; } + + public boolean isAjaxRequest() { + return ajaxRequest; + } + + public void setAjaxRequest(boolean ajaxRequest) { + this.ajaxRequest = ajaxRequest; + } + + public void setResponseHeader(String name, String value) { + this.responseHeaders.put(name, value); + } + + public String getResponseHeader(String name) { + return (String) responseHeaders.get(name); + } } \ No newline at end of file