src/cm/media/js/lib/yui/yui3-3.15.0/build/router/router.js
author Yves-Marie Haussonne <ymh.work+github@gmail.com>
Fri, 09 May 2014 18:35:26 +0200
changeset 656 a84519031134
parent 602 e16a97fb364a
permissions -rw-r--r--
add link to "privacy policy" in the header test
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
602
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     1
YUI.add('router', function (Y, NAME) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     2
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     3
/**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     4
Provides URL-based routing using HTML5 `pushState()` or the location hash.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     5
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     6
@module app
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     7
@submodule router
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     8
@since 3.4.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
     9
**/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    10
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    11
var HistoryHash = Y.HistoryHash,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    12
    QS          = Y.QueryString,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    13
    YArray      = Y.Array,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    14
    YLang       = Y.Lang,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    15
    YObject     = Y.Object,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    16
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    17
    win = Y.config.win,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    18
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    19
    // Holds all the active router instances. This supports the static
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    20
    // `dispatch()` method which causes all routers to dispatch.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    21
    instances = [],
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    22
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    23
    // We have to queue up pushState calls to avoid race conditions, since the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    24
    // popstate event doesn't actually provide any info on what URL it's
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    25
    // associated with.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    26
    saveQueue = [],
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    27
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    28
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    29
    Fired when the router is ready to begin dispatching to route handlers.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    30
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    31
    You shouldn't need to wait for this event unless you plan to implement some
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    32
    kind of custom dispatching logic. It's used internally in order to avoid
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    33
    dispatching to an initial route if a browser history change occurs first.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    34
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    35
    @event ready
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    36
    @param {Boolean} dispatched `true` if routes have already been dispatched
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    37
      (most likely due to a history change).
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    38
    @fireOnce
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    39
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    40
    EVT_READY = 'ready';
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    41
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    42
/**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    43
Provides URL-based routing using HTML5 `pushState()` or the location hash.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    44
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    45
This makes it easy to wire up route handlers for different application states
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    46
while providing full back/forward navigation support and bookmarkable, shareable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    47
URLs.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    48
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    49
@class Router
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    50
@param {Object} [config] Config properties.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    51
    @param {Boolean} [config.html5] Overrides the default capability detection
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    52
        and forces this router to use (`true`) or not use (`false`) HTML5
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    53
        history.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    54
    @param {String} [config.root=''] Root path from which all routes should be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    55
        evaluated.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    56
    @param {Array} [config.routes=[]] Array of route definition objects.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    57
@constructor
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    58
@extends Base
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    59
@since 3.4.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    60
**/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    61
function Router() {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    62
    Router.superclass.constructor.apply(this, arguments);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    63
}
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    64
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    65
Y.Router = Y.extend(Router, Y.Base, {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    66
    // -- Protected Properties -------------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    67
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    68
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    69
    Whether or not `_dispatch()` has been called since this router was
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    70
    instantiated.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    71
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    72
    @property _dispatched
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    73
    @type Boolean
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    74
    @default undefined
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    75
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    76
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    77
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    78
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    79
    Whether or not we're currently in the process of dispatching to routes.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    80
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    81
    @property _dispatching
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    82
    @type Boolean
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    83
    @default undefined
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    84
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    85
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    86
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    87
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    88
    History event handle for the `history:change` or `hashchange` event
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    89
    subscription.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    90
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    91
    @property _historyEvents
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    92
    @type EventHandle
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    93
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    94
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    95
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    96
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    97
    Cached copy of the `html5` attribute for internal use.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    98
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
    99
    @property _html5
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   100
    @type Boolean
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   101
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   102
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   103
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   104
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   105
    Map which holds the registered param handlers in the form:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   106
    `name` -> RegExp | Function.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   107
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   108
    @property _params
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   109
    @type Object
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   110
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   111
    @since 3.12.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   112
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   113
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   114
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   115
    Whether or not the `ready` event has fired yet.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   116
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   117
    @property _ready
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   118
    @type Boolean
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   119
    @default undefined
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   120
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   121
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   122
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   123
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   124
    Regex used to break up a URL string around the URL's path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   125
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   126
    Subpattern captures:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   127
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   128
      1. Origin, everything before the URL's path-part.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   129
      2. The URL's path-part.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   130
      3. The URL's query.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   131
      4. The URL's hash fragment.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   132
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   133
    @property _regexURL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   134
    @type RegExp
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   135
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   136
    @since 3.5.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   137
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   138
    _regexURL: /^((?:[^\/#?:]+:\/\/|\/\/)[^\/]*)?([^?#]*)(\?[^#]*)?(#.*)?$/,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   139
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   140
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   141
    Regex used to match parameter placeholders in route paths.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   142
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   143
    Subpattern captures:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   144
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   145
      1. Parameter prefix character. Either a `:` for subpath parameters that
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   146
         should only match a single level of a path, or `*` for splat parameters
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   147
         that should match any number of path levels.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   148
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   149
      2. Parameter name, if specified, otherwise it is a wildcard match.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   150
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   151
    @property _regexPathParam
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   152
    @type RegExp
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   153
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   154
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   155
    _regexPathParam: /([:*])([\w\-]+)?/g,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   156
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   157
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   158
    Regex that matches and captures the query portion of a URL, minus the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   159
    preceding `?` character, and discarding the hash portion of the URL if any.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   160
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   161
    @property _regexUrlQuery
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   162
    @type RegExp
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   163
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   164
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   165
    _regexUrlQuery: /\?([^#]*).*$/,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   166
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   167
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   168
    Regex that matches everything before the path portion of a URL (the origin).
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   169
    This will be used to strip this part of the URL from a string when we
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   170
    only want the path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   171
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   172
    @property _regexUrlOrigin
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   173
    @type RegExp
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   174
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   175
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   176
    _regexUrlOrigin: /^(?:[^\/#?:]+:\/\/|\/\/)[^\/]*/,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   177
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   178
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   179
    Collection of registered routes.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   180
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   181
    @property _routes
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   182
    @type Array
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   183
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   184
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   185
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   186
    // -- Lifecycle Methods ----------------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   187
    initializer: function (config) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   188
        var self = this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   189
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   190
        self._html5  = self.get('html5');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   191
        self._params = {};
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   192
        self._routes = [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   193
        self._url    = self._getURL();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   194
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   195
        // Necessary because setters don't run on init.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   196
        self._setRoutes(config && config.routes ? config.routes :
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   197
                self.get('routes'));
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   198
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   199
        // Set up a history instance or hashchange listener.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   200
        if (self._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   201
            self._history       = new Y.HistoryHTML5({force: true});
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   202
            self._historyEvents =
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   203
                    Y.after('history:change', self._afterHistoryChange, self);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   204
        } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   205
            self._historyEvents =
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   206
                    Y.on('hashchange', self._afterHistoryChange, win, self);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   207
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   208
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   209
        // Fire a `ready` event once we're ready to route. We wait first for all
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   210
        // subclass initializers to finish, then for window.onload, and then an
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   211
        // additional 20ms to allow the browser to fire a useless initial
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   212
        // `popstate` event if it wants to (and Chrome always wants to).
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   213
        self.publish(EVT_READY, {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   214
            defaultFn  : self._defReadyFn,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   215
            fireOnce   : true,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   216
            preventable: false
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   217
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   218
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   219
        self.once('initializedChange', function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   220
            Y.once('load', function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   221
                setTimeout(function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   222
                    self.fire(EVT_READY, {dispatched: !!self._dispatched});
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   223
                }, 20);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   224
            });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   225
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   226
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   227
        // Store this router in the collection of all active router instances.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   228
        instances.push(this);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   229
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   230
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   231
    destructor: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   232
        var instanceIndex = YArray.indexOf(instances, this);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   233
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   234
        // Remove this router from the collection of active router instances.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   235
        if (instanceIndex > -1) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   236
            instances.splice(instanceIndex, 1);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   237
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   238
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   239
        if (this._historyEvents) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   240
            this._historyEvents.detach();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   241
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   242
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   243
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   244
    // -- Public Methods -------------------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   245
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   246
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   247
    Dispatches to the first route handler that matches the current URL, if any.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   248
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   249
    If `dispatch()` is called before the `ready` event has fired, it will
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   250
    automatically wait for the `ready` event before dispatching. Otherwise it
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   251
    will dispatch immediately.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   252
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   253
    @method dispatch
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   254
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   255
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   256
    dispatch: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   257
        this.once(EVT_READY, function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   258
            var req, res;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   259
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   260
            this._ready = true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   261
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   262
            if (!this.upgrade()) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   263
                req = this._getRequest('dispatch');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   264
                res = this._getResponse(req);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   265
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   266
                this._dispatch(req, res);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   267
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   268
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   269
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   270
        return this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   271
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   272
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   273
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   274
    Gets the current route path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   275
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   276
    @method getPath
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   277
    @return {String} Current route path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   278
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   279
    getPath: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   280
        return this._getPath();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   281
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   282
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   283
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   284
    Returns `true` if this router has at least one route that matches the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   285
    specified URL, `false` otherwise.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   286
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   287
    This method enforces the same-origin security constraint on the specified
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   288
    `url`; any URL which is not from the same origin as the current URL will
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   289
    always return `false`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   290
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   291
    @method hasRoute
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   292
    @param {String} url URL to match.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   293
    @return {Boolean} `true` if there's at least one matching route, `false`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   294
      otherwise.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   295
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   296
    hasRoute: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   297
        var path;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   298
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   299
        if (!this._hasSameOrigin(url)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   300
            return false;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   301
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   302
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   303
        if (!this._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   304
            url = this._upgradeURL(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   305
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   306
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   307
        // Get just the path portion of the specified `url`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   308
        path = this.removeQuery(url.replace(this._regexUrlOrigin, ''));
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   309
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   310
        return !!this.match(path).length;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   311
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   312
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   313
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   314
    Returns an array of route objects that match the specified URL path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   315
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   316
    If this router has a `root`, then the specified `path` _must_ be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   317
    semantically within the `root` path to match any routes.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   318
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   319
    This method is called internally to determine which routes match the current
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   320
    path whenever the URL changes. You may override it if you want to customize
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   321
    the route matching logic, although this usually shouldn't be necessary.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   322
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   323
    Each returned route object has the following properties:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   324
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   325
      * `callback`: A function or a string representing the name of a function
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   326
        this router that should be executed when the route is triggered.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   327
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   328
      * `keys`: An array of strings representing the named parameters defined in
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   329
        the route's path specification, if any.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   330
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   331
      * `path`: The route's path specification, which may be either a string or
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   332
        a regex.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   333
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   334
      * `regex`: A regular expression version of the route's path specification.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   335
        This regex is used to determine whether the route matches a given path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   336
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   337
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   338
        router.route('/foo', function () {});
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   339
        router.match('/foo');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   340
        // => [{callback: ..., keys: [], path: '/foo', regex: ...}]
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   341
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   342
    @method match
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   343
    @param {String} path URL path to match. This should be an absolute path that
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   344
        starts with a slash: "/".
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   345
    @return {Object[]} Array of route objects that match the specified path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   346
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   347
    match: function (path) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   348
        var root = this.get('root');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   349
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   350
        if (root) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   351
            // The `path` must be semantically within this router's `root` path
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   352
            // or mount point, if it's not then no routes should be considered a
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   353
            // match.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   354
            if (!this._pathHasRoot(root, path)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   355
                return [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   356
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   357
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   358
            // Remove this router's `root` from the `path` before checking the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   359
            // routes for any matches.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   360
            path = this.removeRoot(path);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   361
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   362
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   363
        return YArray.filter(this._routes, function (route) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   364
            return path.search(route.regex) > -1;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   365
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   366
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   367
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   368
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   369
    Adds a handler for a route param specified by _name_.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   370
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   371
    Param handlers can be registered via this method and are used to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   372
    validate/format values of named params in routes before dispatching to the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   373
    route's handler functions. Using param handlers allows routes to defined
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   374
    using string paths which allows for `req.params` to use named params, but
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   375
    still applying extra validation or formatting to the param values parsed
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   376
    from the URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   377
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   378
    If a param handler regex or function returns a value of `false`, `null`,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   379
    `undefined`, or `NaN`, the current route will not match and be skipped. All
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   380
    other return values will be used in place of the original param value parsed
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   381
    from the URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   382
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   383
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   384
        router.param('postId', function (value) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   385
            return parseInt(value, 10);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   386
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   387
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   388
        router.param('username', /^\w+$/);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   389
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   390
        router.route('/posts/:postId', function (req) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   391
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   392
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   393
        router.route('/users/:username', function (req) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   394
            // `req.params.username` is an array because the result of calling
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   395
            // `exec()` on the regex is assigned as the param's value.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   396
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   397
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   398
        router.route('*', function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   399
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   400
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   401
        // URLs which match routes:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   402
        router.save('/posts/1');     // => "Post: 1"
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   403
        router.save('/users/ericf'); // => "User: ericf"
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   404
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   405
        // URLs which do not match routes because params fail validation:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   406
        router.save('/posts/a');            // => "Catch-all no routes matched!"
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   407
        router.save('/users/ericf,rgrove'); // => "Catch-all no routes matched!"
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   408
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   409
    @method param
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   410
    @param {String} name Name of the param used in route paths.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   411
    @param {Function|RegExp} handler Function to invoke or regular expression to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   412
        `exec()` during route dispatching whose return value is used as the new
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   413
        param value. Values of `false`, `null`, `undefined`, or `NaN` will cause
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   414
        the current route to not match and be skipped. When a function is
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   415
        specified, it will be invoked in the context of this instance with the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   416
        following parameters:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   417
      @param {String} handler.value The current param value parsed from the URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   418
      @param {String} handler.name The name of the param.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   419
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   420
    @since 3.12.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   421
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   422
    param: function (name, handler) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   423
        this._params[name] = handler;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   424
        return this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   425
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   426
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   427
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   428
    Removes the `root` URL from the front of _url_ (if it's there) and returns
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   429
    the result. The returned path will always have a leading `/`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   430
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   431
    @method removeRoot
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   432
    @param {String} url URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   433
    @return {String} Rootless path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   434
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   435
    removeRoot: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   436
        var root = this.get('root'),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   437
            path;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   438
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   439
        // Strip out the non-path part of the URL, if any (e.g.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   440
        // "http://foo.com"), so that we're left with just the path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   441
        url = url.replace(this._regexUrlOrigin, '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   442
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   443
        // Return the host-less URL if there's no `root` path to further remove.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   444
        if (!root) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   445
            return url;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   446
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   447
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   448
        path = this.removeQuery(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   449
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   450
        // Remove the `root` from the `url` if it's the same or its path is
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   451
        // semantically within the root path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   452
        if (path === root || this._pathHasRoot(root, path)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   453
            url = url.substring(root.length);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   454
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   455
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   456
        return url.charAt(0) === '/' ? url : '/' + url;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   457
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   458
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   459
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   460
    Removes a query string from the end of the _url_ (if one exists) and returns
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   461
    the result.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   462
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   463
    @method removeQuery
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   464
    @param {String} url URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   465
    @return {String} Queryless path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   466
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   467
    removeQuery: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   468
        return url.replace(/\?.*$/, '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   469
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   470
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   471
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   472
    Replaces the current browser history entry with a new one, and dispatches to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   473
    the first matching route handler, if any.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   474
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   475
    Behind the scenes, this method uses HTML5 `pushState()` in browsers that
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   476
    support it (or the location hash in older browsers and IE) to change the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   477
    URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   478
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   479
    The specified URL must share the same origin (i.e., protocol, host, and
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   480
    port) as the current page, or an error will occur.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   481
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   482
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   483
        // Starting URL: http://example.com/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   484
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   485
        router.replace('/path/');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   486
        // New URL: http://example.com/path/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   487
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   488
        router.replace('/path?foo=bar');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   489
        // New URL: http://example.com/path?foo=bar
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   490
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   491
        router.replace('/');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   492
        // New URL: http://example.com/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   493
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   494
    @method replace
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   495
    @param {String} [url] URL to set. This URL needs to be of the same origin as
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   496
      the current URL. This can be a URL relative to the router's `root`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   497
      attribute. If no URL is specified, the page's current URL will be used.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   498
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   499
    @see save()
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   500
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   501
    replace: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   502
        return this._queue(url, true);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   503
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   504
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   505
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   506
    Adds a route handler for the specified `route`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   507
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   508
    The `route` parameter may be a string or regular expression to represent a
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   509
    URL path, or a route object. If it's a string (which is most common), it may
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   510
    contain named parameters: `:param` will match any single part of a URL path
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   511
    (not including `/` characters), and `*param` will match any number of parts
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   512
    of a URL path (including `/` characters). These named parameters will be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   513
    made available as keys on the `req.params` object that's passed to route
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   514
    handlers.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   515
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   516
    If the `route` parameter is a regex, all pattern matches will be made
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   517
    available as numbered keys on `req.params`, starting with `0` for the full
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   518
    match, then `1` for the first subpattern match, and so on.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   519
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   520
    Alternatively, an object can be provided to represent the route and it may
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   521
    contain a `path` property which is a string or regular expression which
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   522
    causes the route to be process as described above. If the route object
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   523
    already contains a `regex` or `regexp` property, the route will be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   524
    considered fully-processed and will be associated with any `callacks`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   525
    specified on the object and those specified as parameters to this method.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   526
    **Note:** Any additional data contained on the route object will be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   527
    preserved.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   528
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   529
    Here's a set of sample routes along with URL paths that they match:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   530
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   531
      * Route: `/photos/:tag/:page`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   532
        * URL: `/photos/kittens/1`, params: `{tag: 'kittens', page: '1'}`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   533
        * URL: `/photos/puppies/2`, params: `{tag: 'puppies', page: '2'}`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   534
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   535
      * Route: `/file/*path`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   536
        * URL: `/file/foo/bar/baz.txt`, params: `{path: 'foo/bar/baz.txt'}`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   537
        * URL: `/file/foo`, params: `{path: 'foo'}`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   538
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   539
    **Middleware**: Routes also support an arbitrary number of callback
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   540
    functions. This allows you to easily reuse parts of your route-handling code
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   541
    with different route. This method is liberal in how it processes the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   542
    specified `callbacks`, you can specify them as separate arguments, or as
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   543
    arrays, or both.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   544
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   545
    If multiple route match a given URL, they will be executed in the order they
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   546
    were added. The first route that was added will be the first to be executed.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   547
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   548
    **Passing Control**: Invoking the `next()` function within a route callback
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   549
    will pass control to the next callback function (if any) or route handler
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   550
    (if any). If a value is passed to `next()`, it's assumed to be an error,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   551
    therefore stopping the dispatch chain, unless that value is: `"route"`,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   552
    which is special case and dispatching will skip to the next route handler.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   553
    This allows middleware to skip any remaining middleware for a particular
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   554
    route.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   555
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   556
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   557
        router.route('/photos/:tag/:page', function (req, res, next) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   558
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   559
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   560
        // Using middleware.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   561
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   562
        router.findUser = function (req, res, next) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   563
            req.user = this.get('users').findById(req.params.user);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   564
            next();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   565
        };
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   566
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   567
        router.route('/users/:user', 'findUser', function (req, res, next) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   568
            // The `findUser` middleware puts the `user` object on the `req`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   569
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   570
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   571
    @method route
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   572
    @param {String|RegExp|Object} route Route to match. May be a string or a
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   573
      regular expression, or a route object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   574
    @param {Array|Function|String} callbacks* Callback functions to call
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   575
        whenever this route is triggered. These can be specified as separate
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   576
        arguments, or in arrays, or both. If a callback is specified as a
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   577
        string, the named function will be called on this router instance.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   578
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   579
      @param {Object} callbacks.req Request object containing information about
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   580
          the request. It contains the following properties.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   581
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   582
        @param {Array|Object} callbacks.req.params Captured parameters matched
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   583
          by the route path specification. If a string path was used and
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   584
          contained named parameters, then this will be a key/value hash mapping
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   585
          parameter names to their matched values. If a regex path was used,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   586
          this will be an array of subpattern matches starting at index 0 for
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   587
          the full match, then 1 for the first subpattern match, and so on.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   588
        @param {String} callbacks.req.path The current URL path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   589
        @param {Number} callbacks.req.pendingCallbacks Number of remaining
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   590
          callbacks the route handler has after this one in the dispatch chain.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   591
        @param {Number} callbacks.req.pendingRoutes Number of matching routes
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   592
          after this one in the dispatch chain.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   593
        @param {Object} callbacks.req.query Query hash representing the URL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   594
          query string, if any. Parameter names are keys, and are mapped to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   595
          parameter values.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   596
        @param {Object} callbacks.req.route Reference to the current route
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   597
          object whose callbacks are being dispatched.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   598
        @param {Object} callbacks.req.router Reference to this router instance.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   599
        @param {String} callbacks.req.src What initiated the dispatch. In an
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   600
          HTML5 browser, when the back/forward buttons are used, this property
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   601
          will have a value of "popstate". When the `dispath()` method is
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   602
          called, the `src` will be `"dispatch"`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   603
        @param {String} callbacks.req.url The full URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   604
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   605
      @param {Object} callbacks.res Response object containing methods and
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   606
          information that relate to responding to a request. It contains the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   607
          following properties.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   608
        @param {Object} callbacks.res.req Reference to the request object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   609
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   610
      @param {Function} callbacks.next Function to pass control to the next
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   611
          callback or the next matching route if no more callbacks (middleware)
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   612
          exist for the current route handler. If you don't call this function,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   613
          then no further callbacks or route handlers will be executed, even if
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   614
          there are more that match. If you do call this function, then the next
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   615
          callback (if any) or matching route handler (if any) will be called.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   616
          All of these functions will receive the same `req` and `res` objects
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   617
          that were passed to this route (so you can use these objects to pass
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   618
          data along to subsequent callbacks and routes).
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   619
        @param {String} [callbacks.next.err] Optional error which will stop the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   620
          dispatch chaining for this `req`, unless the value is `"route"`, which
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   621
          is special cased to jump skip past any callbacks for the current route
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   622
          and pass control the next route handler.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   623
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   624
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   625
    route: function (route, callbacks) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   626
        // Grab callback functions from var-args.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   627
        callbacks = YArray(arguments, 1, true);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   628
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   629
        var keys, regex;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   630
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   631
        // Supports both the `route(path, callbacks)` and `route(config)` call
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   632
        // signatures, allowing for fully-processed route configs to be passed.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   633
        if (typeof route === 'string' || YLang.isRegExp(route)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   634
            // Flatten `callbacks` into a single dimension array.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   635
            callbacks = YArray.flatten(callbacks);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   636
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   637
            keys  = [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   638
            regex = this._getRegex(route, keys);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   639
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   640
            route = {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   641
                callbacks: callbacks,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   642
                keys     : keys,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   643
                path     : route,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   644
                regex    : regex
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   645
            };
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   646
        } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   647
            // Look for any configured `route.callbacks` and fallback to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   648
            // `route.callback` for back-compat, append var-arg `callbacks`,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   649
            // then flatten the entire collection to a single dimension array.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   650
            callbacks = YArray.flatten(
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   651
                [route.callbacks || route.callback || []].concat(callbacks)
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   652
            );
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   653
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   654
            // Check for previously generated regex, also fallback to `regexp`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   655
            // for greater interop.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   656
            keys  = route.keys;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   657
            regex = route.regex || route.regexp;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   658
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   659
            // Generates the route's regex if it doesn't already have one.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   660
            if (!regex) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   661
                keys  = [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   662
                regex = this._getRegex(route.path, keys);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   663
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   664
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   665
            // Merge specified `route` config object with processed data.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   666
            route = Y.merge(route, {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   667
                callbacks: callbacks,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   668
                keys     : keys,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   669
                path     : route.path || regex,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   670
                regex    : regex
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   671
            });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   672
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   673
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   674
        this._routes.push(route);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   675
        return this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   676
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   677
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   678
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   679
    Saves a new browser history entry and dispatches to the first matching route
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   680
    handler, if any.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   681
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   682
    Behind the scenes, this method uses HTML5 `pushState()` in browsers that
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   683
    support it (or the location hash in older browsers and IE) to change the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   684
    URL and create a history entry.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   685
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   686
    The specified URL must share the same origin (i.e., protocol, host, and
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   687
    port) as the current page, or an error will occur.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   688
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   689
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   690
        // Starting URL: http://example.com/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   691
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   692
        router.save('/path/');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   693
        // New URL: http://example.com/path/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   694
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   695
        router.save('/path?foo=bar');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   696
        // New URL: http://example.com/path?foo=bar
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   697
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   698
        router.save('/');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   699
        // New URL: http://example.com/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   700
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   701
    @method save
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   702
    @param {String} [url] URL to set. This URL needs to be of the same origin as
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   703
      the current URL. This can be a URL relative to the router's `root`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   704
      attribute. If no URL is specified, the page's current URL will be used.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   705
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   706
    @see replace()
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   707
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   708
    save: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   709
        return this._queue(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   710
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   711
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   712
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   713
    Upgrades a hash-based URL to an HTML5 URL if necessary. In non-HTML5
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   714
    browsers, this method is a noop.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   715
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   716
    @method upgrade
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   717
    @return {Boolean} `true` if the URL was upgraded, `false` otherwise.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   718
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   719
    upgrade: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   720
        if (!this._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   721
            return false;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   722
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   723
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   724
        // Get the resolve hash path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   725
        var hashPath = this._getHashPath();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   726
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   727
        if (hashPath) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   728
            // This is an HTML5 browser and we have a hash-based path in the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   729
            // URL, so we need to upgrade the URL to a non-hash URL. This
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   730
            // will trigger a `history:change` event, which will in turn
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   731
            // trigger a dispatch.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   732
            this.once(EVT_READY, function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   733
                this.replace(hashPath);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   734
            });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   735
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   736
            return true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   737
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   738
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   739
        return false;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   740
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   741
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   742
    // -- Protected Methods ----------------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   743
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   744
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   745
    Wrapper around `decodeURIComponent` that also converts `+` chars into
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   746
    spaces.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   747
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   748
    @method _decode
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   749
    @param {String} string String to decode.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   750
    @return {String} Decoded string.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   751
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   752
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   753
    _decode: function (string) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   754
        return decodeURIComponent(string.replace(/\+/g, ' '));
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   755
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   756
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   757
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   758
    Shifts the topmost `_save()` call off the queue and executes it. Does
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   759
    nothing if the queue is empty.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   760
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   761
    @method _dequeue
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   762
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   763
    @see _queue
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   764
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   765
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   766
    _dequeue: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   767
        var self = this,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   768
            fn;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   769
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   770
        // If window.onload hasn't yet fired, wait until it has before
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   771
        // dequeueing. This will ensure that we don't call pushState() before an
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   772
        // initial popstate event has fired.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   773
        if (!YUI.Env.windowLoaded) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   774
            Y.once('load', function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   775
                self._dequeue();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   776
            });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   777
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   778
            return this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   779
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   780
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   781
        fn = saveQueue.shift();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   782
        return fn ? fn() : this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   783
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   784
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   785
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   786
    Dispatches to the first route handler that matches the specified _path_.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   787
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   788
    If called before the `ready` event has fired, the dispatch will be aborted.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   789
    This ensures normalized behavior between Chrome (which fires a `popstate`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   790
    event on every pageview) and other browsers (which do not).
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   791
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   792
    @method _dispatch
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   793
    @param {object} req Request object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   794
    @param {String} res Response object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   795
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   796
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   797
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   798
    _dispatch: function (req, res) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   799
        var self      = this,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   800
            decode    = self._decode,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   801
            routes    = self.match(req.path),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   802
            callbacks = [],
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   803
            matches, paramsMatch, routePath;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   804
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   805
        self._dispatching = self._dispatched = true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   806
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   807
        if (!routes || !routes.length) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   808
            self._dispatching = false;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   809
            return self;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   810
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   811
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   812
        routePath = self.removeRoot(req.path);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   813
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   814
        function next(err) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   815
            var callback, name, route;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   816
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   817
            if (err) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   818
                // Special case "route" to skip to the next route handler
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   819
                // avoiding any additional callbacks for the current route.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   820
                if (err === 'route') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   821
                    callbacks = [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   822
                    next();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   823
                } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   824
                    Y.error(err);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   825
                }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   826
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   827
            } else if ((callback = callbacks.shift())) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   828
                if (typeof callback === 'string') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   829
                    name     = callback;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   830
                    callback = self[name];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   831
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   832
                    if (!callback) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   833
                        Y.error('Router: Callback not found: ' + name, null, 'router');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   834
                    }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   835
                }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   836
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   837
                // Allow access to the number of remaining callbacks for the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   838
                // route.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   839
                req.pendingCallbacks = callbacks.length;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   840
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   841
                callback.call(self, req, res, next);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   842
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   843
            } else if ((route = routes.shift())) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   844
                // Make a copy of this route's `callbacks` so the original array
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   845
                // is preserved.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   846
                callbacks = route.callbacks.concat();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   847
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   848
                // Decode each of the path matches so that the any URL-encoded
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   849
                // path segments are decoded in the `req.params` object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   850
                matches = YArray.map(route.regex.exec(routePath) || [],
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   851
                        function (match) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   852
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   853
                    // Decode matches, or coerce `undefined` matches to an empty
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   854
                    // string to match expectations of working with `req.params`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   855
                    // in the content of route dispatching, and normalize
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   856
                    // browser differences in their handling of regex NPCGs:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   857
                    // https://github.com/yui/yui3/issues/1076
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   858
                    return (match && decode(match)) || '';
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   859
                });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   860
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   861
                paramsMatch = true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   862
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   863
                // Use named keys for parameter names if the route path contains
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   864
                // named keys. Otherwise, use numerical match indices.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   865
                if (matches.length === route.keys.length + 1) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   866
                    matches    = matches.slice(1);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   867
                    req.params = YArray.hash(route.keys, matches);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   868
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   869
                    paramsMatch = YArray.every(route.keys, function (key, i) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   870
                        var paramHandler = self._params[key],
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   871
                            value        = matches[i];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   872
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   873
                        if (paramHandler && value && typeof value === 'string') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   874
                            // Check if `paramHandler` is a RegExp, becuase this
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   875
                            // is true in Android 2.3 and other browsers!
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   876
                            // `typeof /.*/ === 'function'`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   877
                            value = YLang.isRegExp(paramHandler) ?
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   878
                                    paramHandler.exec(value) :
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   879
                                    paramHandler.call(self, value, key);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   880
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   881
                            if (value !== false && YLang.isValue(value)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   882
                                req.params[key] = value;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   883
                                return true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   884
                            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   885
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   886
                            return false;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   887
                        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   888
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   889
                        return true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   890
                    });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   891
                } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   892
                    req.params = matches.concat();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   893
                }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   894
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   895
                // Allow access to current route and the number of remaining
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   896
                // routes for this request.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   897
                req.route         = route;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   898
                req.pendingRoutes = routes.length;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   899
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   900
                // Execute this route's `callbacks` or skip this route because
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   901
                // some of the param regexps don't match.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   902
                if (paramsMatch) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   903
                    next();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   904
                } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   905
                    next('route');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   906
                }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   907
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   908
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   909
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   910
        next();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   911
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   912
        self._dispatching = false;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   913
        return self._dequeue();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   914
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   915
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   916
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   917
    Returns the resolved path from the hash fragment, or an empty string if the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   918
    hash is not path-like.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   919
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   920
    @method _getHashPath
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   921
    @param {String} [hash] Hash fragment to resolve into a path. By default this
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   922
        will be the hash from the current URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   923
    @return {String} Current hash path, or an empty string if the hash is empty.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   924
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   925
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   926
    _getHashPath: function (hash) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   927
        hash || (hash = HistoryHash.getHash());
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   928
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   929
        // Make sure the `hash` is path-like.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   930
        if (hash && hash.charAt(0) === '/') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   931
            return this._joinURL(hash);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   932
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   933
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   934
        return '';
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   935
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   936
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   937
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   938
    Gets the location origin (i.e., protocol, host, and port) as a URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   939
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   940
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   941
        http://example.com
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   942
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   943
    @method _getOrigin
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   944
    @return {String} Location origin (i.e., protocol, host, and port).
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   945
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   946
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   947
    _getOrigin: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   948
        var location = Y.getLocation();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   949
        return location.origin || (location.protocol + '//' + location.host);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   950
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   951
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   952
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   953
    Getter for the `params` attribute.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   954
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   955
    @method _getParams
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   956
    @return {Object} Mapping of param handlers: `name` -> RegExp | Function.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   957
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   958
    @since 3.12.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   959
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   960
    _getParams: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   961
        return Y.merge(this._params);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   962
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   963
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   964
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   965
    Gets the current route path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   966
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   967
    @method _getPath
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   968
    @return {String} Current route path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   969
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   970
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   971
    _getPath: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   972
        var path = (!this._html5 && this._getHashPath()) ||
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   973
                Y.getLocation().pathname;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   974
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   975
        return this.removeQuery(path);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   976
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   977
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   978
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   979
    Returns the current path root after popping off the last path segment,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   980
    making it useful for resolving other URL paths against.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   981
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   982
    The path root will always begin and end with a '/'.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   983
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   984
    @method _getPathRoot
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   985
    @return {String} The URL's path root.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   986
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   987
    @since 3.5.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   988
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   989
    _getPathRoot: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   990
        var slash = '/',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   991
            path  = Y.getLocation().pathname,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   992
            segments;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   993
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   994
        if (path.charAt(path.length - 1) === slash) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   995
            return path;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   996
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   997
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   998
        segments = path.split(slash);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
   999
        segments.pop();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1000
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1001
        return segments.join(slash) + slash;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1002
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1003
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1004
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1005
    Gets the current route query string.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1006
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1007
    @method _getQuery
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1008
    @return {String} Current route query string.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1009
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1010
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1011
    _getQuery: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1012
        var location = Y.getLocation(),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1013
            hash, matches;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1014
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1015
        if (this._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1016
            return location.search.substring(1);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1017
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1018
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1019
        hash    = HistoryHash.getHash();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1020
        matches = hash.match(this._regexUrlQuery);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1021
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1022
        return hash && matches ? matches[1] : location.search.substring(1);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1023
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1024
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1025
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1026
    Creates a regular expression from the given route specification. If _path_
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1027
    is already a regex, it will be returned unmodified.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1028
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1029
    @method _getRegex
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1030
    @param {String|RegExp} path Route path specification.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1031
    @param {Array} keys Array reference to which route parameter names will be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1032
      added.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1033
    @return {RegExp} Route regex.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1034
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1035
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1036
    _getRegex: function (path, keys) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1037
        if (YLang.isRegExp(path)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1038
            return path;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1039
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1040
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1041
        // Special case for catchall paths.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1042
        if (path === '*') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1043
            return (/.*/);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1044
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1045
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1046
        path = path.replace(this._regexPathParam, function (match, operator, key) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1047
            // Only `*` operators are supported for key-less matches to allowing
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1048
            // in-path wildcards like: '/foo/*'.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1049
            if (!key) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1050
                return operator === '*' ? '.*' : match;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1051
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1052
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1053
            keys.push(key);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1054
            return operator === '*' ? '(.*?)' : '([^/#?]*)';
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1055
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1056
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1057
        return new RegExp('^' + path + '$');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1058
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1059
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1060
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1061
    Gets a request object that can be passed to a route handler.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1062
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1063
    @method _getRequest
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1064
    @param {String} src What initiated the URL change and need for the request.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1065
    @return {Object} Request object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1066
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1067
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1068
    _getRequest: function (src) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1069
        return {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1070
            path  : this._getPath(),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1071
            query : this._parseQuery(this._getQuery()),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1072
            url   : this._getURL(),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1073
            router: this,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1074
            src   : src
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1075
        };
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1076
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1077
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1078
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1079
    Gets a response object that can be passed to a route handler.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1080
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1081
    @method _getResponse
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1082
    @param {Object} req Request object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1083
    @return {Object} Response Object.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1084
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1085
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1086
    _getResponse: function (req) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1087
        return {req: req};
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1088
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1089
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1090
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1091
    Getter for the `routes` attribute.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1092
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1093
    @method _getRoutes
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1094
    @return {Object[]} Array of route objects.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1095
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1096
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1097
    _getRoutes: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1098
        return this._routes.concat();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1099
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1100
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1101
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1102
    Gets the current full URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1103
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1104
    @method _getURL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1105
    @return {String} URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1106
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1107
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1108
    _getURL: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1109
        var url = Y.getLocation().toString();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1110
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1111
        if (!this._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1112
            url = this._upgradeURL(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1113
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1114
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1115
        return url;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1116
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1117
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1118
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1119
    Returns `true` when the specified `url` is from the same origin as the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1120
    current URL; i.e., the protocol, host, and port of the URLs are the same.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1121
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1122
    All host or path relative URLs are of the same origin. A scheme-relative URL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1123
    is first prefixed with the current scheme before being evaluated.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1124
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1125
    @method _hasSameOrigin
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1126
    @param {String} url URL to compare origin with the current URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1127
    @return {Boolean} Whether the URL has the same origin of the current URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1128
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1129
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1130
    _hasSameOrigin: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1131
        var origin = ((url && url.match(this._regexUrlOrigin)) || [])[0];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1132
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1133
        // Prepend current scheme to scheme-relative URLs.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1134
        if (origin && origin.indexOf('//') === 0) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1135
            origin = Y.getLocation().protocol + origin;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1136
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1137
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1138
        return !origin || origin === this._getOrigin();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1139
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1140
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1141
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1142
    Joins the `root` URL to the specified _url_, normalizing leading/trailing
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1143
    `/` characters.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1144
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1145
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1146
        router.set('root', '/foo');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1147
        router._joinURL('bar');  // => '/foo/bar'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1148
        router._joinURL('/bar'); // => '/foo/bar'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1149
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1150
        router.set('root', '/foo/');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1151
        router._joinURL('bar');  // => '/foo/bar'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1152
        router._joinURL('/bar'); // => '/foo/bar'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1153
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1154
    @method _joinURL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1155
    @param {String} url URL to append to the `root` URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1156
    @return {String} Joined URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1157
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1158
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1159
    _joinURL: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1160
        var root = this.get('root');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1161
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1162
        // Causes `url` to _always_ begin with a "/".
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1163
        url = this.removeRoot(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1164
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1165
        if (url.charAt(0) === '/') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1166
            url = url.substring(1);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1167
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1168
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1169
        return root && root.charAt(root.length - 1) === '/' ?
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1170
                root + url :
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1171
                root + '/' + url;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1172
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1173
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1174
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1175
    Returns a normalized path, ridding it of any '..' segments and properly
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1176
    handling leading and trailing slashes.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1177
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1178
    @method _normalizePath
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1179
    @param {String} path URL path to normalize.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1180
    @return {String} Normalized path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1181
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1182
    @since 3.5.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1183
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1184
    _normalizePath: function (path) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1185
        var dots  = '..',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1186
            slash = '/',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1187
            i, len, normalized, segments, segment, stack;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1188
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1189
        if (!path || path === slash) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1190
            return slash;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1191
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1192
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1193
        segments = path.split(slash);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1194
        stack    = [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1195
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1196
        for (i = 0, len = segments.length; i < len; ++i) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1197
            segment = segments[i];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1198
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1199
            if (segment === dots) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1200
                stack.pop();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1201
            } else if (segment) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1202
                stack.push(segment);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1203
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1204
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1205
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1206
        normalized = slash + stack.join(slash);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1207
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1208
        // Append trailing slash if necessary.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1209
        if (normalized !== slash && path.charAt(path.length - 1) === slash) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1210
            normalized += slash;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1211
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1212
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1213
        return normalized;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1214
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1215
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1216
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1217
    Parses a URL query string into a key/value hash. If `Y.QueryString.parse` is
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1218
    available, this method will be an alias to that.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1219
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1220
    @method _parseQuery
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1221
    @param {String} query Query string to parse.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1222
    @return {Object} Hash of key/value pairs for query parameters.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1223
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1224
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1225
    _parseQuery: QS && QS.parse ? QS.parse : function (query) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1226
        var decode = this._decode,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1227
            params = query.split('&'),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1228
            i      = 0,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1229
            len    = params.length,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1230
            result = {},
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1231
            param;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1232
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1233
        for (; i < len; ++i) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1234
            param = params[i].split('=');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1235
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1236
            if (param[0]) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1237
                result[decode(param[0])] = decode(param[1] || '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1238
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1239
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1240
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1241
        return result;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1242
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1243
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1244
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1245
    Returns `true` when the specified `path` is semantically within the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1246
    specified `root` path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1247
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1248
    If the `root` does not end with a trailing slash ("/"), one will be added
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1249
    before the `path` is evaluated against the root path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1250
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1251
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1252
        this._pathHasRoot('/app',  '/app/foo'); // => true
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1253
        this._pathHasRoot('/app/', '/app/foo'); // => true
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1254
        this._pathHasRoot('/app/', '/app/');    // => true
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1255
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1256
        this._pathHasRoot('/app',  '/foo/bar'); // => false
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1257
        this._pathHasRoot('/app/', '/foo/bar'); // => false
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1258
        this._pathHasRoot('/app/', '/app');     // => false
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1259
        this._pathHasRoot('/app',  '/app');     // => false
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1260
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1261
    @method _pathHasRoot
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1262
    @param {String} root Root path used to evaluate whether the specificed
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1263
        `path` is semantically within. A trailing slash ("/") will be added if
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1264
        it does not already end with one.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1265
    @param {String} path Path to evaluate for containing the specified `root`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1266
    @return {Boolean} Whether or not the `path` is semantically within the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1267
        `root` path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1268
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1269
    @since 3.13.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1270
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1271
    _pathHasRoot: function (root, path) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1272
        var rootPath = root.charAt(root.length - 1) === '/' ? root : root + '/';
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1273
        return path.indexOf(rootPath) === 0;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1274
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1275
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1276
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1277
    Queues up a `_save()` call to run after all previously-queued calls have
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1278
    finished.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1279
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1280
    This is necessary because if we make multiple `_save()` calls before the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1281
    first call gets dispatched, then both calls will dispatch to the last call's
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1282
    URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1283
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1284
    All arguments passed to `_queue()` will be passed on to `_save()` when the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1285
    queued function is executed.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1286
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1287
    @method _queue
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1288
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1289
    @see _dequeue
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1290
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1291
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1292
    _queue: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1293
        var args = arguments,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1294
            self = this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1295
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1296
        saveQueue.push(function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1297
            if (self._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1298
                if (Y.UA.ios && Y.UA.ios < 5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1299
                    // iOS <5 has buggy HTML5 history support, and needs to be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1300
                    // synchronous.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1301
                    self._save.apply(self, args);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1302
                } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1303
                    // Wrapped in a timeout to ensure that _save() calls are
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1304
                    // always processed asynchronously. This ensures consistency
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1305
                    // between HTML5- and hash-based history.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1306
                    setTimeout(function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1307
                        self._save.apply(self, args);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1308
                    }, 1);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1309
                }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1310
            } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1311
                self._dispatching = true; // otherwise we'll dequeue too quickly
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1312
                self._save.apply(self, args);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1313
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1314
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1315
            return self;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1316
        });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1317
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1318
        return !this._dispatching ? this._dequeue() : this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1319
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1320
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1321
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1322
    Returns the normalized result of resolving the `path` against the current
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1323
    path. Falsy values for `path` will return just the current path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1324
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1325
    @method _resolvePath
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1326
    @param {String} path URL path to resolve.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1327
    @return {String} Resolved path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1328
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1329
    @since 3.5.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1330
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1331
    _resolvePath: function (path) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1332
        if (!path) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1333
            return Y.getLocation().pathname;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1334
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1335
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1336
        if (path.charAt(0) !== '/') {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1337
            path = this._getPathRoot() + path;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1338
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1339
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1340
        return this._normalizePath(path);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1341
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1342
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1343
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1344
    Resolves the specified URL against the current URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1345
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1346
    This method resolves URLs like a browser does and will always return an
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1347
    absolute URL. When the specified URL is already absolute, it is assumed to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1348
    be fully resolved and is simply returned as is. Scheme-relative URLs are
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1349
    prefixed with the current protocol. Relative URLs are giving the current
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1350
    URL's origin and are resolved and normalized against the current path root.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1351
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1352
    @method _resolveURL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1353
    @param {String} url URL to resolve.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1354
    @return {String} Resolved URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1355
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1356
    @since 3.5.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1357
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1358
    _resolveURL: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1359
        var parts    = url && url.match(this._regexURL),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1360
            origin, path, query, hash, resolved;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1361
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1362
        if (!parts) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1363
            return Y.getLocation().toString();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1364
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1365
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1366
        origin = parts[1];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1367
        path   = parts[2];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1368
        query  = parts[3];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1369
        hash   = parts[4];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1370
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1371
        // Absolute and scheme-relative URLs are assumed to be fully-resolved.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1372
        if (origin) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1373
            // Prepend the current scheme for scheme-relative URLs.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1374
            if (origin.indexOf('//') === 0) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1375
                origin = Y.getLocation().protocol + origin;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1376
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1377
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1378
            return origin + (path || '/') + (query || '') + (hash || '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1379
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1380
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1381
        // Will default to the current origin and current path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1382
        resolved = this._getOrigin() + this._resolvePath(path);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1383
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1384
        // A path or query for the specified URL trumps the current URL's.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1385
        if (path || query) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1386
            return resolved + (query || '') + (hash || '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1387
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1388
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1389
        query = this._getQuery();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1390
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1391
        return resolved + (query ? ('?' + query) : '') + (hash || '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1392
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1393
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1394
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1395
    Saves a history entry using either `pushState()` or the location hash.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1396
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1397
    This method enforces the same-origin security constraint; attempting to save
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1398
    a `url` that is not from the same origin as the current URL will result in
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1399
    an error.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1400
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1401
    @method _save
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1402
    @param {String} [url] URL for the history entry.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1403
    @param {Boolean} [replace=false] If `true`, the current history entry will
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1404
      be replaced instead of a new one being added.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1405
    @chainable
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1406
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1407
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1408
    _save: function (url, replace) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1409
        var urlIsString = typeof url === 'string',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1410
            currentPath, root, hash;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1411
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1412
        // Perform same-origin check on the specified URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1413
        if (urlIsString && !this._hasSameOrigin(url)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1414
            Y.error('Security error: The new URL must be of the same origin as the current URL.');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1415
            return this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1416
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1417
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1418
        // Joins the `url` with the `root`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1419
        if (urlIsString) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1420
            url = this._joinURL(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1421
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1422
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1423
        // Force _ready to true to ensure that the history change is handled
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1424
        // even if _save is called before the `ready` event fires.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1425
        this._ready = true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1426
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1427
        if (this._html5) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1428
            this._history[replace ? 'replace' : 'add'](null, {url: url});
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1429
        } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1430
            currentPath = Y.getLocation().pathname;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1431
            root        = this.get('root');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1432
            hash        = HistoryHash.getHash();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1433
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1434
            if (!urlIsString) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1435
                url = hash;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1436
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1437
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1438
            // Determine if the `root` already exists in the current location's
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1439
            // `pathname`, and if it does then we can exclude it from the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1440
            // hash-based path. No need to duplicate the info in the URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1441
            if (root === currentPath || root === this._getPathRoot()) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1442
                url = this.removeRoot(url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1443
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1444
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1445
            // The `hashchange` event only fires when the new hash is actually
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1446
            // different. This makes sure we'll always dequeue and dispatch
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1447
            // _all_ router instances, mimicking the HTML5 behavior.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1448
            if (url === hash) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1449
                Y.Router.dispatch();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1450
            } else {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1451
                HistoryHash[replace ? 'replaceHash' : 'setHash'](url);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1452
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1453
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1454
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1455
        return this;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1456
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1457
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1458
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1459
    Setter for the `params` attribute.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1460
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1461
    @method _setParams
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1462
    @param {Object} params Map in the form: `name` -> RegExp | Function.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1463
    @return {Object} The map of params: `name` -> RegExp | Function.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1464
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1465
    @since 3.12.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1466
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1467
    _setParams: function (params) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1468
        this._params = {};
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1469
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1470
        YObject.each(params, function (regex, name) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1471
            this.param(name, regex);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1472
        }, this);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1473
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1474
        return Y.merge(this._params);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1475
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1476
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1477
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1478
    Setter for the `routes` attribute.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1479
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1480
    @method _setRoutes
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1481
    @param {Object[]} routes Array of route objects.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1482
    @return {Object[]} Array of route objects.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1483
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1484
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1485
    _setRoutes: function (routes) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1486
        this._routes = [];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1487
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1488
        YArray.each(routes, function (route) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1489
            this.route(route);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1490
        }, this);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1491
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1492
        return this._routes.concat();
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1493
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1494
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1495
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1496
    Upgrades a hash-based URL to a full-path URL, if necessary.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1497
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1498
    The specified `url` will be upgraded if its of the same origin as the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1499
    current URL and has a path-like hash. URLs that don't need upgrading will be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1500
    returned as-is.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1501
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1502
    @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1503
        app._upgradeURL('http://example.com/#/foo/'); // => 'http://example.com/foo/';
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1504
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1505
    @method _upgradeURL
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1506
    @param {String} url The URL to upgrade from hash-based to full-path.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1507
    @return {String} The upgraded URL, or the specified URL untouched.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1508
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1509
    @since 3.5.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1510
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1511
    _upgradeURL: function (url) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1512
        // We should not try to upgrade paths for external URLs.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1513
        if (!this._hasSameOrigin(url)) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1514
            return url;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1515
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1516
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1517
        var hash       = (url.match(/#(.*)$/) || [])[1] || '',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1518
            hashPrefix = Y.HistoryHash.hashPrefix,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1519
            hashPath;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1520
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1521
        // Strip any hash prefix, like hash-bangs.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1522
        if (hashPrefix && hash.indexOf(hashPrefix) === 0) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1523
            hash = hash.replace(hashPrefix, '');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1524
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1525
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1526
        // If the hash looks like a URL path, assume it is, and upgrade it!
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1527
        if (hash) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1528
            hashPath = this._getHashPath(hash);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1529
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1530
            if (hashPath) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1531
                return this._resolveURL(hashPath);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1532
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1533
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1534
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1535
        return url;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1536
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1537
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1538
    // -- Protected Event Handlers ---------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1539
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1540
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1541
    Handles `history:change` and `hashchange` events.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1542
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1543
    @method _afterHistoryChange
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1544
    @param {EventFacade} e
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1545
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1546
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1547
    _afterHistoryChange: function (e) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1548
        var self       = this,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1549
            src        = e.src,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1550
            prevURL    = self._url,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1551
            currentURL = self._getURL(),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1552
            req, res;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1553
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1554
        self._url = currentURL;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1555
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1556
        // Handles the awkwardness that is the `popstate` event. HTML5 browsers
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1557
        // fire `popstate` right before they fire `hashchange`, and Chrome fires
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1558
        // `popstate` on page load. If this router is not ready or the previous
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1559
        // and current URLs only differ by their hash, then we want to ignore
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1560
        // this `popstate` event.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1561
        if (src === 'popstate' &&
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1562
                (!self._ready || prevURL.replace(/#.*$/, '') === currentURL.replace(/#.*$/, ''))) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1563
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1564
            return;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1565
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1566
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1567
        req = self._getRequest(src);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1568
        res = self._getResponse(req);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1569
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1570
        self._dispatch(req, res);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1571
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1572
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1573
    // -- Default Event Handlers -----------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1574
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1575
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1576
    Default handler for the `ready` event.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1577
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1578
    @method _defReadyFn
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1579
    @param {EventFacade} e
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1580
    @protected
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1581
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1582
    _defReadyFn: function (e) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1583
        this._ready = true;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1584
    }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1585
}, {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1586
    // -- Static Properties ----------------------------------------------------
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1587
    NAME: 'router',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1588
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1589
    ATTRS: {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1590
        /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1591
        Whether or not this browser is capable of using HTML5 history.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1592
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1593
        Setting this to `false` will force the use of hash-based history even on
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1594
        HTML5 browsers, but please don't do this unless you understand the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1595
        consequences.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1596
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1597
        @attribute html5
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1598
        @type Boolean
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1599
        @initOnly
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1600
        **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1601
        html5: {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1602
            // Android versions lower than 3.0 are buggy and don't update
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1603
            // window.location after a pushState() call, so we fall back to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1604
            // hash-based history for them.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1605
            //
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1606
            // See http://code.google.com/p/android/issues/detail?id=17471
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1607
            valueFn: function () { return Y.Router.html5; },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1608
            writeOnce: 'initOnly'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1609
        },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1610
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1611
        /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1612
        Map of params handlers in the form: `name` -> RegExp | Function.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1613
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1614
        If a param handler regex or function returns a value of `false`, `null`,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1615
        `undefined`, or `NaN`, the current route will not match and be skipped.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1616
        All other return values will be used in place of the original param
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1617
        value parsed from the URL.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1618
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1619
        This attribute is intended to be used to set params at init time, or to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1620
        completely reset all params after init. To add params after init without
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1621
        resetting all existing params, use the `param()` method.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1622
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1623
        @attribute params
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1624
        @type Object
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1625
        @default `{}`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1626
        @see param
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1627
        @since 3.12.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1628
        **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1629
        params: {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1630
            value : {},
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1631
            getter: '_getParams',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1632
            setter: '_setParams'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1633
        },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1634
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1635
        /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1636
        Absolute root path from which all routes should be evaluated.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1637
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1638
        For example, if your router is running on a page at
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1639
        `http://example.com/myapp/` and you add a route with the path `/`, your
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1640
        route will never execute, because the path will always be preceded by
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1641
        `/myapp`. Setting `root` to `/myapp` would cause all routes to be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1642
        evaluated relative to that root URL, so the `/` route would then execute
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1643
        when the user browses to `http://example.com/myapp/`.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1644
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1645
        @example
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1646
            router.set('root', '/myapp');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1647
            router.route('/foo', function () { ... });
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1648
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1649
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1650
            // Updates the URL to: "/myapp/foo"
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1651
            router.save('/foo');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1652
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1653
        @attribute root
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1654
        @type String
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1655
        @default `''`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1656
        **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1657
        root: {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1658
            value: ''
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1659
        },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1660
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1661
        /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1662
        Array of route objects.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1663
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1664
        Each item in the array must be an object with the following properties
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1665
        in order to be processed by the router:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1666
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1667
          * `path`: String or regex representing the path to match. See the docs
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1668
            for the `route()` method for more details.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1669
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1670
          * `callbacks`: Function or a string representing the name of a
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1671
            function on this router instance that should be called when the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1672
            route is triggered. An array of functions and/or strings may also be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1673
            provided. See the docs for the `route()` method for more details.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1674
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1675
        If a route object contains a `regex` or `regexp` property, or if its
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1676
        `path` is a regular express, then the route will be considered to be
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1677
        fully-processed. Any fully-processed routes may contain the following
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1678
        properties:
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1679
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1680
          * `regex`: The regular expression representing the path to match, this
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1681
            property may also be named `regexp` for greater compatibility.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1682
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1683
          * `keys`: Array of named path parameters used to populate `req.params`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1684
            objects when dispatching to route handlers.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1685
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1686
        Any additional data contained on these route objects will be retained.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1687
        This is useful to store extra metadata about a route; e.g., a `name` to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1688
        give routes logical names.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1689
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1690
        This attribute is intended to be used to set routes at init time, or to
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1691
        completely reset all routes after init. To add routes after init without
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1692
        resetting all existing routes, use the `route()` method.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1693
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1694
        @attribute routes
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1695
        @type Object[]
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1696
        @default `[]`
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1697
        @see route
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1698
        **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1699
        routes: {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1700
            value : [],
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1701
            getter: '_getRoutes',
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1702
            setter: '_setRoutes'
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1703
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1704
    },
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1705
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1706
    // Used as the default value for the `html5` attribute, and for testing.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1707
    html5: Y.HistoryBase.html5 && (!Y.UA.android || Y.UA.android >= 3),
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1708
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1709
    // To make this testable.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1710
    _instances: instances,
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1711
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1712
    /**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1713
    Dispatches to the first route handler that matches the specified `path` for
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1714
    all active router instances.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1715
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1716
    This provides a mechanism to cause all active router instances to dispatch
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1717
    to their route handlers without needing to change the URL or fire the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1718
    `history:change` or `hashchange` event.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1719
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1720
    @method dispatch
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1721
    @static
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1722
    @since 3.6.0
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1723
    **/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1724
    dispatch: function () {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1725
        var i, len, router, req, res;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1726
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1727
        for (i = 0, len = instances.length; i < len; i += 1) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1728
            router = instances[i];
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1729
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1730
            if (router) {
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1731
                req = router._getRequest('dispatch');
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1732
                res = router._getResponse(req);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1733
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1734
                router._dispatch(req, res);
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1735
            }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1736
        }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1737
    }
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1738
});
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1739
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1740
/**
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1741
The `Controller` class was deprecated in YUI 3.5.0 and is now an alias for the
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1742
`Router` class. Use that class instead. This alias will be removed in a future
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1743
version of YUI.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1744
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1745
@class Controller
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1746
@constructor
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1747
@extends Base
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1748
@deprecated Use `Router` instead.
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1749
@see Router
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1750
**/
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1751
Y.Controller = Y.Router;
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1752
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1753
e16a97fb364a Use YUI 3.15
gibus
parents:
diff changeset
  1754
}, '@VERSION@', {"optional": ["querystring-parse"], "requires": ["array-extras", "base-build", "history"]});