All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wallissoftware.pushstate.client.PushStateHistorianImpl Maven / Gradle / Ivy

There is a newer version: 2.0.0.26
Show newest version
/*
 * Copyright 2014 Richard Wallis
 *
 * 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 com.wallissoftware.pushstate.client;

import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceHistoryHandler.Historian;
import com.google.gwt.user.client.Window;

import org.apache.commons.lang3.StringUtils;

public class PushStateHistorianImpl implements Historian, HasValueChangeHandlers {

  private final EventBus handlers = new SimpleEventBus();
  private String token;
  private final String relativePath;

  /**
   * constructor.
   *
   * @param prelativePath relative path to use
   */
  PushStateHistorianImpl(final String prelativePath) {
    this.relativePath = StringUtils.endsWith(prelativePath, "/") ? prelativePath
        : StringUtils.defaultString(prelativePath) + "/";
    this.initToken();
    this.registerPopstateHandler();
  }

  @Override
  public final String getToken() {
    return this.token;
  }

  @Override
  public void newItem(final String ptoken, final boolean pissueEvent) {
    this.newItem(ptoken, pissueEvent, false);
  }

  /**
   * add new item.
   *
   * @param ptoken token of the page
   * @param pissueEvent issue event
   * @param preplaceState repace state
   */
  public void newItem(final String ptoken, final boolean pissueEvent, final boolean preplaceState) {
    if (this.setToken(ptoken)) {
      if (preplaceState) {
        PushStateHistorianImpl.replaceState(this.relativePath, this.getToken());
      } else {
        PushStateHistorianImpl.pushState(this.relativePath, this.getToken());
      }

      if (pissueEvent) {
        ValueChangeEvent.fire(this, this.getToken());
      }
    }
  }

  @Override
  public void fireEvent(final GwtEvent pevent) {
    this.handlers.fireEvent(pevent);
  }

  private native void registerPopstateHandler()/*-{
    var that = this;
    var oldHandler = $wnd.onpopstate;
    $wnd.onpopstate = $entry(function(e) {
      if (e) {
        if (e.state) {
          [email protected]::onPopState(Ljava/lang/String;)(e.state.token);
        }
        if (oldHandler) {
          oldHandler(e);
        }
      }
    });
  }-*/;

  private void onPopState(final String ptoken) {
    if (this.setToken(ptoken)) {
      ValueChangeEvent.fire(this, this.getToken());
    }
  }

  private final void initToken() {
    final String token = Window.Location.getPath() + Window.Location.getQueryString();

    this.setToken(token);
    PushStateHistorianImpl.replaceState(this.relativePath, this.getToken());
  }

  private String stripStartSlash(final String pinput) {
    return StringUtils.removeStart(pinput, "/");
  }

  private String stripRelativePath(final String ptoken) {
    final String relPath = this.stripStartSlash(this.relativePath);
    final String token = this.stripStartSlash(ptoken);

    if (StringUtils.startsWith(token, relPath)) {
      return this.stripStartSlash(StringUtils.substring(token, relPath.length()));
    }
    return token;
  }

  private static native void replaceState(final String prelativePath, final String ptoken) /*-{
    $wnd.history.replaceState({'token' : ptoken}, $doc.title, prelativePath + ptoken);
  }-*/;

  private static native void pushState(final String prelativePath, final String ptoken) /*-{
    $wnd.history.pushState({'token' : ptoken}, $doc.title, prelativePath + ptoken);
  }-*/;

  private final boolean setToken(final String pnewToken) {
    final String newToken = this.stripRelativePath(pnewToken);
    if (!this.matchesToken(newToken)) {
      this.token = newToken;
      return true;
    }
    return false;
  }

  private boolean matchesToken(final String pcompare) {
    return StringUtils.equals(pcompare, this.token)
        || StringUtils.equals(pcompare, this.token + "/")
        || StringUtils.equals(this.token, pcompare + "/");
  }

  @Override
  public HandlerRegistration addValueChangeHandler(
      final ValueChangeHandler pvalueChangeHandler) {
    return this.handlers.addHandler(ValueChangeEvent.getType(), pvalueChangeHandler);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy