UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

365 lines (364 loc) 11.2 kB
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); require("./kendo.core-kmRaf_Lg.js"); //#region ../src/kendo.router.js const __meta__ = { id: "router", name: "Router", category: "framework", description: "The Router class is responsible for tracking the application state and navigating between the application states.", depends: ["core"], hidden: false }; (function($, undefined) { var kendo = window.kendo, CHANGE = "change", BACK = "back", SAME = "same", support = kendo.support, location = window.location, history = window.history, CHECK_URL_INTERVAL = 50, BROKEN_BACK_NAV = kendo.support.browser.msie, hashStrip = /^#*/, document = window.document; function absoluteURL(path, pathPrefix) { if (!pathPrefix) return path; if (path + "/" === pathPrefix) path = pathPrefix; if (!new RegExp("^" + pathPrefix, "i").test(path)) path = pathPrefix + "/" + path; return location.protocol + "//" + (location.host + "/" + path).replace(/\/\/+/g, "/"); } function hashDelimiter(bang) { return bang ? "#!" : "#"; } function locationHash(hashDelimiter) { var href = location.href; if (hashDelimiter === "#!" && href.indexOf("#") > -1 && href.indexOf("#!") < 0) return null; return href.split(hashDelimiter)[1] || ""; } function stripRoot(root, url) { if (url.indexOf(root) === 0) return url.substr(root.length).replace(/\/\//g, "/"); else return url; } var HistoryAdapter = kendo.Class.extend({ back: function() { if (BROKEN_BACK_NAV) setTimeout(function() { history.back(); }); else history.back(); }, forward: function() { if (BROKEN_BACK_NAV) setTimeout(function() { history.forward(); }); else history.forward(); }, length: function() { return history.length; }, replaceLocation: function(url) { location.replace(url); } }); var PushStateAdapter = HistoryAdapter.extend({ init: function(root) { this.root = root; }, navigate: function(to) { history.pushState({}, document.title, absoluteURL(to, this.root)); }, replace: function(to) { history.replaceState({}, document.title, absoluteURL(to, this.root)); }, normalize: function(url) { return stripRoot(this.root, url); }, current: function() { var current = location.pathname; if (location.search) current += location.search; return stripRoot(this.root, current); }, change: function(callback) { $(window).bind("popstate.kendo", callback); }, stop: function() { $(window).unbind("popstate.kendo"); }, normalizeCurrent: function(options) { var fixedUrl, root = options.root, pathname = location.pathname, hash = locationHash(hashDelimiter(options.hashBang)); if (root === pathname + "/") fixedUrl = root; if (root === pathname && hash) fixedUrl = absoluteURL(hash.replace(hashStrip, ""), root); if (fixedUrl) history.pushState({}, document.title, fixedUrl); } }); function fixHash(url) { return url.replace(/^(#)?/, "#"); } function fixBang(url) { return url.replace(/^(#(!)?)?/, "#!"); } var HashAdapter = HistoryAdapter.extend({ init: function(bang) { this._id = kendo.guid(); this.prefix = hashDelimiter(bang); this.fix = bang ? fixBang : fixHash; }, navigate: function(to) { location.hash = this.fix(to); }, replace: function(to) { this.replaceLocation(this.fix(to)); }, normalize: function(url) { if (url.indexOf(this.prefix) < 0) return url; else return url.split(this.prefix)[1]; }, change: function(callback) { if (support.hashChange) $(window).on("hashchange." + this._id, callback); else this._interval = setInterval(callback, CHECK_URL_INTERVAL); }, stop: function() { $(window).off("hashchange." + this._id); clearInterval(this._interval); }, current: function() { return locationHash(this.prefix); }, normalizeCurrent: function(options) { var pathname = location.pathname, root = options.root; if (options.pushState && root !== pathname) { this.replaceLocation(root + this.prefix + stripRoot(root, pathname)); return true; } return false; } }); var History = kendo.Observable.extend({ start: function(options) { options = options || {}; this.bind([ CHANGE, BACK, SAME ], options); if (this._started) return; this._started = true; options.root = options.root || "/"; var adapter = this.createAdapter(options), current; if (adapter.normalizeCurrent(options)) return; current = adapter.current(); $.extend(this, { adapter, root: options.root, historyLength: adapter.length(), current, locations: [current] }); adapter.change(this._checkUrl.bind(this)); }, createAdapter: function(options) { return support.pushState && options.pushState ? new PushStateAdapter(options.root) : new HashAdapter(options.hashBang); }, stop: function() { if (!this._started) return; this.adapter.stop(); this.unbind(CHANGE); this._started = false; }, change: function(callback) { this.bind(CHANGE, callback); }, replace: function(to, silent) { this._navigate(to, silent, function(adapter) { adapter.replace(to); this.locations[this.locations.length - 1] = this.current; }); }, navigate: function(to, silent) { if (to === "#:back") { this.backCalled = true; this.adapter.back(); return; } this._navigate(to, silent, function(adapter) { adapter.navigate(to); this.locations.push(this.current); }); }, _navigate: function(to, silent, callback) { var adapter = this.adapter; to = adapter.normalize(to); if (this.current === to || this.current === decodeURIComponent(to)) { this.trigger(SAME); return; } if (!silent) { if (this.trigger(CHANGE, { url: to, decode: false })) return; } this.current = to; callback.call(this, adapter); this.historyLength = adapter.length(); }, _checkUrl: function() { var adapter = this.adapter, current = adapter.current(), newLength = adapter.length(), navigatingInExisting = this.historyLength === newLength, back = current === this.locations[this.locations.length - 2] && navigatingInExisting, backCalled = this.backCalled, prev = this.current; if (current === null || this.current === current || this.current === decodeURIComponent(current)) return true; this.historyLength = newLength; this.backCalled = false; this.current = current; if (back && this.trigger("back", { url: prev, to: current })) { adapter.forward(); this.current = prev; return; } if (this.trigger(CHANGE, { url: current, backButtonPressed: !backCalled })) { if (back) adapter.forward(); else { adapter.back(); this.historyLength--; } this.current = prev; return; } if (back) this.locations.pop(); else this.locations.push(current); } }); kendo.History = History; kendo.History.HistoryAdapter = HistoryAdapter; kendo.History.HashAdapter = HashAdapter; kendo.History.PushStateAdapter = PushStateAdapter; kendo.absoluteURL = absoluteURL; kendo.history = new History(); })(window.kendo.jQuery); var kendo_router_default = kendo; (function() { var kendo = window.kendo, history = kendo.history, Observable = kendo.Observable, INIT = "init", ROUTE_MISSING = "routeMissing", CHANGE = "change", BACK = "back", SAME = "same", optionalParam = /\((.*?)\)/g, namedParam = /(\(\?)?:\w+/g, splatParam = /\*\w+/g, escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; function namedParamReplace(match, optional) { return optional ? match : "([^/]+)"; } function routeToRegExp(route, ignoreCase) { return new RegExp("^" + route.replace(escapeRegExp, "\\$&").replace(optionalParam, "(?:$1)?").replace(namedParam, namedParamReplace).replace(splatParam, "(.*?)") + "$", ignoreCase ? "i" : ""); } function stripUrl(url) { return url.replace(/(\?.*)|(#.*)/g, ""); } var Route = kendo.Class.extend({ init: function(route, callback, ignoreCase) { if (!(route instanceof RegExp)) route = routeToRegExp(route, ignoreCase); this.route = route; this._callback = callback; }, callback: function(url, back, decode) { var params, idx = 0, length, queryStringParams = kendo.parseQueryStringParams(url); queryStringParams._back = back; url = stripUrl(url); params = this.route.exec(url).slice(1); length = params.length; if (decode) { for (; idx < length; idx++) if (typeof params[idx] !== "undefined") params[idx] = decodeURIComponent(params[idx]); } params.push(queryStringParams); this._callback.apply(null, params); }, worksWith: function(url, back, decode) { if (this.route.test(stripUrl(url))) { this.callback(url, back, decode); return true; } else return false; } }); kendo.Router = Observable.extend({ init: function(options) { if (!options) options = {}; Observable.fn.init.call(this); this.routes = []; this.pushState = options.pushState; this.hashBang = options.hashBang; this.root = options.root; this.ignoreCase = options.ignoreCase !== false; this.bind([ INIT, ROUTE_MISSING, CHANGE, SAME, BACK ], options); }, destroy: function() { history.unbind(CHANGE, this._urlChangedProxy); history.unbind(SAME, this._sameProxy); history.unbind(BACK, this._backProxy); this.unbind(); }, start: function() { var that = this, sameProxy = function() { that._same(); }, backProxy = function(e) { that._back(e); }, urlChangedProxy = function(e) { that._urlChanged(e); }; history.start({ same: sameProxy, change: urlChangedProxy, back: backProxy, pushState: that.pushState, hashBang: that.hashBang, root: that.root }); var initEventObject = { url: history.current || "/", preventDefault: $.noop }; if (!that.trigger(INIT, initEventObject)) that._urlChanged(initEventObject); this._urlChangedProxy = urlChangedProxy; this._backProxy = backProxy; }, route: function(route, callback) { this.routes.push(new Route(route, callback, this.ignoreCase)); }, navigate: function(url, silent) { kendo.history.navigate(url, silent); }, replace: function(url, silent) { kendo.history.replace(url, silent); }, _back: function(e) { if (this.trigger(BACK, { url: e.url, to: e.to })) e.preventDefault(); }, _same: function() { this.trigger(SAME); }, _urlChanged: function(e) { var url = e.url; var decode = !!e.decode; var back = e.backButtonPressed; if (!url) url = "/"; if (this.trigger(CHANGE, { url: e.url, params: kendo.parseQueryStringParams(e.url), backButtonPressed: back })) { e.preventDefault(); return; } var idx = 0, routes = this.routes, route, length = routes.length; for (; idx < length; idx++) { route = routes[idx]; if (route.worksWith(url, back, decode)) return; } if (this.trigger(ROUTE_MISSING, { url, params: kendo.parseQueryStringParams(url), backButtonPressed: back })) e.preventDefault(); } }); })(); //#endregion exports.__meta__ = __meta__; exports.default = kendo_router_default;