package org.ocpsoft.rewrite.gwt.client.history; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.google.gwt.user.client.impl.HistoryImpl; /** * History implementation based on pushState */ public class HistoryStateImpl extends HistoryImpl { private static List<ContextPathProvider> providers = Arrays.asList(new CookieContextPathProvider(), new RequestContextPathProvider()); static String contextPath = null; private static List<ContextPathListener> listeners = new ArrayList<ContextPathListener>(); @Override public boolean init() { for (ContextPathProvider provider : providers) { provider.getContextPath(this); if (contextPath != null) { break; } } return initNative(); } static void setContextPath(String contextPath) { if (contextPath != null && !contextPath.endsWith("/")) { contextPath += "/"; } HistoryStateImpl.contextPath = contextPath; System.out.println("Set contextPath: " + contextPath); for (ContextPathListener listner : listeners) { listner.onContextPathSet(contextPath); } } public static ListenerRegistration addContextPathListener(final ContextPathListener listener) { listeners.add(listener); return new ListenerRegistration() { @Override public void removeListener() { listeners.remove(listener); } }; } public static String getContextPath() { return contextPath; } public static boolean isInitialized() { return contextPath != null; } public native boolean initNative() /*-{ var token = ''; var historyImpl = this; var path = $wnd.location.pathname; if (path.length > 0) { token = historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(path); token = historyImpl.@org.ocpsoft.rewrite.gwt.client.history.HistoryStateImpl::cleanToken(Ljava/lang/String;)(token); } @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token); var oldHandler = $wnd.history.onpopstate; $wnd.onpopstate = $entry(function() { var token = ''; var path = $wnd.location.pathname; if (path.length > 0) { token = historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(path); token = historyImpl.@org.ocpsoft.rewrite.gwt.client.history.HistoryStateImpl::cleanToken(Ljava/lang/String;)(token); } historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token); if (oldHandler) { oldHandler(); } }); return true; }-*/; protected String cleanToken(String historyToken) { String contextPath = HistoryStateImpl.getContextPath(); if (!contextPath.equals(historyToken) && historyToken.startsWith(contextPath)) historyToken = historyToken.substring(contextPath.length()); System.out.println("History.pop() = [" + historyToken + "]"); return historyToken; } @Override protected void nativeUpdate(String historyToken) { String contextPath = HistoryStateImpl.getContextPath(); if (!contextPath.equals(historyToken)) historyToken = contextPath + historyToken; System.out.println("History.push(" + historyToken + ")"); update(historyToken); } protected native void update(String historyToken) /*-{ var encodedToken = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken); $wnd.history.pushState(encodedToken, $wnd.document.title, encodedToken); }-*/; }