router-debug.js revision 8868b979badbb9aeed3c32f3fb02eafead9aedfe
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncYUI.add('router', function(Y) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncProvides URL-based routing using HTML5 `pushState()` or the location hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@submodule router
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@since 3.4.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync**/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncvar HistoryHash = Y.HistoryHash,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync QS = Y.QueryString,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync YArray = Y.Array,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync win = Y.config.win,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync location = win.location,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync origin = location.origin || (location.protocol + '//' + location.host),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // We have to queue up pushState calls to avoid race conditions, since the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // popstate event doesn't actually provide any info on what URL it's
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // associated with.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync saveQueue = [],
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Fired when the router is ready to begin dispatching to route handlers.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync You shouldn't need to wait for this event unless you plan to implement some
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync kind of custom dispatching logic. It's used internally in order to avoid
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync dispatching to an initial route if a browser history change occurs first.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @event ready
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} dispatched `true` if routes have already been dispatched
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (most likely due to a history change).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @fireOnce
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync EVT_READY = 'ready';
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncProvides URL-based routing using HTML5 `pushState()` or the location hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncThis makes it easy to wire up route handlers for different application states
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncwhile providing full back/forward navigation support and bookmarkable, shareable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncURLs.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@class Router
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@param {Object} [config] Config properties.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} [config.html5] Overrides the default capability detection
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync and forces this router to use (`true`) or not use (`false`) HTML5
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync history.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} [config.root=''] Root path from which all routes should be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync evaluated.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Array} [config.routes=[]] Array of route definition objects.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@constructor
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@extends Base
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@since 3.4.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync**/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncfunction Router() {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Router.superclass.constructor.apply(this, arguments);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncY.Router = Y.extend(Router, Y.Base, {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Protected Properties -------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Whether or not `_dispatch()` has been called since this router was
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync instantiated.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _dispatched
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default undefined
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Whether or not we're currently in the process of dispatching to routes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _dispatching
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default undefined
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Cached copy of the `html5` attribute for internal use.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _html5
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Whether or not the `ready` event has fired yet.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _ready
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default undefined
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Regex used to match parameter placeholders in route paths.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Subpattern captures:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 1. Parameter prefix character. Either a `:` for subpath parameters that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync should only match a single level of a path, or `*` for splat parameters
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync that should match any number of path levels.
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync 2. Parameter name.
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync @property _regexPathParam
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync @type RegExp
e7c4c205cb0af88b5ef0786be46da94847a9a37bvboxsync @protected
e7c4c205cb0af88b5ef0786be46da94847a9a37bvboxsync **/
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync _regexPathParam: /([:*])([\w\-]+)/g,
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Regex that matches and captures the query portion of a URL, minus the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync preceding `?` character, and discarding the hash portion of the URL if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _regexUrlQuery
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type RegExp
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _regexUrlQuery: /\?([^#]*).*$/,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Regex that matches everything before the path portion of a URL (the origin).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This will be used to strip this part of the URL from a string when we
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync only want the path.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _regexUrlOrigin
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type RegExp
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _regexUrlOrigin: /^(?:[^\/#?:]+:\/\/|\/\/)[^\/]*/,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Lifecycle Methods ----------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync initializer: function (config) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._html5 = self.get('html5');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._routes = [];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Necessary because setters don't run on init.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._setRoutes(config && config.routes ? config.routes :
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this.get('routes'));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Set up a history instance or hashchange listener.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (self._html5) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._history = new Y.HistoryHTML5({force: true});
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Y.after('history:change', self._afterHistoryChange, self);
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync } else {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync Y.on('hashchange', self._afterHistoryChange, win, self);
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync }
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync // Fire a 'ready' event once we're ready to route. We wait first for all
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync // subclass initializers to finish, then for window.onload, and then an
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync // additional 20ms to allow the browser to fire a useless initial
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync // `popstate` event if it wants to (and Chrome always wants to).
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync self.publish(EVT_READY, {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync defaultFn : self._defReadyFn,
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync fireOnce : true,
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync preventable: false
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync });
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync self.once('initializedChange', function () {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync Y.once('load', function () {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync setTimeout(function () {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync self.fire(EVT_READY, {dispatched: !!self._dispatched});
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync }, 20);
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync });
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync });
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync },
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync destructor: function () {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync if (this._html5) {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync Y.detach('history:change', this._afterHistoryChange, this);
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync } else {
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync Y.detach('hashchange', this._afterHistoryChange, win);
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync }
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync },
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync // -- Public Methods -------------------------------------------------------
4aebc69aadd38c5c13ed4211d60635ad49538275vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Dispatches to the first route handler that matches the current URL, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If `dispatch()` is called before the `ready` event has fired, it will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync automatically wait for the `ready` event before dispatching. Otherwise it
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync will dispatch immediately.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method dispatch
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync dispatch: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this.once(EVT_READY, function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._ready = true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (this._html5 && this.upgrade()) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._dispatch(this._getPath(), this._getURL());
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Gets the current route path, relative to the `root` (if any).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method getPath
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Current route path.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync getPath: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this._getPath();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
241adddf415cbdf66230864a215b24415f482e72vboxsync Returns `true` if this router has at least one route that matches the
241adddf415cbdf66230864a215b24415f482e72vboxsync specified URL, `false` otherwise.
241adddf415cbdf66230864a215b24415f482e72vboxsync
241adddf415cbdf66230864a215b24415f482e72vboxsync This method enforces the same-origin security constraint on the specified
241adddf415cbdf66230864a215b24415f482e72vboxsync `url`; any URL which is not from the same origin as the current URL will
241adddf415cbdf66230864a215b24415f482e72vboxsync always return `false`.
241adddf415cbdf66230864a215b24415f482e72vboxsync
241adddf415cbdf66230864a215b24415f482e72vboxsync @method hasRoute
241adddf415cbdf66230864a215b24415f482e72vboxsync @param {String} url URL to match.
241adddf415cbdf66230864a215b24415f482e72vboxsync @return {Boolean} `true` if there's at least one matching route, `false`
241adddf415cbdf66230864a215b24415f482e72vboxsync otherwise.
241adddf415cbdf66230864a215b24415f482e72vboxsync **/
241adddf415cbdf66230864a215b24415f482e72vboxsync hasRoute: function (url) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!this._hasSameOrigin(url)) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync return !!this.match(this.removeRoot(url)).length;
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Returns an array of route objects that match the specified URL path.
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync This method is called internally to determine which routes match the current
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync path whenever the URL changes. You may override it if you want to customize
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync the route matching logic, although this usually shouldn't be necessary.
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync Each returned route object has the following properties:
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync * `callback`: A function or a string representing the name of a function
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync this router that should be executed when the route is triggered.
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync * `keys`: An array of strings representing the named parameters defined in
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the route's path specification, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `path`: The route's path specification, which may be either a string or
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync a regex.
241adddf415cbdf66230864a215b24415f482e72vboxsync * `regex`: A regular expression version of the route's path specification.
241adddf415cbdf66230864a215b24415f482e72vboxsync This regex is used to determine whether the route matches a given path.
241adddf415cbdf66230864a215b24415f482e72vboxsync
241adddf415cbdf66230864a215b24415f482e72vboxsync @example
241adddf415cbdf66230864a215b24415f482e72vboxsync router.route('/foo', function () {});
241adddf415cbdf66230864a215b24415f482e72vboxsync router.match('/foo');
241adddf415cbdf66230864a215b24415f482e72vboxsync // => [{callback: ..., keys: [], path: '/foo', regex: ...}]
241adddf415cbdf66230864a215b24415f482e72vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method match
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} path URL path to match.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object[]} Array of route objects that match the specified path.
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync **/
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync match: function (path) {
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync return YArray.filter(this._routes, function (route) {
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync return path.search(route.regex) > -1;
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync });
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync },
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync /**
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync Removes the `root` URL from the front of _url_ (if it's there) and returns
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync the result. The returned path will always have a leading `/`.
a8ce9568e18b8c1a49833bf3b3ac2b2cc634b13cvboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method removeRoot
241adddf415cbdf66230864a215b24415f482e72vboxsync @param {String} url URL.
241adddf415cbdf66230864a215b24415f482e72vboxsync @return {String} Rootless path.
241adddf415cbdf66230864a215b24415f482e72vboxsync **/
241adddf415cbdf66230864a215b24415f482e72vboxsync removeRoot: function (url) {
241adddf415cbdf66230864a215b24415f482e72vboxsync var root = this.get('root');
241adddf415cbdf66230864a215b24415f482e72vboxsync
241adddf415cbdf66230864a215b24415f482e72vboxsync // Strip out the non-path part of the URL, if any (e.g.
241adddf415cbdf66230864a215b24415f482e72vboxsync // "http://foo.com"), so that we're left with just the path.
241adddf415cbdf66230864a215b24415f482e72vboxsync url = url.replace(this._regexUrlOrigin, '');
241adddf415cbdf66230864a215b24415f482e72vboxsync
241adddf415cbdf66230864a215b24415f482e72vboxsync if (root && url.indexOf(root) === 0) {
241adddf415cbdf66230864a215b24415f482e72vboxsync url = url.substring(root.length);
241adddf415cbdf66230864a215b24415f482e72vboxsync }
241adddf415cbdf66230864a215b24415f482e72vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return url.charAt(0) === '/' ? url : '/' + url;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Replaces the current browser history entry with a new one, and dispatches to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the first matching route handler, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Behind the scenes, this method uses HTML5 `pushState()` in browsers that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync support it (or the location hash in older browsers and IE) to change the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The specified URL must share the same origin (i.e., protocol, host, and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync port) as the current page, or an error will occur.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @example
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Starting URL: http://example.com/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.replace('/path/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // New URL: http://example.com/path/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.replace('/path?foo=bar');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // New URL: http://example.com/path?foo=bar
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.replace('/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // New URL: http://example.com/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method replace
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} [url] URL to set. This URL needs to be of the same origin as
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the current URL. This can be a URL relative to the router's `root`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attribute. If no URL is specified, the page's current URL will be used.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @see save()
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync replace: function (url) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this._queue(url, true);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Adds a route handler for the specified URL _path_.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The _path_ parameter may be either a string or a regular expression. If it's
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync a string, it may contain named parameters: `:param` will match any single
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync part of a URL path (not including `/` characters), and `*param` will match
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync any number of parts of a URL path (including `/` characters). These named
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync parameters will be made available as keys on the `req.params` object that's
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync passed to route handlers.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If the _path_ parameter is a regex, all pattern matches will be made
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync available as numbered keys on `req.params`, starting with `0` for the full
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync match, then `1` for the first subpattern match, and so on.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Here's a set of sample routes along with URL paths that they match:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Route: `/photos/:tag/:page`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * URL: `/photos/kittens/1`, params: `{tag: 'kittens', page: '1'}`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * URL: `/photos/puppies/2`, params: `{tag: 'puppies', page: '2'}`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Route: `/file/*path`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * URL: `/file/foo/bar/baz.txt`, params: `{path: 'foo/bar/baz.txt'}`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * URL: `/file/foo`, params: `{path: 'foo'}`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If multiple route handlers match a given URL, they will be executed in the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync order they were added. The first route that was added will be the first to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be executed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @example
4791a729647f035b6561d292c9f848dd1fc797a9vboxsync router.route('/photos/:tag/:page', function (req, res, next) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Y.log('Current tag: ' + req.params.tag);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Y.log('Current page number: ' + req.params.page);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method route
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String|RegExp} path Path to match. May be a string or a regular
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync expression.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Function|String} callback Callback function to call whenever this
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync route is triggered. If specified as a string, the named function will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync called on this router instance.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} callback.req Request object containing information about
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the request. It contains the following properties.
3dd1d8fdf12303b292d9ee378edbc5f5fb6d6cb5vboxsync @param {Array|Object} callback.req.params Captured parameters matched by
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the route path specification. If a string path was used and contained
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync named parameters, then this will be a key/value hash mapping parameter
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync names to their matched values. If a regex path was used, this will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync an array of subpattern matches starting at index 0 for the full match,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync then 1 for the first subpattern match, and so on.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} callback.req.path The current URL path.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} callback.req.query Query hash representing the URL query
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync string, if any. Parameter names are keys, and are mapped to parameter
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync values.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} callback.req.url The full URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} callback.req.src What initiated the dispatch. In an
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync HTML5 browser, when the back/forward buttons are used, this property
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync will have a value of "popstate".
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} callback.res Response object containing methods and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync information that relate to responding to a request. It contains the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync following properties.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} callback.res.req Reference to the request object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Function} callback.next Callback to pass control to the next
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync matching route. If you don't call this function, then no further route
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync handlers will be executed, even if there are more that match. If you do
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync call this function, then the next matching route handler (if any) will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be called, and will receive the same `req` object that was passed to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this route (so you can use the request object to pass data along to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync subsequent routes).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync route: function (path, callback) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var keys = [];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._routes.push({
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync callback: callback,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync keys : keys,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync path : path,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync regex : this._getRegex(path, keys)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Saves a new browser history entry and dispatches to the first matching route
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync handler, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Behind the scenes, this method uses HTML5 `pushState()` in browsers that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync support it (or the location hash in older browsers and IE) to change the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync URL and create a history entry.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The specified URL must share the same origin (i.e., protocol, host, and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync port) as the current page, or an error will occur.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @example
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Starting URL: http://example.com/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.save('/path/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // New URL: http://example.com/path/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.save('/path?foo=bar');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // New URL: http://example.com/path?foo=bar
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.save('/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // New URL: http://example.com/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} [url] URL to set. This URL needs to be of the same origin as
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the current URL. This can be a URL relative to the router's `root`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attribute. If no URL is specified, the page's current URL will be used.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @see replace()
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync save: function (url) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this._queue(url);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Upgrades a hash-based URL to an HTML5 URL if necessary. In non-HTML5
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync browsers, this method is a noop.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method upgrade
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Boolean} `true` if the URL was upgraded, `false` otherwise.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync upgrade: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!this._html5) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Get the full hash in all its glory!
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var hash = HistoryHash.getHash();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (hash && hash.charAt(0) === '/') {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // This is an HTML5 browser and we have a hash-based path in the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // URL, so we need to upgrade the URL to a non-hash URL. This
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // will trigger a `history:change` event, which will in turn
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // trigger a dispatch.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this.once(EVT_READY, function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this.replace(hash);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Protected Methods ----------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Wrapper around `decodeURIComponent` that also converts `+` chars into
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync spaces.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _decode
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} string String to decode.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Decoded string.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _decode: function (string) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return decodeURIComponent(string.replace(/\+/g, ' '));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Shifts the topmost `_save()` call off the queue and executes it. Does
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync nothing if the queue is empty.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _dequeue
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @see _queue
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _dequeue: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fn;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // If window.onload hasn't yet fired, wait until it has before
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // dequeueing. This will ensure that we don't call pushState() before an
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // initial popstate event has fired.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!YUI.Env.windowLoaded) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Y.once('load', function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._dequeue();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync fn = saveQueue.shift();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return fn ? fn() : this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Dispatches to the first route handler that matches the specified _path_.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If called before the `ready` event has fired, the dispatch will be aborted.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This ensures normalized behavior between Chrome (which fires a `popstate`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync event on every pageview) and other browsers (which do not).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _dispatch
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} path URL path.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} url Full URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} src What initiated the dispatch.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _dispatch: function (path, url, src) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync routes = self.match(path),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync req, res;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._dispatching = self._dispatched = true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!routes || !routes.length) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._dispatching = false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return self;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync req = self._getRequest(path, url, src);
fd60bfdb327b9b1e7a6d084cf368fb7f07c566cfvboxsync res = self._getResponse(req);
223935479ac42db56b7b7a7d16548d590022996avboxsync
223935479ac42db56b7b7a7d16548d590022996avboxsync req.next = function (err) {
223935479ac42db56b7b7a7d16548d590022996avboxsync var callback, matches, route;
223935479ac42db56b7b7a7d16548d590022996avboxsync
fd60bfdb327b9b1e7a6d084cf368fb7f07c566cfvboxsync if (err) {
fd60bfdb327b9b1e7a6d084cf368fb7f07c566cfvboxsync Y.error(err);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else if ((route = routes.shift())) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync matches = route.regex.exec(path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync callback = typeof route.callback === 'string' ?
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self[route.callback] : route.callback;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Use named keys for parameter names if the route path contains
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // named keys. Otherwise, use numerical match indices.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (matches.length === route.keys.length + 1) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync req.params = YArray.hash(route.keys, matches.slice(1));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync req.params = matches.concat();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync callback.call(self, req, res, req.next);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync };
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync req.next();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._dispatching = false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return self._dequeue();
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync },
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync /**
64863d3a0ffadf1ac248b295b78be5d55db6ee13vboxsync Gets the current path from the location hash, or an empty string if the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync hash is empty.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getHashPath
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Current hash path, or an empty string if the hash is empty.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getHashPath: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return HistoryHash.getHash().replace(this._regexUrlQuery, '');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Gets the location origin (i.e., protocol, host, and port) as a URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @example
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync http://example.com
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getOrigin
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Location origin (i.e., protocol, host, and port).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getOrigin: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return origin;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Gets the current route path, relative to the `root` (if any).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getPath
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Current route path.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getPath: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var path = (!this._html5 && this._getHashPath()) || location.pathname;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this.removeRoot(path);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Gets the current route query string.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getQuery
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Current route query string.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getQuery: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (this._html5) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return location.search.substring(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var hash = HistoryHash.getHash(),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync matches = hash.match(this._regexUrlQuery);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return hash && matches ? matches[1] : location.search.substring(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Creates a regular expression from the given route specification. If _path_
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync is already a regex, it will be returned unmodified.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getRegex
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String|RegExp} path Route path specification.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Array} keys Array reference to which route parameter names will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync added.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {RegExp} Route regex.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getRegex: function (path, keys) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (path instanceof RegExp) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return path;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Special case for catchall paths.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (path === '*') {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return /.*/;
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync }
2927a95ee3fe77d319ee5959368c7dfc119a96fbvboxsync
2927a95ee3fe77d319ee5959368c7dfc119a96fbvboxsync path = path.replace(this._regexPathParam, function (match, operator, key) {
2927a95ee3fe77d319ee5959368c7dfc119a96fbvboxsync keys.push(key);
2927a95ee3fe77d319ee5959368c7dfc119a96fbvboxsync return operator === '*' ? '(.*?)' : '([^/]*)';
2927a95ee3fe77d319ee5959368c7dfc119a96fbvboxsync });
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync return new RegExp('^' + path + '$');
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync },
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync /**
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync Gets a request object that can be passed to a route handler.
574d36adfdd4d9e62af3640ecde108bdefb1c663vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getRequest
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} path Current path being dispatched.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} url Current full URL being dispatched.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} src What initiated the dispatch.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object} Request object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getRequest: function (path, url, src) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync path : path,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync query: this._parseQuery(this._getQuery()),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync url : url,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync src : src
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync };
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Gets a response object that can be passed to a route handler.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _getResponse
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} req Request object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object} Response Object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getResponse: function (req) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // For backwards compatibility, the response object is a function that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // calls `next()` on the request object and returns the result.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var res = function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return req.next.apply(this, arguments);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync };
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
3e0090e25f336e84cefbe2697bec04151abfc44dvboxsync res.req = req;
3e0090e25f336e84cefbe2697bec04151abfc44dvboxsync return res;
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync },
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync /**
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync Getter for the `routes` attribute.
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync @method _getRoutes
3e0090e25f336e84cefbe2697bec04151abfc44dvboxsync @return {Object[]} Array of route objects.
3e0090e25f336e84cefbe2697bec04151abfc44dvboxsync @protected
3e0090e25f336e84cefbe2697bec04151abfc44dvboxsync **/
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync _getRoutes: function () {
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync return this._routes.concat();
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync },
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync
d2f75d9ba9861d2f77e46d06b818eff7dc680982vboxsync /**
5f33a06f645ac83b9e28a1b792fd80df96676e11vboxsync Gets the current full URL.
5f33a06f645ac83b9e28a1b792fd80df96676e11vboxsync
3e0090e25f336e84cefbe2697bec04151abfc44dvboxsync @method _getURL
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _getURL: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return location.toString();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Returns `true` when the specified `url` is from the same origin as the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync current URL; i.e., the protocol, host, and port of the URLs are the same.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync All host or path relative URLs are of the same origin. A scheme-relative URL
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync is first prefixed with the current scheme before being evaluated.
447cbf113f44132911fc13dc33cb26603759b82evboxsync
447cbf113f44132911fc13dc33cb26603759b82evboxsync @method _hasSameOrigin
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} url URL to compare origin with the current URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Boolean} Whether the URL has the same origin of the current URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _hasSameOrigin: function (url) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var origin = ((url && url.match(this._regexUrlOrigin)) || [])[0];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Prepend current scheme to scheme-relative URLs.
447cbf113f44132911fc13dc33cb26603759b82evboxsync if (origin && origin.indexOf('//') === 0) {
447cbf113f44132911fc13dc33cb26603759b82evboxsync origin = location.protocol + origin;
447cbf113f44132911fc13dc33cb26603759b82evboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return !origin || origin === this._getOrigin();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Joins the `root` URL to the specified _url_, normalizing leading/trailing
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `/` characters.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @example
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.set('root', '/foo');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router._joinURL('bar'); // => '/foo/bar'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router._joinURL('/bar'); // => '/foo/bar'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router.set('root', '/foo/');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router._joinURL('bar'); // => '/foo/bar'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync router._joinURL('/bar'); // => '/foo/bar'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _joinURL
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} url URL to append to the `root` URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {String} Joined URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _joinURL: function (url) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var root = this.get('root');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync url = this.removeRoot(url);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (url.charAt(0) === '/') {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync url = url.substring(1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return root && root.charAt(root.length - 1) === '/' ?
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync root + url :
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync root + '/' + url;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Parses a URL query string into a key/value hash. If `Y.QueryString.parse` is
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync available, this method will be an alias to that.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _parseQuery
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} query Query string to parse.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object} Hash of key/value pairs for query parameters.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _parseQuery: QS && QS.parse ? QS.parse : function (query) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var decode = this._decode,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync params = query.split('&'),
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync i = 0,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync len = params.length,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync result = {},
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync param;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (; i < len; ++i) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync param = params[i].split('=');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (param[0]) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync result[decode(param[0])] = decode(param[1] || '');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return result;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Queues up a `_save()` call to run after all previously-queued calls have
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync finished.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This is necessary because if we make multiple `_save()` calls before the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync first call gets dispatched, then both calls will dispatch to the last call's
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync All arguments passed to `_queue()` will be passed on to `_save()` when the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync queued function is executed.
447cbf113f44132911fc13dc33cb26603759b82evboxsync
4fac78486305f1f002adbf23953382e5d832af94vboxsync @method _queue
447cbf113f44132911fc13dc33cb26603759b82evboxsync @chainable
447cbf113f44132911fc13dc33cb26603759b82evboxsync @see _dequeue
447cbf113f44132911fc13dc33cb26603759b82evboxsync @protected
447cbf113f44132911fc13dc33cb26603759b82evboxsync **/
447cbf113f44132911fc13dc33cb26603759b82evboxsync _queue: function () {
447cbf113f44132911fc13dc33cb26603759b82evboxsync var args = arguments,
4fac78486305f1f002adbf23953382e5d832af94vboxsync self = this;
447cbf113f44132911fc13dc33cb26603759b82evboxsync
4fac78486305f1f002adbf23953382e5d832af94vboxsync saveQueue.push(function () {
447cbf113f44132911fc13dc33cb26603759b82evboxsync if (self._html5) {
447cbf113f44132911fc13dc33cb26603759b82evboxsync if (Y.UA.ios && Y.UA.ios < 5) {
447cbf113f44132911fc13dc33cb26603759b82evboxsync // iOS <5 has buggy HTML5 history support, and needs to be
447cbf113f44132911fc13dc33cb26603759b82evboxsync // synchronous.
4fac78486305f1f002adbf23953382e5d832af94vboxsync self._save.apply(self, args);
447cbf113f44132911fc13dc33cb26603759b82evboxsync } else {
447cbf113f44132911fc13dc33cb26603759b82evboxsync // Wrapped in a timeout to ensure that _save() calls are
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // always processed asynchronously. This ensures consistency
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // between HTML5- and hash-based history.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync setTimeout(function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._save.apply(self, args);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }, 1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._dispatching = true; // otherwise we'll dequeue too quickly
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._save.apply(self, args);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return self;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return !this._dispatching ? this._dequeue() : this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Saves a history entry using either `pushState()` or the location hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This method enforces the same-origin security constraint; attempting to save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync a `url` that is not from the same origin as the current URL will result in
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync an error.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} [url] URL for the history entry.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} [replace=false] If `true`, the current history entry will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be replaced instead of a new one being added.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @chainable
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _save: function (url, replace) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var urlIsString = typeof url === 'string';
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Perform same-origin check on the specified URL.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (urlIsString && !this._hasSameOrigin(url)) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Y.error('Security error: The new URL must be of the same origin as the current URL.');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Force _ready to true to ensure that the history change is handled
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // even if _save is called before the `ready` event fires.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._ready = true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (this._html5) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._history[replace ? 'replace' : 'add'](null, {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync url: urlIsString ? this._joinURL(url) : url
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync });
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Remove the root from the URL before it's set as the hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync urlIsString && (url = this.removeRoot(url));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // The `hashchange` event only fires when the new hash is actually
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // different. This makes sure we'll always dequeue and dispatch,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // mimicking the HTML5 behavior.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (url === HistoryHash.getHash()) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._dispatch(this._getPath(), this._getURL());
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } else {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync HistoryHash[replace ? 'replaceHash' : 'setHash'](url);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Setter for the `routes` attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _setRoutes
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object[]} routes Array of route objects.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object[]} Array of route objects.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _setRoutes: function (routes) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._routes = [];
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync YArray.each(routes, function (route) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this.route(route.path, route.callback);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }, this);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this._routes.concat();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Protected Event Handlers ---------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Handles `history:change` and `hashchange` events.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _afterHistoryChange
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {EventFacade} e
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync _afterHistoryChange: function (e) {
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync var self = this,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync src = e.src;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (self._ready || src !== 'popstate') {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self._dispatch(self._getPath(), self._getURL(), src);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Default Event Handlers -----------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Default handler for the `ready` event.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _defReadyFn
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {EventFacade} e
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @protected
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _defReadyFn: function (e) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this._ready = true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}, {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Static Properties ----------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync NAME: 'router',
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ATTRS: {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Whether or not this browser is capable of using HTML5 history.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Setting this to `false` will force the use of hash-based history even on
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync HTML5 browsers, but please don't do this unless you understand the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync consequences.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @attribute html5
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @initOnly
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync html5: {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Android versions lower than 3.0 are buggy and don't update
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // window.location after a pushState() call, so we fall back to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // hash-based history for them.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync //
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // See http://code.google.com/p/android/issues/detail?id=17471
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync valueFn: function () { return Y.Router.html5; },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync writeOnce: 'initOnly'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Absolute root path from which all routes should be evaluated.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync For example, if your router is running on a page at
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `http://example.com/myapp/` and you add a route with the path `/`, your
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync route will never execute, because the path will always be preceded by
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `/myapp`. Setting `root` to `/myapp` would cause all routes to be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync evaluated relative to that root URL, so the `/` route would then execute
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync when the user browses to `http://example.com/myapp/`.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @attribute root
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type String
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default `''`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync root: {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync value: ''
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Array of route objects.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Each item in the array must be an object with the following properties:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `path`: String or regex representing the path to match. See the docs
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for the `route()` method for more details.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `callback`: Function or a string representing the name of a function
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync on this router instance that should be called when the route is
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync triggered. See the docs for the `route()` method for more details.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This attribute is intended to be used to set routes at init time, or to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync completely reset all routes after init. To add routes after init without
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync resetting all existing routes, use the `route()` method.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @attribute routes
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Object[]
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default `[]`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @see route
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync **/
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync routes: {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync value : [],
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync getter: '_getRoutes',
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync setter: '_setRoutes'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync }
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync },
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Used as the default value for the `html5` attribute, and for testing.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync html5: Y.HistoryBase.html5 && (!Y.UA.android || Y.UA.android >= 3)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync});
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/**
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncThe `Controller` class was deprecated in YUI 3.5.0 and is now an alias for the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync`Router` class. Use that class instead. This alias will be removed in a future
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncversion of YUI.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@class Controller
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@constructor
4791a729647f035b6561d292c9f848dd1fc797a9vboxsync@extends Base
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@deprecated Use `Router` instead.
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync@see Router
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync**/
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsyncY.Controller = Y.Router;
859c9a7cc74066a52cf7e76d54169859e7705c3dvboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}, '@VERSION@' ,{optional:['querystring-parse'], requires:['array-extras', 'base-build', 'history']});
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync