Handle History back step in browser #PL-1897

This commit is contained in:
Yuriy Artamonov 2013-03-01 10:30:56 +00:00
parent ce4ed2aece
commit a6cb23b02a
8 changed files with 143 additions and 17 deletions

View File

@ -15,9 +15,9 @@ import com.vaadin.terminal.gwt.client.ValueMap;
/** /**
* Component for evaluate custom JavaScript from server * Component for evaluate custom JavaScript from server
* <p>$Id$</p>
* *
* @author artamonov * @author artamonov
* @version $Id$
*/ */
public class VScriptHost extends SimplePanel implements Paintable { public class VScriptHost extends SimplePanel implements Paintable {
public static final String COMMAND_PARAM_KEY = "command"; public static final String COMMAND_PARAM_KEY = "command";
@ -34,13 +34,28 @@ public class VScriptHost extends SimplePanel implements Paintable {
public static final String URL_PARAM_KEY = "url"; public static final String URL_PARAM_KEY = "url";
public static final String LOCALE_PARAM_KEY = "messages"; public static final String LOCALE_PARAM_KEY = "messages";
public static final String HISTORY_BACK_ACTION = "historyBackAction";
private boolean historyHandlerInitialized = false;
private ApplicationConnection client;
private String paintableId;
public VScriptHost() { public VScriptHost() {
getElement().getStyle().setDisplay(Style.Display.NONE); getElement().getStyle().setDisplay(Style.Display.NONE);
getElement().getStyle().setVisibility(Style.Visibility.HIDDEN); getElement().getStyle().setVisibility(Style.Visibility.HIDDEN);
} }
@Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
String paintableId = uidl.getId(); this.client = client;
this.paintableId = uidl.getId();
if (client.getConfiguration().isHandleHistoryBack() && !historyHandlerInitialized) {
initHistoryHandler();
historyHandlerInitialized = true;
}
this.getElement().setId("scriptHost_" + paintableId); this.getElement().setId("scriptHost_" + paintableId);
@ -66,6 +81,12 @@ public class VScriptHost extends SimplePanel implements Paintable {
} }
} }
public void handleHistoryBackAction() {
if (historyHandlerInitialized) {
client.updateVariable(paintableId, HISTORY_BACK_ACTION, "performed", true);
}
}
private native void evaluateScript(String script)/*-{ private native void evaluateScript(String script)/*-{
eval(script); eval(script);
}-*/; }-*/;
@ -80,4 +101,34 @@ public class VScriptHost extends SimplePanel implements Paintable {
}; };
setTimeout(timedAction, 50); setTimeout(timedAction, 50);
}-*/; }-*/;
}
private native void initHistoryHandler()
/*-{
var vScriptHost = this;
(function(window){
var History = window.History;
var location = window.location.href;
var defaultState = 0;
if (location.indexOf('?wv') >= 0) {
History.pushState({state: 1, rand: 1}, window.document.title, '?vw');
defaultState = 1;
} else {
History.pushState({state: 2, rand: 2}, window.document.title, '?wv');
defaultState = 2;
}
History.Adapter.bind(window, 'statechange', function () {
var State = History.getState();
if (!State.data || State.data.state != defaultState) {
History.go(1);
vScriptHost.@com.haulmont.cuba.toolkit.gwt.client.utils.VScriptHost::handleHistoryBackAction()();
}
});
})($wnd);
}-*/;
}

View File

