/*
* Copyright 2014 cruxframework.org.
*
* 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.cruxframework.crux.core.client.screen.history;
import org.cruxframework.crux.core.client.collection.FastList;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* Implementation of the HTML5 History API
* @author Thiago da Rosa de Bustamante
*/
public class History
{
private static boolean handlerInitialized = false;
private static FastList<HistoryHandler> historyHandlers;
/**
* Programmatic equivalent to the user pressing the browser's 'back' button.
*/
public static native void back() /*-{
$wnd.history.back();
}-*/;
/**
* Programmatic equivalent to the user pressing the browser's 'forward'
* button.
*/
public static native void forward() /*-{
$wnd.history.forward();
}-*/;
/**
* Goes back or forward the specified number of steps in the joint session history.
* A zero delta will reload the current page.
* If the delta is out of range, does nothing.
* @param delta number of steps
*/
public static native void go(int delta) /*-{
$wnd.history.go(delta);
}-*/;
/**
* Returns the number of entries in the joint session history.
* @return history length
*/
public static native int length()/*-{
return ($wnd.history.length?$wnd.history.length:0);
}-*/;
/**
* Adds a state object entry to the history.
* @param data Some structured data, such as settings or content, assigned to the history item.
* @param title The name of the item in the history drop-down shown by the browser’s back and forward buttons.
* @param url The URL to this state that should be displayed in the address bar.
*/
public static native void pushState(JavaScriptObject data, String title, String url)/*-{
$wnd.history.pushState({'data': data, 'url': url?url:'', 'title': title?title:''}, title, url);
}-*/;
/**
* Adds a state object entry to the history.
* @param data Some structured data, such as settings or content, assigned to the history item.
* @param title The name of the item in the history drop-down shown by the browser’s back and forward buttons.
*/
public static native void pushState(JavaScriptObject data, String title)/*-{
$wnd.history.pushState({'data': data, 'url': '', 'title': title?title:''}, title);
}-*/;
/**
* Updates the state object, title of the current entry in the history.
* @param data Some structured data, such as settings or content, assigned to the history item.
* @param title The name of the item in the history drop-down shown by the browser’s back and forward buttons.
*/
public static native void replaceState(JavaScriptObject data, String title)/*-{
$wnd.history.replaceState({'data': data, 'url': '', 'title': title?title:''}, title);
}-*/;
/**
* Updates the state object, title and the URL of the current entry in the history.
* @param data Some structured data, such as settings or content, assigned to the history item.
* @param title The name of the item in the history drop-down shown by the browser’s back and forward buttons.
* @param url The URL to this state that should be displayed in the address bar.
*/
public static native void replaceState(JavaScriptObject data, String title, String url)/*-{
$wnd.history.replaceState({'data': data, 'url': url?url:'', 'title': title?title:''}, title, url);
}-*/;
/**
* Some structured data, such as settings or content, assigned to the history item
* @return item state data
*/
public static native <T extends JavaScriptObject> T state()/*-{
return ($wnd.history.state?$wnd.history.state.data:null);
}-*/;
/**
* The URL to this state that should be displayed in the address bar
* @return item state url
*/
public static native String url()/*-{
return ($wnd.history.state?$wnd.history.state.url:null);
}-*/;
/**
* The name of the item in the history drop-down shown by the browser’s back and forward buttons.
* @return item state url
*/
public static native String title()/*-{
return ($wnd.history.state?$wnd.history.state.title:null);
}-*/;
public static HandlerRegistration addHistoryHandler(final HistoryHandler historyHandler)
{
if (!handlerInitialized)
{
initWindowHistoryHandler();
historyHandlers = new FastList<HistoryHandler>();
handlerInitialized = true;
}
historyHandlers.add(historyHandler);
return new HandlerRegistration()
{
@Override
public void removeHandler()
{
int index = historyHandlers.indexOf(historyHandler);
if (index >= 0)
{
historyHandlers.remove(index);
}
}
};
}
private static void onStateChanged(JavaScriptObject data, String url, String title)
{
HistoryEvent event = new HistoryEvent(data, url, title);
for (int i=0; i<historyHandlers.size(); i++)
{
historyHandlers.get(i).onStateChange(event);
}
}
private static native void initWindowHistoryHandler() /*-{
var oldOnPopstate = $wnd.onpopstate;
$wnd.onpopstate = function(evt) {
try
{
if (evt && evt.state)
{
@org.cruxframework.crux.core.client.screen.history.History::onStateChanged(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Ljava/lang/String;)(evt.state.data, evt.state.url, evt.state.title);
}
else
{
@org.cruxframework.crux.core.client.screen.history.History::onStateChanged(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Ljava/lang/String;)(null, $wnd.location.pathname, $doc.title);
}
}
finally
{
oldOnPopstate && oldOnPopstate(evt);
}
};
}-*/;
}