03aeeb2040a8807d5003885d514de2535339932a
3 * https://www.mediawiki.org/wiki/OOjs_Router
5 * Copyright 2011-2019 OOjs Team and other contributors.
6 * Released under the MIT license
7 * http://oojs.mit-license.org
9 * Date: 2019-01-11T03:40:55Z
16 * Provides navigation routing and location information
19 * @extends OO.Registry
21 OO
.Router
= function OoRouter() {
25 OO
.Router
.parent
.call( this );
28 this.oldHash
= this.getPath();
30 $( window
).on( 'popstate', function () {
31 router
.emit( 'popstate' );
34 $( window
).on( 'hashchange', function () {
35 router
.emit( 'hashchange' );
38 this.on( 'hashchange', function () {
39 // event.originalEvent.newURL is undefined on Android 2.x
42 if ( router
.enabled
) {
43 routeEvent
= $.Event( 'route', {
44 path
: router
.getPath()
46 router
.emit( 'route', routeEvent
);
48 if ( !routeEvent
.isDefaultPrevented() ) {
51 // if route was prevented, ignore the next hash change and revert the
52 // hash to its old value
53 router
.enabled
= false;
54 router
.navigate( router
.oldHash
);
57 router
.enabled
= true;
60 router
.oldHash
= router
.getPath();
66 OO
.inheritClass( OO
.Router
, OO
.Registry
);
80 * @param {jQuery.Event} routeEvent
86 * Determine if current browser supports this router
88 * @return {boolean} The browser is supported
90 OO
.Router
.static.isSupported = function () {
91 return 'onhashchange' in window
;
97 * Check the current route and run appropriate callback if it matches.
99 OO
.Router
.prototype.checkRoute = function () {
100 var id
, entry
, match
,
101 hash
= this.getPath();
103 for ( id
in this.registry
) {
104 entry
= this.registry
[ id
];
105 match
= hash
.match( entry
.path
);
107 entry
.callback
.apply( this, match
.slice( 1 ) );
114 * Bind a specific callback to a hash-based route, e.g.
117 * addRoute( 'alert', function () { alert( 'something' ); } );
118 * addRoute( /hi-(.*)/, function ( name ) { alert( 'Hi ' + name ) } );
120 * Note that after defining all available routes it is up to the caller
121 * to check the existing route via the checkRoute method.
123 * @param {string|RegExp} path Path to match, string or regular expression
124 * @param {Function} callback Callback to be run when hash changes to one
127 OO
.Router
.prototype.addRoute = function ( path
, callback
) {
129 path
: typeof path
=== 'string' ?
130 new RegExp( '^' + path
.replace( /[\\^$*+?.()|[\]{}]/g, '\\$&' ) + '$' ) :
134 this.register( entry
.path
.toString(), entry
);
138 * @deprecated Use #addRoute
140 OO
.Router
.prototype.route
= OO
.Router
.prototype.addRoute
;
143 * Navigate to a specific route.
145 * @param {string} path String with a route (hash without #).
147 OO
.Router
.prototype.navigate = function ( path
) {
148 var history
= window
.history
;
149 // Take advantage of `pushState` when available, to clear the hash and
150 // not leave `#` in the history. An entry with `#` in the history has
151 // the side-effect of resetting the scroll position when navigating the
153 if ( path
=== '' && history
&& history
.pushState
) {
154 // To clear the hash we need to cut the hash from the URL.
155 path
= window
.location
.href
.replace( /#.*$/, '' );
156 history
.pushState( null, document
.title
, path
);
159 window
.location
.hash
= path
;
164 * Navigate to the previous route. This is a wrapper for window.history.back
166 * @return {jQuery.Promise} Promise which resolves when the back navigation is complete
168 OO
.Router
.prototype.back = function () {
171 deferred
= $.Deferred();
173 this.once( 'popstate', function () {
174 clearTimeout( timeoutID
);
178 window
.history
.back();
180 // If for some reason (old browser, bug in IE/windows 8.1, etc) popstate doesn't fire,
181 // resolve manually. Since we don't know for sure which browsers besides IE10/11 have
182 // this problem, it's better to fall back this way rather than singling out browsers
183 // and resolving the deferred request for them individually.
184 // See https://connect.microsoft.com/IE/feedback/details/793618/history-back-popstate-not-working-as-expected-in-webview-control
185 // Give browser a few ms to update its history.
186 timeoutID
= setTimeout( function () {
187 router
.off( 'popstate' );
191 return deferred
.promise();
195 * Get current path (hash).
197 * @return {string} Current path.
199 OO
.Router
.prototype.getPath = function () {
200 return window
.location
.hash
.slice( 1 );
204 * @deprecated Use static method
206 OO
.Router
.prototype.isSupported
= OO
.Router
.static.isSupported
;
208 if ( typeof module
!== 'undefined' && module
.exports
) {
209 module
.exports
= OO
.Router
;