@ -63,6 +63,8 @@ public class ApplicationConfiguration implements EntryPoint {
private String blockUiMessage = "Please wait"; private String blockUiMessage = "Please wait";
private boolean useUiBlocking = false; private boolean useUiBlocking = false;
private boolean handleHistoryBack = false;
private String requiredWidgetset; private String requiredWidgetset;
private boolean useDebugIdInDom = true; private boolean useDebugIdInDom = true;
private boolean usePortletURLs = false; private boolean usePortletURLs = false;
@ -123,7 +125,7 @@ public class ApplicationConfiguration implements EntryPoint {
*/ */
public void updateSystemMessages(ValueMap localeMessages) { public void updateSystemMessages(ValueMap localeMessages) {
if (!localeMessages.getKeySet().isEmpty()) { if (!localeMessages.getKeySet().isEmpty()) {
// Update all system messages // Update all system messages handleHistoryBack
communicationErrorCaption = localeMessages.getString("communicationErrorCaption"); communicationErrorCaption = localeMessages.getString("communicationErrorCaption");
communicationErrorMessage = localeMessages.getString("communicationErrorMessage"); communicationErrorMessage = localeMessages.getString("communicationErrorMessage");
@ -190,6 +192,14 @@ public class ApplicationConfiguration implements EntryPoint {
return useUiBlocking; return useUiBlocking;
} }
public boolean isHandleHistoryBack() {
return handleHistoryBack;
}
public void setHandleHistoryBack(boolean handleHistoryBack) {
this.handleHistoryBack = handleHistoryBack;
}
private native void loadFromDOM() private native void loadFromDOM()
/*-{ /*-{
@ -203,6 +213,7 @@ public class ApplicationConfiguration implements EntryPoint {
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::appUri = uri; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::appUri = uri;
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::themeUri = jsobj.themeUri; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::themeUri = jsobj.themeUri;
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::sessionId = jsobj.sessionId; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::sessionId = jsobj.sessionId;
if(jsobj.windowName) { if(jsobj.windowName) {
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::windowName = jsobj.windowName; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::windowName = jsobj.windowName;
} }
@ -226,6 +237,9 @@ public class ApplicationConfiguration implements EntryPoint {
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::useUiBlocking = jsobj.uiBlocking.useUiBlocking; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::useUiBlocking = jsobj.uiBlocking.useUiBlocking;
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::blockUiMessage = jsobj.uiBlocking.blockUiMessage; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::blockUiMessage = jsobj.uiBlocking.blockUiMessage;
} }
if (jsobj.handleHistoryBack) {
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::handleHistoryBack = jsobj.handleHistoryBack;
}
if (jsobj.usePortletURLs) { if (jsobj.usePortletURLs) {
this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::usePortletURLs = jsobj.usePortletURLs; this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::usePortletURLs = jsobj.usePortletURLs;
} }

View File

@ -51,7 +51,7 @@ import java.util.*;
* @version $Id$ * @version $Id$
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class AppWindow extends Window implements UserSubstitutionListener { public class AppWindow extends Window implements UserSubstitutionListener, JavaScriptHost.HistoryBackHandler {
private static final long serialVersionUID = 7269808125566032433L; private static final long serialVersionUID = 7269808125566032433L;
@ -165,9 +165,17 @@ public class AppWindow extends Window implements UserSubstitutionListener {
private void initStaticComponents() { private void initStaticComponents() {
scriptHost = new JavaScriptHost(); scriptHost = new JavaScriptHost();
if (webConfig.getAllowHandleBrowserHistoryBack()) {
scriptHost.setHistoryBackHandler(this);
}
addComponent(scriptHost); addComponent(scriptHost);
} }
@Override
public void onHistoryBackPerformed() {
showNotification("Go back to the Future!", Notification.TYPE_HUMANIZED_MESSAGE);
}
/** /**
* @return Current mode * @return Current mode
*/ */

View File

@ -217,6 +217,13 @@ public interface WebConfig extends Config {
@DefaultBoolean(true) @DefaultBoolean(true)
boolean getUseUiBlocking(); boolean getUseUiBlocking();
/**
* @return Whether to handle back button click in browser on server-side.
*/
@Property("cuba.web.getAllowHandleBrowserHistoryBack")
@DefaultBoolean(true)
boolean getAllowHandleBrowserHistoryBack();
/** /**
* @return Theme * @return Theme
*/ */

View File

@ -2,16 +2,12 @@
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved. * Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential. * Haulmont Technology proprietary and confidential.
* Use is subject to license terms. * Use is subject to license terms.
* Author: Nikolay Gorodnov
* Created: 27.08.2009 18:39:09
*
* $Id$
*/ */
package com.haulmont.cuba.web.sys; package com.haulmont.cuba.web.sys;
import com.haulmont.cuba.core.app.ServerInfoService; import com.haulmont.cuba.core.app.ServerInfoService;
import com.haulmont.cuba.core.global.ConfigProvider; import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.Configuration;
import com.haulmont.cuba.core.global.GlobalConfig; import com.haulmont.cuba.core.global.GlobalConfig;
import com.haulmont.cuba.gui.ServiceLocator; import com.haulmont.cuba.gui.ServiceLocator;
import com.haulmont.cuba.web.App; import com.haulmont.cuba.web.App;
@ -25,6 +21,7 @@ import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -38,6 +35,10 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
/**
* @author gorodnov
* @version $Id$
*/
public class CubaApplicationServlet extends ApplicationServlet { public class CubaApplicationServlet extends ApplicationServlet {
private static final long serialVersionUID = -8701539520754293569L; private static final long serialVersionUID = -8701539520754293569L;
@ -45,9 +46,13 @@ public class CubaApplicationServlet extends ApplicationServlet {
private Log log = LogFactory.getLog(CubaApplicationServlet.class); private Log log = LogFactory.getLog(CubaApplicationServlet.class);
private WebConfig webConfig;
private GlobalConfig globalConfig;
@Override @Override
protected boolean isTestingMode() { protected boolean isTestingMode() {
return ConfigProvider.getConfig(GlobalConfig.class).getTestMode(); return globalConfig.getTestMode();
} }
@Override @Override
@ -55,6 +60,15 @@ public class CubaApplicationServlet extends ApplicationServlet {
return CubaApplicationContext.getApplicationContext(session); return CubaApplicationContext.getApplicationContext(session);
} }
@Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
Configuration configuration = AppBeans.get(Configuration.class);
webConfig = configuration.getConfig(WebConfig.class);
globalConfig = configuration.getConfig(GlobalConfig.class);
}
@Override @Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI(); String requestURI = request.getRequestURI();
@ -249,7 +263,9 @@ public class CubaApplicationServlet extends ApplicationServlet {
page.write("useDebugIdInDom: true,\n"); page.write("useDebugIdInDom: true,\n");
} }
WebConfig webConfig = ConfigProvider.getConfig(WebConfig.class); if (webConfig.getAllowHandleBrowserHistoryBack())
page.write("handleHistoryBack: true,\n");
page.write("\n\"uiBlocking\" : {"); page.write("\n\"uiBlocking\" : {");
page.write(" \"blockUiMessage\" : \"" + systemMessages.getUiBlockingMessage() + "\" ,"); page.write(" \"blockUiMessage\" : \"" + systemMessages.getUiBlockingMessage() + "\" ,");
page.write(" \"useUiBlocking\" : " + page.write(" \"useUiBlocking\" : " +
@ -296,7 +312,7 @@ public class CubaApplicationServlet extends ApplicationServlet {
protected void writeAjaxPageHtmlHeader(HttpServletRequest request, BufferedWriter page, String title, protected void writeAjaxPageHtmlHeader(HttpServletRequest request, BufferedWriter page, String title,
String themeUri) throws IOException { String themeUri) throws IOException {
page.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"); page.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n");
if (ConfigProvider.getConfig(WebConfig.class).getUseChromeFramePlugin() if (webConfig.getUseChromeFramePlugin()
&& Browser.getBrowserInfo(request).isChromeFrame()) { && Browser.getBrowserInfo(request).isChromeFrame()) {
page.write("<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n"); page.write("<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\" />\n");
/* /*
@ -319,6 +335,12 @@ public class CubaApplicationServlet extends ApplicationServlet {
writeScriptResource(request, page, "jquery-1.4.2.min.js", false); writeScriptResource(request, page, "jquery-1.4.2.min.js", false);
writeScriptResource(request, page, "jquery.blockUI.js", false); writeScriptResource(request, page, "jquery.blockUI.js", false);
writeScriptResource(request, page, "scripts.js", true); writeScriptResource(request, page, "scripts.js", true);
// history control
if (webConfig.getAllowHandleBrowserHistoryBack()) {
writeScriptResource(request, page, "jquery.history.js", false);
writeScriptResource(request, page, "json2.js", false);
}
} }
private void writeScriptResource(HttpServletRequest request, BufferedWriter page, String fileName, boolean nocache) throws IOException { private void writeScriptResource(HttpServletRequest request, BufferedWriter page, String fileName, boolean nocache) throws IOException {

View File

@ -19,9 +19,9 @@ import java.util.Set;
/** /**
* Component for evaluate custom JavaScript from server * Component for evaluate custom JavaScript from server
* <p>$Id$</p>
* *
* @author artamonov * @author artamonov
* @version $Id$
*/ */
@ClientWidget(VScriptHost.class) @ClientWidget(VScriptHost.class)
public class JavaScriptHost extends AbstractComponent { public class JavaScriptHost extends AbstractComponent {
@ -29,12 +29,14 @@ public class JavaScriptHost extends AbstractComponent {
private static class ScriptValueProvider implements ValueProvider { private static class ScriptValueProvider implements ValueProvider {
Map<String, Object> params = new HashMap<String, Object>(); Map<String, Object> params = new HashMap<>();
@Override
public Map<String, Object> getValues() { public Map<String, Object> getValues() {
return params; return params;
} }
@Override
public Map<String, Object> getParameters() { public Map<String, Object> getParameters() {
return params; return params;
} }
@ -54,7 +56,15 @@ public class JavaScriptHost extends AbstractComponent {
private ScriptValueProvider valueProvider = new ScriptValueProvider(); private ScriptValueProvider valueProvider = new ScriptValueProvider();
public JavaScriptHost() { private HistoryBackHandler historyBackHandler = null;
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
super.changeVariables(source, variables);
if (variables.containsKey(VScriptHost.HISTORY_BACK_ACTION) && historyBackHandler != null) {
historyBackHandler.onHistoryBackPerformed();
}
} }
@Override @Override
@ -114,4 +124,16 @@ public class JavaScriptHost extends AbstractComponent {
valueProvider.removeParam(VScriptHost.SCRIPT_PARAM_KEY); valueProvider.removeParam(VScriptHost.SCRIPT_PARAM_KEY);
valueProvider.removeParam(VScriptHost.COMMAND_PARAM_KEY); valueProvider.removeParam(VScriptHost.COMMAND_PARAM_KEY);
} }
public HistoryBackHandler getHistoryBackHandler() {
return historyBackHandler;
}
public void setHistoryBackHandler(HistoryBackHandler historyBackHandler) {
this.historyBackHandler = historyBackHandler;
}
public interface HistoryBackHandler {
void onHistoryBackPerformed();
}
} }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
window.JSON||(window.JSON={}),function(){function f(a){return a<10?"0"+a:a}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";return e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g,e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)d=rep[c],typeof d=="string"&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));return e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g,e}}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var JSON=window.JSON,cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),typeof reviver=="function"?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}()