|  | @@ -408,16 +408,6 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Module exports.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var page_js = page;
 | 
	
		
			
				|  |  | -  page.default = page;
 | 
	
		
			
				|  |  | -  page.Context = Context;
 | 
	
		
			
				|  |  | -  page.Route = Route;
 | 
	
		
			
				|  |  | -  page.sameOrigin = sameOrigin;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Short-cuts for global-object checks
 | 
	
		
			
				|  |  |     */
 | 
	
	
		
			
				|  | @@ -440,116 +430,67 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |    var isLocation = hasWindow && !!(window.history.location || window.location);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  | -   * Perform initial dispatch.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var dispatch = true;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Decode URL components (query string, pathname, hash).
 | 
	
		
			
				|  |  | -   * Accommodates both regular percent encoding and x-www-form-urlencoded format.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  var decodeURLComponents = true;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Base path.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var base = '';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Strict path matching.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var strict = false;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Running flag.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var running;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * HashBang option
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var hashbang = false;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Previous context, for capturing
 | 
	
		
			
				|  |  | -   * page exit events.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var prevContext;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * The window for which this `page` is running
 | 
	
		
			
				|  |  | +   * The page instance
 | 
	
		
			
				|  |  | +   * @api private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  var pageWindow;
 | 
	
		
			
				|  |  | +  function Page(options) {
 | 
	
		
			
				|  |  | +    // public things
 | 
	
		
			
				|  |  | +    this.callbacks = [];
 | 
	
		
			
				|  |  | +    this.exits = [];
 | 
	
		
			
				|  |  | +    this.current = '';
 | 
	
		
			
				|  |  | +    this.len = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // private things
 | 
	
		
			
				|  |  | +    this._dispatch = true;
 | 
	
		
			
				|  |  | +    this._decodeURLComponents = true;
 | 
	
		
			
				|  |  | +    this._base = '';
 | 
	
		
			
				|  |  | +    this._strict = false;
 | 
	
		
			
				|  |  | +    this._running = false;
 | 
	
		
			
				|  |  | +    this._hashbang = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // bound functions
 | 
	
		
			
				|  |  | +    this._onclick = this._onclick.bind(this);
 | 
	
		
			
				|  |  | +    this._onpopstate = this._onpopstate.bind(this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this.configure(options);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  | -   * Register `path` with callback `fn()`,
 | 
	
		
			
				|  |  | -   * or route `path`, or redirection,
 | 
	
		
			
				|  |  | -   * or `page.start()`.
 | 
	
		
			
				|  |  | +   * Configure the instance of page. This can be called multiple times.
 | 
	
		
			
				|  |  |     *
 | 
	
		
			
				|  |  | -   *   page(fn);
 | 
	
		
			
				|  |  | -   *   page('*', fn);
 | 
	
		
			
				|  |  | -   *   page('/user/:id', load, user);
 | 
	
		
			
				|  |  | -   *   page('/user/' + user.id, { some: 'thing' });
 | 
	
		
			
				|  |  | -   *   page('/user/' + user.id);
 | 
	
		
			
				|  |  | -   *   page('/from', '/to')
 | 
	
		
			
				|  |  | -   *   page();
 | 
	
		
			
				|  |  | -   *
 | 
	
		
			
				|  |  | -   * @param {string|!Function|!Object} path
 | 
	
		
			
				|  |  | -   * @param {Function=} fn
 | 
	
		
			
				|  |  | +   * @param {Object} options
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  function page(path, fn) {
 | 
	
		
			
				|  |  | -    // <callback>
 | 
	
		
			
				|  |  | -    if ('function' === typeof path) {
 | 
	
		
			
				|  |  | -      return page('*', path);
 | 
	
		
			
				|  |  | +  Page.prototype.configure = function(options) {
 | 
	
		
			
				|  |  | +    var opts = options || {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this._window = opts.window || (hasWindow && window);
 | 
	
		
			
				|  |  | +    this._dispatch = opts.dispatch !== false;
 | 
	
		
			
				|  |  | +    this._decodeURLComponents = opts.decodeURLComponents !== false;
 | 
	
		
			
				|  |  | +    this._popstate = opts.popstate !== false && hasWindow;
 | 
	
		
			
				|  |  | +    this._click = opts.click !== false && hasDocument;
 | 
	
		
			
				|  |  | +    this._hashbang = !!opts.hashbang;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var _window = this._window;
 | 
	
		
			
				|  |  | +    if(this._popstate) {
 | 
	
		
			
				|  |  | +      _window.addEventListener('popstate', this._onpopstate, false);
 | 
	
		
			
				|  |  | +    } else if(hasWindow) {
 | 
	
		
			
				|  |  | +      _window.removeEventListener('popstate', this._onpopstate, false);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // route <path> to <callback ...>
 | 
	
		
			
				|  |  | -    if ('function' === typeof fn) {
 | 
	
		
			
				|  |  | -      var route = new Route(/** @type {string} */ (path));
 | 
	
		
			
				|  |  | -      for (var i = 1; i < arguments.length; ++i) {
 | 
	
		
			
				|  |  | -        page.callbacks.push(route.middleware(arguments[i]));
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      // show <path> with [state]
 | 
	
		
			
				|  |  | -    } else if ('string' === typeof path) {
 | 
	
		
			
				|  |  | -      page['string' === typeof fn ? 'redirect' : 'show'](path, fn);
 | 
	
		
			
				|  |  | -      // start [options]
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      page.start(path);
 | 
	
		
			
				|  |  | +    if (this._click) {
 | 
	
		
			
				|  |  | +      _window.document.addEventListener(clickEvent, this._onclick, false);
 | 
	
		
			
				|  |  | +    } else if(hasDocument) {
 | 
	
		
			
				|  |  | +      _window.document.removeEventListener(clickEvent, this._onclick, false);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Callback functions.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  page.callbacks = [];
 | 
	
		
			
				|  |  | -  page.exits = [];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Current path being processed
 | 
	
		
			
				|  |  | -   * @type {string}
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  page.current = '';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Number of pages navigated to.
 | 
	
		
			
				|  |  | -   * @type {number}
 | 
	
		
			
				|  |  | -   *
 | 
	
		
			
				|  |  | -   *     page.len == 0;
 | 
	
		
			
				|  |  | -   *     page('/login');
 | 
	
		
			
				|  |  | -   *     page.len == 1;
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  page.len = 0;
 | 
	
		
			
				|  |  | +    if(this._hashbang && hasWindow && !hasHistory) {
 | 
	
		
			
				|  |  | +      _window.addEventListener('hashchange', this._onpopstate, false);
 | 
	
		
			
				|  |  | +    } else if(hasWindow) {
 | 
	
		
			
				|  |  | +      _window.removeEventListener('hashchange', this._onpopstate, false);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Get or set basepath to `path`.
 | 
	
	
		
			
				|  | @@ -558,9 +499,22 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.base = function(path) {
 | 
	
		
			
				|  |  | -    if (0 === arguments.length) return base;
 | 
	
		
			
				|  |  | -    base = path;
 | 
	
		
			
				|  |  | +  Page.prototype.base = function(path) {
 | 
	
		
			
				|  |  | +    if (0 === arguments.length) return this._base;
 | 
	
		
			
				|  |  | +    this._base = path;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Gets the `base`, which depends on whether we are using History or
 | 
	
		
			
				|  |  | +   * hashbang routing.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   * @api private
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  Page.prototype._getBase = function() {
 | 
	
		
			
				|  |  | +    var base = this._base;
 | 
	
		
			
				|  |  | +    if(!!base) return base;
 | 
	
		
			
				|  |  | +    var loc = hasWindow && this._window && this._window.location;
 | 
	
		
			
				|  |  | +    return (hasWindow && this._hashbang && loc && loc.protocol === 'file:') ? loc.pathname : base;
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
	
		
			
				|  | @@ -570,11 +524,12 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.strict = function(enable) {
 | 
	
		
			
				|  |  | -    if (0 === arguments.length) return strict;
 | 
	
		
			
				|  |  | -    strict = enable;
 | 
	
		
			
				|  |  | +  Page.prototype.strict = function(enable) {
 | 
	
		
			
				|  |  | +    if (0 === arguments.length) return this._strict;
 | 
	
		
			
				|  |  | +    this._strict = enable;
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Bind with the given `options`.
 | 
	
		
			
				|  |  |     *
 | 
	
	
		
			
				|  | @@ -588,37 +543,27 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.start = function(options) {
 | 
	
		
			
				|  |  | -    options = options || {};
 | 
	
		
			
				|  |  | -    if (running) return;
 | 
	
		
			
				|  |  | -    running = true;
 | 
	
		
			
				|  |  | -    pageWindow = options.window || (hasWindow && window);
 | 
	
		
			
				|  |  | -    if (false === options.dispatch) dispatch = false;
 | 
	
		
			
				|  |  | -    if (false === options.decodeURLComponents) decodeURLComponents = false;
 | 
	
		
			
				|  |  | -    if (false !== options.popstate && hasWindow) pageWindow.addEventListener('popstate', onpopstate, false);
 | 
	
		
			
				|  |  | -    if (false !== options.click && hasDocument) {
 | 
	
		
			
				|  |  | -      pageWindow.document.addEventListener(clickEvent, onclick, false);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    hashbang = !!options.hashbang;
 | 
	
		
			
				|  |  | -    if(hashbang && hasWindow && !hasHistory) {
 | 
	
		
			
				|  |  | -      pageWindow.addEventListener('hashchange', onpopstate, false);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (!dispatch) return;
 | 
	
		
			
				|  |  | +  Page.prototype.start = function(options) {
 | 
	
		
			
				|  |  | +    this.configure(options);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!this._dispatch) return;
 | 
	
		
			
				|  |  | +    this._running = true;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      var url;
 | 
	
		
			
				|  |  |      if(isLocation) {
 | 
	
		
			
				|  |  | -      var loc = pageWindow.location;
 | 
	
		
			
				|  |  | +      var window = this._window;
 | 
	
		
			
				|  |  | +      var loc = window.location;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      if(hashbang && ~loc.hash.indexOf('#!')) {
 | 
	
		
			
				|  |  | +      if(this._hashbang && ~loc.hash.indexOf('#!')) {
 | 
	
		
			
				|  |  |          url = loc.hash.substr(2) + loc.search;
 | 
	
		
			
				|  |  | -      } else if (hashbang) {
 | 
	
		
			
				|  |  | +      } else if (this._hashbang) {
 | 
	
		
			
				|  |  |          url = loc.search + loc.hash;
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  |          url = loc.pathname + loc.search + loc.hash;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    page.replace(url, null, true, dispatch);
 | 
	
		
			
				|  |  | +    this.replace(url, null, true, this._dispatch);
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
	
		
			
				|  | @@ -627,14 +572,16 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.stop = function() {
 | 
	
		
			
				|  |  | -    if (!running) return;
 | 
	
		
			
				|  |  | -    page.current = '';
 | 
	
		
			
				|  |  | -    page.len = 0;
 | 
	
		
			
				|  |  | -    running = false;
 | 
	
		
			
				|  |  | -    hasDocument && pageWindow.document.removeEventListener(clickEvent, onclick, false);
 | 
	
		
			
				|  |  | -    hasWindow && pageWindow.removeEventListener('popstate', onpopstate, false);
 | 
	
		
			
				|  |  | -    hasWindow && pageWindow.removeEventListener('hashchange', onpopstate, false);
 | 
	
		
			
				|  |  | +  Page.prototype.stop = function() {
 | 
	
		
			
				|  |  | +    if (!this._running) return;
 | 
	
		
			
				|  |  | +    this.current = '';
 | 
	
		
			
				|  |  | +    this.len = 0;
 | 
	
		
			
				|  |  | +    this._running = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var window = this._window;
 | 
	
		
			
				|  |  | +    hasDocument && window.document.removeEventListener(clickEvent, this._onclick, false);
 | 
	
		
			
				|  |  | +    hasWindow && window.removeEventListener('popstate', this._onpopstate, false);
 | 
	
		
			
				|  |  | +    hasWindow && window.removeEventListener('hashchange', this._onpopstate, false);
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
	
		
			
				|  | @@ -648,12 +595,12 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.show = function(path, state, dispatch, push) {
 | 
	
		
			
				|  |  | -    var ctx = new Context(path, state),
 | 
	
		
			
				|  |  | -      prev = prevContext;
 | 
	
		
			
				|  |  | -    prevContext = ctx;
 | 
	
		
			
				|  |  | -    page.current = ctx.path;
 | 
	
		
			
				|  |  | -    if (false !== dispatch) page.dispatch(ctx, prev);
 | 
	
		
			
				|  |  | +  Page.prototype.show = function(path, state, dispatch, push) {
 | 
	
		
			
				|  |  | +    var ctx = new Context(path, state, this),
 | 
	
		
			
				|  |  | +      prev = this.prevContext;
 | 
	
		
			
				|  |  | +    this.prevContext = ctx;
 | 
	
		
			
				|  |  | +    this.current = ctx.path;
 | 
	
		
			
				|  |  | +    if (this._dispatch) this.dispatch(ctx, prev);
 | 
	
		
			
				|  |  |      if (false !== ctx.handled && false !== push) ctx.pushState();
 | 
	
		
			
				|  |  |      return ctx;
 | 
	
		
			
				|  |  |    };
 | 
	
	
		
			
				|  | @@ -667,24 +614,25 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.back = function(path, state) {
 | 
	
		
			
				|  |  | -    if (page.len > 0) {
 | 
	
		
			
				|  |  | +  Page.prototype.back = function(path, state) {
 | 
	
		
			
				|  |  | +    var page = this;
 | 
	
		
			
				|  |  | +    if (this.len > 0) {
 | 
	
		
			
				|  |  | +      var window = this._window;
 | 
	
		
			
				|  |  |        // this may need more testing to see if all browsers
 | 
	
		
			
				|  |  |        // wait for the next tick to go back in history
 | 
	
		
			
				|  |  | -      hasHistory && pageWindow.history.back();
 | 
	
		
			
				|  |  | -      page.len--;
 | 
	
		
			
				|  |  | +      hasHistory && window.history.back();
 | 
	
		
			
				|  |  | +      this.len--;
 | 
	
		
			
				|  |  |      } else if (path) {
 | 
	
		
			
				|  |  |        setTimeout(function() {
 | 
	
		
			
				|  |  |          page.show(path, state);
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  | -    }else{
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  |        setTimeout(function() {
 | 
	
		
			
				|  |  | -        page.show(getBase(), state);
 | 
	
		
			
				|  |  | +        page.show(page._getBase(), state);
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Register route to redirect from one path to other
 | 
	
		
			
				|  |  |     * or just redirect to another route
 | 
	
	
		
			
				|  | @@ -693,12 +641,14 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @param {string=} to
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  page.redirect = function(from, to) {
 | 
	
		
			
				|  |  | +  Page.prototype.redirect = function(from, to) {
 | 
	
		
			
				|  |  | +    var inst = this;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      // Define route from a path to another
 | 
	
		
			
				|  |  |      if ('string' === typeof from && 'string' === typeof to) {
 | 
	
		
			
				|  |  | -      page(from, function(e) {
 | 
	
		
			
				|  |  | +      page.call(this, from, function(e) {
 | 
	
		
			
				|  |  |          setTimeout(function() {
 | 
	
		
			
				|  |  | -          page.replace(/** @type {!string} */ (to));
 | 
	
		
			
				|  |  | +          inst.replace(/** @type {!string} */ (to));
 | 
	
		
			
				|  |  |          }, 0);
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -706,7 +656,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |      // Wait for the push state and replace it with another
 | 
	
		
			
				|  |  |      if ('string' === typeof from && 'undefined' === typeof to) {
 | 
	
		
			
				|  |  |        setTimeout(function() {
 | 
	
		
			
				|  |  | -        page.replace(from);
 | 
	
		
			
				|  |  | +        inst.replace(from);
 | 
	
		
			
				|  |  |        }, 0);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    };
 | 
	
	
		
			
				|  | @@ -723,14 +673,14 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.replace = function(path, state, init, dispatch) {
 | 
	
		
			
				|  |  | -    var ctx = new Context(path, state),
 | 
	
		
			
				|  |  | -      prev = prevContext;
 | 
	
		
			
				|  |  | -    prevContext = ctx;
 | 
	
		
			
				|  |  | -    page.current = ctx.path;
 | 
	
		
			
				|  |  | +  Page.prototype.replace = function(path, state, init, dispatch) {
 | 
	
		
			
				|  |  | +    var ctx = new Context(path, state, this),
 | 
	
		
			
				|  |  | +      prev = this.prevContext;
 | 
	
		
			
				|  |  | +    this.prevContext = ctx;
 | 
	
		
			
				|  |  | +    this.current = ctx.path;
 | 
	
		
			
				|  |  |      ctx.init = init;
 | 
	
		
			
				|  |  |      ctx.save(); // save before dispatching, which may redirect
 | 
	
		
			
				|  |  | -    if (false !== dispatch) page.dispatch(ctx, prev);
 | 
	
		
			
				|  |  | +    if (false !== dispatch) this.dispatch(ctx, prev);
 | 
	
		
			
				|  |  |      return ctx;
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -741,9 +691,8 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.dispatch = function(ctx, prev) {
 | 
	
		
			
				|  |  | -    var i = 0,
 | 
	
		
			
				|  |  | -      j = 0;
 | 
	
		
			
				|  |  | +  Page.prototype.dispatch = function(ctx, prev) {
 | 
	
		
			
				|  |  | +    var i = 0, j = 0, page = this;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      function nextExit() {
 | 
	
		
			
				|  |  |        var fn = page.exits[j++];
 | 
	
	
		
			
				|  | @@ -758,7 +707,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |          ctx.handled = false;
 | 
	
		
			
				|  |  |          return;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      if (!fn) return unhandled(ctx);
 | 
	
		
			
				|  |  | +      if (!fn) return unhandled.call(page, ctx);
 | 
	
		
			
				|  |  |        fn(ctx, nextEnter);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -770,44 +719,190 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  | -   * Unhandled `ctx`. When it's not the initial
 | 
	
		
			
				|  |  | -   * popstate then redirect. If you wish to handle
 | 
	
		
			
				|  |  | -   * 404s on your own use `page('*', callback)`.
 | 
	
		
			
				|  |  | -   *
 | 
	
		
			
				|  |  | -   * @param {Context} ctx
 | 
	
		
			
				|  |  | +   * Register an exit route on `path` with
 | 
	
		
			
				|  |  | +   * callback `fn()`, which will be called
 | 
	
		
			
				|  |  | +   * on the previous context when a new
 | 
	
		
			
				|  |  | +   * page is visited.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  Page.prototype.exit = function(path, fn) {
 | 
	
		
			
				|  |  | +    if (typeof path === 'function') {
 | 
	
		
			
				|  |  | +      return this.exit('*', path);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var route = new Route(path, null, this);
 | 
	
		
			
				|  |  | +    for (var i = 1; i < arguments.length; ++i) {
 | 
	
		
			
				|  |  | +      this.exits.push(route.middleware(arguments[i]));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Handle "click" events.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* jshint +W054 */
 | 
	
		
			
				|  |  | +  Page.prototype._onclick = function(e) {
 | 
	
		
			
				|  |  | +    if (1 !== this._which(e)) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (e.metaKey || e.ctrlKey || e.shiftKey) return;
 | 
	
		
			
				|  |  | +    if (e.defaultPrevented) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // ensure link
 | 
	
		
			
				|  |  | +    // use shadow dom when available if not, fall back to composedPath()
 | 
	
		
			
				|  |  | +    // for browsers that only have shady
 | 
	
		
			
				|  |  | +    var el = e.target;
 | 
	
		
			
				|  |  | +    var eventPath = e.path || (e.composedPath ? e.composedPath() : null);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(eventPath) {
 | 
	
		
			
				|  |  | +      for (var i = 0; i < eventPath.length; i++) {
 | 
	
		
			
				|  |  | +        if (!eventPath[i].nodeName) continue;
 | 
	
		
			
				|  |  | +        if (eventPath[i].nodeName.toUpperCase() !== 'A') continue;
 | 
	
		
			
				|  |  | +        if (!eventPath[i].href) continue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        el = eventPath[i];
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // continue ensure link
 | 
	
		
			
				|  |  | +    // el.nodeName for svg links are 'a' instead of 'A'
 | 
	
		
			
				|  |  | +    while (el && 'A' !== el.nodeName.toUpperCase()) el = el.parentNode;
 | 
	
		
			
				|  |  | +    if (!el || 'A' !== el.nodeName.toUpperCase()) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // check if link is inside an svg
 | 
	
		
			
				|  |  | +    // in this case, both href and target are always inside an object
 | 
	
		
			
				|  |  | +    var svg = (typeof el.href === 'object') && el.href.constructor.name === 'SVGAnimatedString';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Ignore if tag has
 | 
	
		
			
				|  |  | +    // 1. "download" attribute
 | 
	
		
			
				|  |  | +    // 2. rel="external" attribute
 | 
	
		
			
				|  |  | +    if (el.hasAttribute('download') || el.getAttribute('rel') === 'external') return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // ensure non-hash for the same path
 | 
	
		
			
				|  |  | +    var link = el.getAttribute('href');
 | 
	
		
			
				|  |  | +    if(!this._hashbang && this._samePath(el) && (el.hash || '#' === link)) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Check for mailto: in the href
 | 
	
		
			
				|  |  | +    if (link && link.indexOf('mailto:') > -1) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // check target
 | 
	
		
			
				|  |  | +    // svg target is an object and its desired value is in .baseVal property
 | 
	
		
			
				|  |  | +    if (svg ? el.target.baseVal : el.target) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // x-origin
 | 
	
		
			
				|  |  | +    // note: svg links that are not relative don't call click events (and skip page.js)
 | 
	
		
			
				|  |  | +    // consequently, all svg links tested inside page.js are relative and in the same origin
 | 
	
		
			
				|  |  | +    if (!svg && !this.sameOrigin(el.href)) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // rebuild path
 | 
	
		
			
				|  |  | +    // There aren't .pathname and .search properties in svg links, so we use href
 | 
	
		
			
				|  |  | +    // Also, svg href is an object and its desired value is in .baseVal property
 | 
	
		
			
				|  |  | +    var path = svg ? el.href.baseVal : (el.pathname + el.search + (el.hash || ''));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    path = path[0] !== '/' ? '/' + path : path;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // strip leading "/[drive letter]:" on NW.js on Windows
 | 
	
		
			
				|  |  | +    if (hasProcess && path.match(/^\/[a-zA-Z]:\//)) {
 | 
	
		
			
				|  |  | +      path = path.replace(/^\/[a-zA-Z]:\//, '/');
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // same page
 | 
	
		
			
				|  |  | +    var orig = path;
 | 
	
		
			
				|  |  | +    var pageBase = this._getBase();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (path.indexOf(pageBase) === 0) {
 | 
	
		
			
				|  |  | +      path = path.substr(pageBase.length);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (this._hashbang) path = path.replace('#!', '');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (pageBase && orig === path) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    e.preventDefault();
 | 
	
		
			
				|  |  | +    this.show(orig);
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Handle "populate" events.
 | 
	
		
			
				|  |  |     * @api private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  function unhandled(ctx) {
 | 
	
		
			
				|  |  | -    if (ctx.handled) return;
 | 
	
		
			
				|  |  | -    var current;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (hashbang) {
 | 
	
		
			
				|  |  | -      current = isLocation && getBase() + pageWindow.location.hash.replace('#!', '');
 | 
	
		
			
				|  |  | +  Page.prototype._onpopstate = (function () {
 | 
	
		
			
				|  |  | +    var loaded = false;
 | 
	
		
			
				|  |  | +    if ( ! hasWindow ) {
 | 
	
		
			
				|  |  | +      return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (hasDocument && document.readyState === 'complete') {
 | 
	
		
			
				|  |  | +      loaded = true;
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -      current = isLocation && pageWindow.location.pathname + pageWindow.location.search;
 | 
	
		
			
				|  |  | +      window.addEventListener('load', function() {
 | 
	
		
			
				|  |  | +        setTimeout(function() {
 | 
	
		
			
				|  |  | +          loaded = true;
 | 
	
		
			
				|  |  | +        }, 0);
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    return function onpopstate(e) {
 | 
	
		
			
				|  |  | +      if (!loaded) return;
 | 
	
		
			
				|  |  | +      var page = this;
 | 
	
		
			
				|  |  | +      if (e.state) {
 | 
	
		
			
				|  |  | +        var path = e.state.path;
 | 
	
		
			
				|  |  | +        page.replace(path, e.state);
 | 
	
		
			
				|  |  | +      } else if (isLocation) {
 | 
	
		
			
				|  |  | +        var loc = page._window.location;
 | 
	
		
			
				|  |  | +        page.show(loc.pathname + loc.search + loc.hash, undefined, undefined, false);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +  })();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (current === ctx.canonicalPath) return;
 | 
	
		
			
				|  |  | -    page.stop();
 | 
	
		
			
				|  |  | -    ctx.handled = false;
 | 
	
		
			
				|  |  | -    isLocation && (pageWindow.location.href = ctx.canonicalPath);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Event button.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  Page.prototype._which = function(e) {
 | 
	
		
			
				|  |  | +    e = e || (hasWindow && this._window.event);
 | 
	
		
			
				|  |  | +    return null == e.which ? e.button : e.which;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  | -   * Register an exit route on `path` with
 | 
	
		
			
				|  |  | -   * callback `fn()`, which will be called
 | 
	
		
			
				|  |  | -   * on the previous context when a new
 | 
	
		
			
				|  |  | -   * page is visited.
 | 
	
		
			
				|  |  | +   * Convert to a URL object
 | 
	
		
			
				|  |  | +   * @api private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  page.exit = function(path, fn) {
 | 
	
		
			
				|  |  | -    if (typeof path === 'function') {
 | 
	
		
			
				|  |  | -      return page.exit('*', path);
 | 
	
		
			
				|  |  | +  Page.prototype._toURL = function(href) {
 | 
	
		
			
				|  |  | +    var window = this._window;
 | 
	
		
			
				|  |  | +    if(typeof URL === 'function' && isLocation) {
 | 
	
		
			
				|  |  | +      return new URL(href, window.location.toString());
 | 
	
		
			
				|  |  | +    } else if (hasDocument) {
 | 
	
		
			
				|  |  | +      var anc = window.document.createElement('a');
 | 
	
		
			
				|  |  | +      anc.href = href;
 | 
	
		
			
				|  |  | +      return anc;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    var route = new Route(path);
 | 
	
		
			
				|  |  | -    for (var i = 1; i < arguments.length; ++i) {
 | 
	
		
			
				|  |  | -      page.exits.push(route.middleware(arguments[i]));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Check if `href` is the same origin.
 | 
	
		
			
				|  |  | +   * @param {string} href
 | 
	
		
			
				|  |  | +   * @api public
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  Page.prototype.sameOrigin = function(href) {
 | 
	
		
			
				|  |  | +    if(!href || !isLocation) return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var url = this._toURL(href);
 | 
	
		
			
				|  |  | +    var window = this._window;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var loc = window.location;
 | 
	
		
			
				|  |  | +    return loc.protocol === url.protocol &&
 | 
	
		
			
				|  |  | +      loc.hostname === url.hostname &&
 | 
	
		
			
				|  |  | +      loc.port === url.port;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * @api private
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  Page.prototype._samePath = function(url) {
 | 
	
		
			
				|  |  | +    if(!isLocation) return false;
 | 
	
		
			
				|  |  | +    var window = this._window;
 | 
	
		
			
				|  |  | +    var loc = window.location;
 | 
	
		
			
				|  |  | +    return url.pathname === loc.pathname &&
 | 
	
		
			
				|  |  | +      url.search === loc.search;
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
	
		
			
				|  | @@ -816,10 +911,129 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * and regular percent-encoded form.
 | 
	
		
			
				|  |  |     *
 | 
	
		
			
				|  |  |     * @param {string} val - URL component to decode
 | 
	
		
			
				|  |  | +   * @api private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  function decodeURLEncodedURIComponent(val) {
 | 
	
		
			
				|  |  | +  Page.prototype._decodeURLEncodedURIComponent = function(val) {
 | 
	
		
			
				|  |  |      if (typeof val !== 'string') { return val; }
 | 
	
		
			
				|  |  | -    return decodeURLComponents ? decodeURIComponent(val.replace(/\+/g, ' ')) : val;
 | 
	
		
			
				|  |  | +    return this._decodeURLComponents ? decodeURIComponent(val.replace(/\+/g, ' ')) : val;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Create a new `page` instance and function
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  function createPage(options) {
 | 
	
		
			
				|  |  | +    var pageInstance = new Page();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    function pageFn(/* args */) {
 | 
	
		
			
				|  |  | +      return page.apply(pageInstance, arguments);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Copy all of the things over. In 2.0 maybe we use setPrototypeOf
 | 
	
		
			
				|  |  | +    pageFn.callbacks = pageInstance.callbacks;
 | 
	
		
			
				|  |  | +    pageFn.exits = pageInstance.exits;
 | 
	
		
			
				|  |  | +    pageFn.base = pageInstance.base.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.strict = pageInstance.strict.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.start = pageInstance.start.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.stop = pageInstance.stop.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.show = pageInstance.show.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.back = pageInstance.back.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.redirect = pageInstance.redirect.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.replace = pageInstance.replace.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.dispatch = pageInstance.dispatch.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.exit = pageInstance.exit.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.configure = pageInstance.configure.bind(pageInstance);
 | 
	
		
			
				|  |  | +    pageFn.sameOrigin = pageInstance.sameOrigin.bind(pageInstance);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pageFn.create = createPage;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Object.defineProperty(pageFn, 'len', {
 | 
	
		
			
				|  |  | +      get: function(){
 | 
	
		
			
				|  |  | +        return pageInstance.len;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      set: function(val) {
 | 
	
		
			
				|  |  | +        pageInstance.len = val;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Object.defineProperty(pageFn, 'current', {
 | 
	
		
			
				|  |  | +      get: function(){
 | 
	
		
			
				|  |  | +        return pageInstance.current;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      set: function(val) {
 | 
	
		
			
				|  |  | +        pageInstance.current = val;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // In 2.0 these can be named exports
 | 
	
		
			
				|  |  | +    pageFn.Context = Context;
 | 
	
		
			
				|  |  | +    pageFn.Route = Route;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return pageFn;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Register `path` with callback `fn()`,
 | 
	
		
			
				|  |  | +   * or route `path`, or redirection,
 | 
	
		
			
				|  |  | +   * or `page.start()`.
 | 
	
		
			
				|  |  | +   *
 | 
	
		
			
				|  |  | +   *   page(fn);
 | 
	
		
			
				|  |  | +   *   page('*', fn);
 | 
	
		
			
				|  |  | +   *   page('/user/:id', load, user);
 | 
	
		
			
				|  |  | +   *   page('/user/' + user.id, { some: 'thing' });
 | 
	
		
			
				|  |  | +   *   page('/user/' + user.id);
 | 
	
		
			
				|  |  | +   *   page('/from', '/to')
 | 
	
		
			
				|  |  | +   *   page();
 | 
	
		
			
				|  |  | +   *
 | 
	
		
			
				|  |  | +   * @param {string|!Function|!Object} path
 | 
	
		
			
				|  |  | +   * @param {Function=} fn
 | 
	
		
			
				|  |  | +   * @api public
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function page(path, fn) {
 | 
	
		
			
				|  |  | +    // <callback>
 | 
	
		
			
				|  |  | +    if ('function' === typeof path) {
 | 
	
		
			
				|  |  | +      return page.call(this, '*', path);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // route <path> to <callback ...>
 | 
	
		
			
				|  |  | +    if ('function' === typeof fn) {
 | 
	
		
			
				|  |  | +      var route = new Route(/** @type {string} */ (path), null, this);
 | 
	
		
			
				|  |  | +      for (var i = 1; i < arguments.length; ++i) {
 | 
	
		
			
				|  |  | +        this.callbacks.push(route.middleware(arguments[i]));
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // show <path> with [state]
 | 
	
		
			
				|  |  | +    } else if ('string' === typeof path) {
 | 
	
		
			
				|  |  | +      this['string' === typeof fn ? 'redirect' : 'show'](path, fn);
 | 
	
		
			
				|  |  | +      // start [options]
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      this.start(path);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Unhandled `ctx`. When it's not the initial
 | 
	
		
			
				|  |  | +   * popstate then redirect. If you wish to handle
 | 
	
		
			
				|  |  | +   * 404s on your own use `page('*', callback)`.
 | 
	
		
			
				|  |  | +   *
 | 
	
		
			
				|  |  | +   * @param {Context} ctx
 | 
	
		
			
				|  |  | +   * @api private
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  function unhandled(ctx) {
 | 
	
		
			
				|  |  | +    if (ctx.handled) return;
 | 
	
		
			
				|  |  | +    var current;
 | 
	
		
			
				|  |  | +    var page = this;
 | 
	
		
			
				|  |  | +    var window = page._window;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (page._hashbang) {
 | 
	
		
			
				|  |  | +      current = isLocation && this._getBase() + window.location.hash.replace('#!', '');
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      current = isLocation && window.location.pathname + window.location.search;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (current === ctx.canonicalPath) return;
 | 
	
		
			
				|  |  | +    page.stop();
 | 
	
		
			
				|  |  | +    ctx.handled = false;
 | 
	
		
			
				|  |  | +    isLocation && (window.location.href = ctx.canonicalPath);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
	
		
			
				|  | @@ -832,8 +1046,12 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api public
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  function Context(path, state) {
 | 
	
		
			
				|  |  | -    var pageBase = getBase();
 | 
	
		
			
				|  |  | +  function Context(path, state, pageInstance) {
 | 
	
		
			
				|  |  | +    var _page = this.page = pageInstance || page;
 | 
	
		
			
				|  |  | +    var window = _page._window;
 | 
	
		
			
				|  |  | +    var hashbang = _page.hashbang;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var pageBase = _page._getBase();
 | 
	
		
			
				|  |  |      if ('/' === path[0] && 0 !== path.indexOf(pageBase)) path = pageBase + (hashbang ? '#!' : '') + path;
 | 
	
		
			
				|  |  |      var i = path.indexOf('?');
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -841,11 +1059,11 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |      this.path = path.replace(pageBase, '') || '/';
 | 
	
		
			
				|  |  |      if (hashbang) this.path = this.path.replace('#!', '') || '/';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    this.title = (hasDocument && pageWindow.document.title);
 | 
	
		
			
				|  |  | +    this.title = (hasDocument && window.document.title);
 | 
	
		
			
				|  |  |      this.state = state || {};
 | 
	
		
			
				|  |  |      this.state.path = path;
 | 
	
		
			
				|  |  | -    this.querystring = ~i ? decodeURLEncodedURIComponent(path.slice(i + 1)) : '';
 | 
	
		
			
				|  |  | -    this.pathname = decodeURLEncodedURIComponent(~i ? path.slice(0, i) : path);
 | 
	
		
			
				|  |  | +    this.querystring = ~i ? _page._decodeURLEncodedURIComponent(path.slice(i + 1)) : '';
 | 
	
		
			
				|  |  | +    this.pathname = _page._decodeURLEncodedURIComponent(~i ? path.slice(0, i) : path);
 | 
	
		
			
				|  |  |      this.params = {};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // fragment
 | 
	
	
		
			
				|  | @@ -854,17 +1072,11 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |        if (!~this.path.indexOf('#')) return;
 | 
	
		
			
				|  |  |        var parts = this.path.split('#');
 | 
	
		
			
				|  |  |        this.path = this.pathname = parts[0];
 | 
	
		
			
				|  |  | -      this.hash = decodeURLEncodedURIComponent(parts[1]) || '';
 | 
	
		
			
				|  |  | +      this.hash = _page._decodeURLEncodedURIComponent(parts[1]) || '';
 | 
	
		
			
				|  |  |        this.querystring = this.querystring.split('#')[0];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Expose `Context`.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  page.Context = Context;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Push state.
 | 
	
		
			
				|  |  |     *
 | 
	
	
		
			
				|  | @@ -872,9 +1084,13 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    Context.prototype.pushState = function() {
 | 
	
		
			
				|  |  | +    var page = this.page;
 | 
	
		
			
				|  |  | +    var window = page._window;
 | 
	
		
			
				|  |  | +    var hashbang = page._hashbang;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      page.len++;
 | 
	
		
			
				|  |  |      if (hasHistory) {
 | 
	
		
			
				|  |  | -        pageWindow.history.pushState(this.state, this.title,
 | 
	
		
			
				|  |  | +        window.history.pushState(this.state, this.title,
 | 
	
		
			
				|  |  |            hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    };
 | 
	
	
		
			
				|  | @@ -886,9 +1102,10 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    Context.prototype.save = function() {
 | 
	
		
			
				|  |  | -    if (hasHistory && pageWindow.location.protocol !== 'file:') {
 | 
	
		
			
				|  |  | -        pageWindow.history.replaceState(this.state, this.title,
 | 
	
		
			
				|  |  | -          hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath);
 | 
	
		
			
				|  |  | +    var page = this.page;
 | 
	
		
			
				|  |  | +    if (hasHistory && page._window.location.protocol !== 'file:') {
 | 
	
		
			
				|  |  | +        page._window.history.replaceState(this.state, this.title,
 | 
	
		
			
				|  |  | +          page._hashbang && this.path !== '/' ? '#!' + this.path : this.canonicalPath);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -907,22 +1124,15 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |     * @api private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  function Route(path, options) {
 | 
	
		
			
				|  |  | -    options = options || {};
 | 
	
		
			
				|  |  | -    options.strict = options.strict || strict;
 | 
	
		
			
				|  |  | +  function Route(path, options, page) {
 | 
	
		
			
				|  |  | +    var _page = this.page = page || globalPage;
 | 
	
		
			
				|  |  | +    var opts = options || {};
 | 
	
		
			
				|  |  | +    opts.strict = opts.strict || page._strict;
 | 
	
		
			
				|  |  |      this.path = (path === '*') ? '(.*)' : path;
 | 
	
		
			
				|  |  |      this.method = 'GET';
 | 
	
		
			
				|  |  | -    this.regexp = pathToRegexp_1(this.path,
 | 
	
		
			
				|  |  | -      this.keys = [],
 | 
	
		
			
				|  |  | -      options);
 | 
	
		
			
				|  |  | +    this.regexp = pathToRegexp_1(this.path, this.keys = [], opts);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Expose `Route`.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  page.Route = Route;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  |     * Return route middleware with
 | 
	
		
			
				|  |  |     * the given callback `fn()`.
 | 
	
	
		
			
				|  | @@ -960,7 +1170,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for (var i = 1, len = m.length; i < len; ++i) {
 | 
	
		
			
				|  |  |        var key = keys[i - 1];
 | 
	
		
			
				|  |  | -      var val = decodeURLEncodedURIComponent(m[i]);
 | 
	
		
			
				|  |  | +      var val = this.page._decodeURLEncodedURIComponent(m[i]);
 | 
	
		
			
				|  |  |        if (val !== undefined || !(hasOwnProperty.call(params, key.name))) {
 | 
	
		
			
				|  |  |          params[key.name] = val;
 | 
	
		
			
				|  |  |        }
 | 
	
	
		
			
				|  | @@ -971,172 +1181,12 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
		
			
				|  |  | -   * Handle "populate" events.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var onpopstate = (function () {
 | 
	
		
			
				|  |  | -    var loaded = false;
 | 
	
		
			
				|  |  | -    if ( ! hasWindow ) {
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (hasDocument && document.readyState === 'complete') {
 | 
	
		
			
				|  |  | -      loaded = true;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      window.addEventListener('load', function() {
 | 
	
		
			
				|  |  | -        setTimeout(function() {
 | 
	
		
			
				|  |  | -          loaded = true;
 | 
	
		
			
				|  |  | -        }, 0);
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return function onpopstate(e) {
 | 
	
		
			
				|  |  | -      if (!loaded) return;
 | 
	
		
			
				|  |  | -      if (e.state) {
 | 
	
		
			
				|  |  | -        var path = e.state.path;
 | 
	
		
			
				|  |  | -        page.replace(path, e.state);
 | 
	
		
			
				|  |  | -      } else if (isLocation) {
 | 
	
		
			
				|  |  | -        var loc = pageWindow.location;
 | 
	
		
			
				|  |  | -        page.show(loc.pathname + loc.hash, undefined, undefined, false);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -  })();
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Handle "click" events.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* jshint +W054 */
 | 
	
		
			
				|  |  | -  function onclick(e) {
 | 
	
		
			
				|  |  | -    if (1 !== which(e)) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (e.metaKey || e.ctrlKey || e.shiftKey) return;
 | 
	
		
			
				|  |  | -    if (e.defaultPrevented) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // ensure link
 | 
	
		
			
				|  |  | -    // use shadow dom when available if not, fall back to composedPath() for browsers that only have shady
 | 
	
		
			
				|  |  | -    var el = e.target;
 | 
	
		
			
				|  |  | -    var eventPath = e.path || (e.composedPath ? e.composedPath() : null);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if(eventPath) {
 | 
	
		
			
				|  |  | -      for (var i = 0; i < eventPath.length; i++) {
 | 
	
		
			
				|  |  | -        if (!eventPath[i].nodeName) continue;
 | 
	
		
			
				|  |  | -        if (eventPath[i].nodeName.toUpperCase() !== 'A') continue;
 | 
	
		
			
				|  |  | -        if (!eventPath[i].href) continue;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        el = eventPath[i];
 | 
	
		
			
				|  |  | -        break;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // continue ensure link
 | 
	
		
			
				|  |  | -    // el.nodeName for svg links are 'a' instead of 'A'
 | 
	
		
			
				|  |  | -    while (el && 'A' !== el.nodeName.toUpperCase()) el = el.parentNode;
 | 
	
		
			
				|  |  | -    if (!el || 'A' !== el.nodeName.toUpperCase()) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // check if link is inside an svg
 | 
	
		
			
				|  |  | -    // in this case, both href and target are always inside an object
 | 
	
		
			
				|  |  | -    var svg = (typeof el.href === 'object') && el.href.constructor.name === 'SVGAnimatedString';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Ignore if tag has
 | 
	
		
			
				|  |  | -    // 1. "download" attribute
 | 
	
		
			
				|  |  | -    // 2. rel="external" attribute
 | 
	
		
			
				|  |  | -    if (el.hasAttribute('download') || el.getAttribute('rel') === 'external') return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // ensure non-hash for the same path
 | 
	
		
			
				|  |  | -    var link = el.getAttribute('href');
 | 
	
		
			
				|  |  | -    if(!hashbang && samePath(el) && (el.hash || '#' === link)) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Check for mailto: in the href
 | 
	
		
			
				|  |  | -    if (link && link.indexOf('mailto:') > -1) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // check target
 | 
	
		
			
				|  |  | -    // svg target is an object and its desired value is in .baseVal property
 | 
	
		
			
				|  |  | -    if (svg ? el.target.baseVal : el.target) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // x-origin
 | 
	
		
			
				|  |  | -    // note: svg links that are not relative don't call click events (and skip page.js)
 | 
	
		
			
				|  |  | -    // consequently, all svg links tested inside page.js are relative and in the same origin
 | 
	
		
			
				|  |  | -    if (!svg && !sameOrigin(el.href)) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // rebuild path
 | 
	
		
			
				|  |  | -    // There aren't .pathname and .search properties in svg links, so we use href
 | 
	
		
			
				|  |  | -    // Also, svg href is an object and its desired value is in .baseVal property
 | 
	
		
			
				|  |  | -    var path = svg ? el.href.baseVal : (el.pathname + el.search + (el.hash || ''));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    path = path[0] !== '/' ? '/' + path : path;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // strip leading "/[drive letter]:" on NW.js on Windows
 | 
	
		
			
				|  |  | -    if (hasProcess && path.match(/^\/[a-zA-Z]:\//)) {
 | 
	
		
			
				|  |  | -      path = path.replace(/^\/[a-zA-Z]:\//, '/');
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // same page
 | 
	
		
			
				|  |  | -    var orig = path;
 | 
	
		
			
				|  |  | -    var pageBase = getBase();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (path.indexOf(pageBase) === 0) {
 | 
	
		
			
				|  |  | -      path = path.substr(base.length);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (hashbang) path = path.replace('#!', '');
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (pageBase && orig === path) return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    e.preventDefault();
 | 
	
		
			
				|  |  | -    page.show(orig);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Event button.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  function which(e) {
 | 
	
		
			
				|  |  | -    e = e || (hasWindow && window.event);
 | 
	
		
			
				|  |  | -    return null == e.which ? e.button : e.which;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Convert to a URL object
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  function toURL(href) {
 | 
	
		
			
				|  |  | -    if(typeof URL === 'function' && isLocation) {
 | 
	
		
			
				|  |  | -      return new URL(href, location.toString());
 | 
	
		
			
				|  |  | -    } else if (hasDocument) {
 | 
	
		
			
				|  |  | -      var anc = document.createElement('a');
 | 
	
		
			
				|  |  | -      anc.href = href;
 | 
	
		
			
				|  |  | -      return anc;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Check if `href` is the same origin.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  function sameOrigin(href) {
 | 
	
		
			
				|  |  | -    if(!href || !isLocation) return false;
 | 
	
		
			
				|  |  | -    var url = toURL(href);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var loc = pageWindow.location;
 | 
	
		
			
				|  |  | -    return loc.protocol === url.protocol &&
 | 
	
		
			
				|  |  | -      loc.hostname === url.hostname &&
 | 
	
		
			
				|  |  | -      loc.port === url.port;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  function samePath(url) {
 | 
	
		
			
				|  |  | -    if(!isLocation) return false;
 | 
	
		
			
				|  |  | -    var loc = pageWindow.location;
 | 
	
		
			
				|  |  | -    return url.pathname === loc.pathname &&
 | 
	
		
			
				|  |  | -      url.search === loc.search;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Gets the `base`, which depends on whether we are using History or
 | 
	
		
			
				|  |  | -   * hashbang routing.
 | 
	
		
			
				|  |  | +   * Module exports.
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  function getBase() {
 | 
	
		
			
				|  |  | -    if(!!base) return base;
 | 
	
		
			
				|  |  | -    var loc = hasWindow && pageWindow && pageWindow.location;
 | 
	
		
			
				|  |  | -    return (hasWindow && hashbang && loc && loc.protocol === 'file:') ? loc.pathname : base;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  page.sameOrigin = sameOrigin;
 | 
	
		
			
				|  |  | +  var globalPage = createPage();
 | 
	
		
			
				|  |  | +  var page_js = globalPage;
 | 
	
		
			
				|  |  | +  page.default = globalPage;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  return page_js;
 | 
	
		
			
				|  |  |  
 |