diff --git a/dist/amd/aurelia-history-browser.js b/dist/amd/aurelia-history-browser.js index 4c68ff0..238ced5 100644 --- a/dist/amd/aurelia-history-browser.js +++ b/dist/amd/aurelia-history-browser.js @@ -1,358 +1,298 @@ -define(['exports', 'aurelia-pal', 'aurelia-history'], function (exports, _aureliaPal, _aureliaHistory) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports.BrowserHistory = exports.DefaultLinkHandler = exports.LinkHandler = undefined; - exports.configure = configure; - - var _class, _temp; - - function _possibleConstructorReturn(self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); +define(['exports', 'aurelia-history', 'aurelia-pal'], function (exports, aureliaHistory, aureliaPal) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } - return call && (typeof call === "object" || typeof call === "function") ? call : self; - } - - function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + var LinkHandler = (function () { + function LinkHandler() { + } + LinkHandler.prototype.activate = function (history) { }; + LinkHandler.prototype.deactivate = function () { }; + return LinkHandler; + }()); + var DefaultLinkHandler = (function (_super) { + __extends(DefaultLinkHandler, _super); + function DefaultLinkHandler() { + var _this = _super.call(this) || this; + _this.handler = function (e) { + var _a = DefaultLinkHandler.getEventInfo(e), shouldHandleEvent = _a.shouldHandleEvent, href = _a.href; + if (shouldHandleEvent) { + e.preventDefault(); + _this.history.navigate(href); + } + }; + return _this; + } + DefaultLinkHandler.prototype.activate = function (history) { + if (history._hasPushState) { + this.history = history; + aureliaPal.DOM.addEventListener('click', this.handler, true); + } + }; + DefaultLinkHandler.prototype.deactivate = function () { + aureliaPal.DOM.removeEventListener('click', this.handler, true); + }; + DefaultLinkHandler.getEventInfo = function (event) { + var $event = event; + var info = { + shouldHandleEvent: false, + href: null, + anchor: null + }; + var target = DefaultLinkHandler.findClosestAnchor($event.target); + if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { + return info; + } + if (hasAttribute(target, 'download') + || hasAttribute(target, 'router-ignore') + || hasAttribute(target, 'data-router-ignore')) { + return info; + } + if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) { + return info; + } + var href = target.getAttribute('href'); + info.anchor = target; + info.href = href; + var leftButtonClicked = $event.which === 1; + var isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); + info.shouldHandleEvent = leftButtonClicked && isRelative; + return info; + }; + DefaultLinkHandler.findClosestAnchor = function (el) { + while (el) { + if (el.tagName === 'A') { + return el; + } + el = el.parentNode; + } + }; + DefaultLinkHandler.targetIsThisWindow = function (target) { + var targetWindow = target.getAttribute('target'); + var win = aureliaPal.PLATFORM.global; + return !targetWindow || + targetWindow === win.name || + targetWindow === '_self'; + }; + return DefaultLinkHandler; + }(LinkHandler)); + var hasAttribute = function (el, attr) { return el.hasAttribute(attr); }; + + var BrowserHistory = (function (_super) { + __extends(BrowserHistory, _super); + function BrowserHistory(linkHandler) { + var _this = _super.call(this) || this; + _this._isActive = false; + _this._checkUrlCallback = _this._checkUrl.bind(_this); + _this.location = aureliaPal.PLATFORM.location; + _this.history = aureliaPal.PLATFORM.history; + _this.linkHandler = linkHandler; + return _this; + } + BrowserHistory.prototype.activate = function (options) { + if (this._isActive) { + throw new Error('History has already been activated.'); + } + var $history = this.history; + var wantsPushState = !!options.pushState; + this._isActive = true; + var normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options); + var rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/'); + var wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false; + var hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState); + var eventName; + if (hasPushState) { + eventName = 'popstate'; + } + else if (wantsHashChange) { + eventName = 'hashchange'; + } + aureliaPal.PLATFORM.addEventListener(eventName, this._checkUrlCallback); + if (wantsHashChange && wantsPushState) { + var $location = this.location; + var atRoot = $location.pathname.replace(/[^\/]$/, '$&/') === rootUrl; + if (!hasPushState && !atRoot) { + var fragment = this.fragment = this._getFragment(null, true); + $location.replace(rootUrl + $location.search + '#' + fragment); + return true; + } + else if (hasPushState && atRoot && $location.hash) { + var fragment = this.fragment = this._getHash().replace(routeStripper, ''); + $history.replaceState({}, aureliaPal.DOM.title, rootUrl + fragment + $location.search); + } + } + if (!this.fragment) { + this.fragment = this._getFragment(''); + } + this.linkHandler.activate(this); + if (!normalizedOptions.silent) { + return this._loadUrl(''); + } + }; + BrowserHistory.prototype.deactivate = function () { + var handler = this._checkUrlCallback; + aureliaPal.PLATFORM.removeEventListener('popstate', handler); + aureliaPal.PLATFORM.removeEventListener('hashchange', handler); + this._isActive = false; + this.linkHandler.deactivate(); + }; + BrowserHistory.prototype.getAbsoluteRoot = function () { + var $location = this.location; + var origin = createOrigin($location.protocol, $location.hostname, $location.port); + return "" + origin + this.root; + }; + BrowserHistory.prototype.navigate = function (fragment, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b.trigger, trigger = _c === void 0 ? true : _c, _d = _b.replace, replace = _d === void 0 ? false : _d; + var location = this.location; + if (fragment && absoluteUrl.test(fragment)) { + location.href = fragment; + return true; + } + if (!this._isActive) { + return false; + } + fragment = this._getFragment(fragment || ''); + if (this.fragment === fragment && !replace) { + return false; + } + this.fragment = fragment; + var url = this.root + fragment; + if (fragment === '' && url !== '/') { + url = url.slice(0, -1); + } + if (this._hasPushState) { + url = url.replace('//', '/'); + this.history[replace ? 'replaceState' : 'pushState']({}, aureliaPal.DOM.title, url); + } + else if (this._wantsHashChange) { + updateHash(location, fragment, replace); + } + else { + location.assign(url); + } + if (trigger) { + return this._loadUrl(fragment); + } + return true; + }; + BrowserHistory.prototype.navigateBack = function () { + this.history.back(); + }; + BrowserHistory.prototype.setTitle = function (title) { + aureliaPal.DOM.title = title; + }; + BrowserHistory.prototype.setState = function (key, value) { + var $history = this.history; + var state = Object.assign({}, $history.state); + var _a = this.location, pathname = _a.pathname, search = _a.search, hash = _a.hash; + state[key] = value; + $history.replaceState(state, null, "" + pathname + search + hash); + }; + BrowserHistory.prototype.getState = function (key) { + var state = Object.assign({}, this.history.state); + return state[key]; + }; + BrowserHistory.prototype.getHistoryIndex = function () { + var historyIndex = this.getState('HistoryIndex'); + if (historyIndex === undefined) { + historyIndex = this.history.length - 1; + this.setState('HistoryIndex', historyIndex); + } + return historyIndex; + }; + BrowserHistory.prototype.go = function (movement) { + this.history.go(movement); + }; + BrowserHistory.prototype._getHash = function () { + return this.location.hash.substr(1); + }; + BrowserHistory.prototype._getFragment = function (fragment, forcePushState) { + var rootUrl; + if (!fragment) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + var location_1 = this.location; + fragment = location_1.pathname + location_1.search; + rootUrl = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(rootUrl)) { + fragment = fragment.substr(rootUrl.length); + } + } + else { + fragment = this._getHash(); + } + } + return '/' + fragment.replace(routeStripper, ''); + }; + BrowserHistory.prototype._checkUrl = function () { + var current = this._getFragment(''); + if (current !== this.fragment) { + this._loadUrl(''); + } + }; + BrowserHistory.prototype._loadUrl = function (fragmentOverride) { + var fragment = this.fragment = this._getFragment(fragmentOverride); + return this.options.routeHandler ? + this.options.routeHandler(fragment) : + false; + }; + BrowserHistory.inject = [LinkHandler]; + return BrowserHistory; + }(aureliaHistory.History)); + var routeStripper = /^#?\/*|\s+$/g; + var rootStripper = /^\/+|\/+$/g; + var trailingSlash = /\/$/; + var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; + function updateHash($location, fragment, replace) { + if (replace) { + var href = $location.href.replace(/(javascript:|#).*$/, ''); + $location.replace(href + '#' + fragment); + } + else { + $location.hash = '#' + fragment; + } + } + function createOrigin(protocol, hostname, port) { + return protocol + "//" + hostname + (port ? ':' + port : ''); } - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - } - - - - var LinkHandler = exports.LinkHandler = function () { - function LinkHandler() { - + function configure(config) { + var $config = config; + $config.singleton(aureliaHistory.History, BrowserHistory); + $config.transient(LinkHandler, DefaultLinkHandler); } - LinkHandler.prototype.activate = function activate(history) {}; - - LinkHandler.prototype.deactivate = function deactivate() {}; - - return LinkHandler; - }(); - - var DefaultLinkHandler = exports.DefaultLinkHandler = function (_LinkHandler) { - _inherits(DefaultLinkHandler, _LinkHandler); - - function DefaultLinkHandler() { - - - var _this = _possibleConstructorReturn(this, _LinkHandler.call(this)); - - _this.handler = function (e) { - var _DefaultLinkHandler$g = DefaultLinkHandler.getEventInfo(e), - shouldHandleEvent = _DefaultLinkHandler$g.shouldHandleEvent, - href = _DefaultLinkHandler$g.href; - - if (shouldHandleEvent) { - e.preventDefault(); - _this.history.navigate(href); - } - }; - return _this; - } - - DefaultLinkHandler.prototype.activate = function activate(history) { - if (history._hasPushState) { - this.history = history; - _aureliaPal.DOM.addEventListener('click', this.handler, true); - } - }; - - DefaultLinkHandler.prototype.deactivate = function deactivate() { - _aureliaPal.DOM.removeEventListener('click', this.handler); - }; - - DefaultLinkHandler.getEventInfo = function getEventInfo(event) { - var info = { - shouldHandleEvent: false, - href: null, - anchor: null - }; - - var target = DefaultLinkHandler.findClosestAnchor(event.target); - if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { - return info; - } - - if (target.hasAttribute('download') || target.hasAttribute('router-ignore') || target.hasAttribute('data-router-ignore')) { - return info; - } - - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return info; - } - - var href = target.getAttribute('href'); - info.anchor = target; - info.href = href; - - var leftButtonClicked = event.which === 1; - var isRelative = href && !(href.charAt(0) === '#' || /^[a-z]+:/i.test(href)); - - info.shouldHandleEvent = leftButtonClicked && isRelative; - return info; - }; - - DefaultLinkHandler.findClosestAnchor = function findClosestAnchor(el) { - while (el) { - if (el.tagName === 'A') { - return el; - } - - el = el.parentNode; - } - }; - - DefaultLinkHandler.targetIsThisWindow = function targetIsThisWindow(target) { - var targetWindow = target.getAttribute('target'); - var win = _aureliaPal.PLATFORM.global; - - return !targetWindow || targetWindow === win.name || targetWindow === '_self'; - }; - - return DefaultLinkHandler; - }(LinkHandler); - - function configure(config) { - config.singleton(_aureliaHistory.History, BrowserHistory); - config.transient(LinkHandler, DefaultLinkHandler); - } - - var BrowserHistory = exports.BrowserHistory = (_temp = _class = function (_History) { - _inherits(BrowserHistory, _History); - - function BrowserHistory(linkHandler) { - - - var _this2 = _possibleConstructorReturn(this, _History.call(this)); - - _this2._isActive = false; - _this2._checkUrlCallback = _this2._checkUrl.bind(_this2); - - _this2.location = _aureliaPal.PLATFORM.location; - _this2.history = _aureliaPal.PLATFORM.history; - _this2.linkHandler = linkHandler; - return _this2; - } - - BrowserHistory.prototype.activate = function activate(options) { - if (this._isActive) { - throw new Error('History has already been activated.'); - } - - var wantsPushState = !!options.pushState; - - this._isActive = true; - this.options = Object.assign({}, { root: '/' }, this.options, options); - - this.root = ('/' + this.options.root + '/').replace(rootStripper, '/'); - - this._wantsHashChange = this.options.hashChange !== false; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - - var eventName = void 0; - if (this._hasPushState) { - eventName = 'popstate'; - } else if (this._wantsHashChange) { - eventName = 'hashchange'; - } + exports.BrowserHistory = BrowserHistory; + exports.DefaultLinkHandler = DefaultLinkHandler; + exports.LinkHandler = LinkHandler; + exports.configure = configure; - _aureliaPal.PLATFORM.addEventListener(eventName, this._checkUrlCallback); - - if (this._wantsHashChange && wantsPushState) { - var loc = this.location; - var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; - - if (!this._hasPushState && !atRoot) { - this.fragment = this._getFragment(null, true); - this.location.replace(this.root + this.location.search + '#' + this.fragment); - - return true; - } else if (this._hasPushState && atRoot && loc.hash) { - this.fragment = this._getHash().replace(routeStripper, ''); - this.history.replaceState({}, _aureliaPal.DOM.title, this.root + this.fragment + loc.search); - } - } - - if (!this.fragment) { - this.fragment = this._getFragment(); - } - - this.linkHandler.activate(this); - - if (!this.options.silent) { - return this._loadUrl(); - } - }; - - BrowserHistory.prototype.deactivate = function deactivate() { - _aureliaPal.PLATFORM.removeEventListener('popstate', this._checkUrlCallback); - _aureliaPal.PLATFORM.removeEventListener('hashchange', this._checkUrlCallback); - this._isActive = false; - this.linkHandler.deactivate(); - }; - - BrowserHistory.prototype.getAbsoluteRoot = function getAbsoluteRoot() { - var origin = createOrigin(this.location.protocol, this.location.hostname, this.location.port); - return '' + origin + this.root; - }; - - BrowserHistory.prototype.navigate = function navigate(fragment) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$trigger = _ref.trigger, - trigger = _ref$trigger === undefined ? true : _ref$trigger, - _ref$replace = _ref.replace, - replace = _ref$replace === undefined ? false : _ref$replace; - - if (fragment && absoluteUrl.test(fragment)) { - this.location.href = fragment; - return true; - } - - if (!this._isActive) { - return false; - } - - fragment = this._getFragment(fragment || ''); - - if (this.fragment === fragment && !replace) { - return false; - } - - this.fragment = fragment; - - var url = this.root + fragment; - - if (fragment === '' && url !== '/') { - url = url.slice(0, -1); - } - - if (this._hasPushState) { - url = url.replace('//', '/'); - this.history[replace ? 'replaceState' : 'pushState']({}, _aureliaPal.DOM.title, url); - } else if (this._wantsHashChange) { - updateHash(this.location, fragment, replace); - } else { - this.location.assign(url); - } - - if (trigger) { - return this._loadUrl(fragment); - } - - return true; - }; - - BrowserHistory.prototype.navigateBack = function navigateBack() { - this.history.back(); - }; - - BrowserHistory.prototype.setTitle = function setTitle(title) { - _aureliaPal.DOM.title = title; - }; - - BrowserHistory.prototype.setState = function setState(key, value) { - var state = Object.assign({}, this.history.state); - var _location = this.location, - pathname = _location.pathname, - search = _location.search, - hash = _location.hash; - - state[key] = value; - this.history.replaceState(state, null, '' + pathname + search + hash); - }; - - BrowserHistory.prototype.getState = function getState(key) { - var state = Object.assign({}, this.history.state); - return state[key]; - }; - - BrowserHistory.prototype.getHistoryIndex = function getHistoryIndex() { - var historyIndex = this.getState('HistoryIndex'); - if (historyIndex === undefined) { - historyIndex = this.history.length - 1; - this.setState('HistoryIndex', historyIndex); - } - return historyIndex; - }; - - BrowserHistory.prototype.go = function go(movement) { - this.history.go(movement); - }; - - BrowserHistory.prototype._getHash = function _getHash() { - return this.location.hash.substr(1); - }; - - BrowserHistory.prototype._getFragment = function _getFragment(fragment, forcePushState) { - var root = void 0; - - if (!fragment) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname + this.location.search; - root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) { - fragment = fragment.substr(root.length); - } - } else { - fragment = this._getHash(); - } - } - - return '/' + fragment.replace(routeStripper, ''); - }; - - BrowserHistory.prototype._checkUrl = function _checkUrl() { - var current = this._getFragment(); - if (current !== this.fragment) { - this._loadUrl(); - } - }; - - BrowserHistory.prototype._loadUrl = function _loadUrl(fragmentOverride) { - var fragment = this.fragment = this._getFragment(fragmentOverride); - - return this.options.routeHandler ? this.options.routeHandler(fragment) : false; - }; - - return BrowserHistory; - }(_aureliaHistory.History), _class.inject = [LinkHandler], _temp); - - var routeStripper = /^#?\/*|\s+$/g; - - var rootStripper = /^\/+|\/+$/g; - - var trailingSlash = /\/$/; - - var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; - - function updateHash(location, fragment, replace) { - if (replace) { - var _href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(_href + '#' + fragment); - } else { - location.hash = '#' + fragment; - } - } + Object.defineProperty(exports, '__esModule', { value: true }); - function createOrigin(protocol, hostname, port) { - return protocol + '//' + hostname + (port ? ':' + port : ''); - } -}); \ No newline at end of file +}); +//# sourceMappingURL=aurelia-history-browser.js.map diff --git a/dist/amd/aurelia-history-browser.js.map b/dist/amd/aurelia-history-browser.js.map new file mode 100644 index 0000000..10a150e --- /dev/null +++ b/dist/amd/aurelia-history-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"aurelia-history-browser.js","sources":["../../src/link-handler.ts","../../src/browser-history.ts","../../src/aurelia-history-browser.ts"],"sourcesContent":["import { DOM, PLATFORM } from 'aurelia-pal';\nimport { BrowserHistory } from './browser-history';\nimport { AnchorEventInfo } from './interfaces';\n\n/**\n * Class responsible for handling interactions that should trigger browser history navigations.\n */\nexport class LinkHandler {\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {/**/}\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {/**/}\n}\n\n/**\n * The default LinkHandler implementation. Navigations are triggered by click events on\n * anchor elements with relative hrefs when the history instance is using pushstate.\n */\nexport class DefaultLinkHandler extends LinkHandler {\n\n /**@internal */\n handler: (e: Event) => void;\n\n /**@internal */\n history: BrowserHistory;\n /**\n * Creates an instance of DefaultLinkHandler.\n */\n constructor() {\n super();\n\n this.handler = (e) => {\n let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e);\n\n if (shouldHandleEvent) {\n e.preventDefault();\n this.history.navigate(href);\n }\n };\n }\n\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {\n if (history._hasPushState) {\n this.history = history;\n DOM.addEventListener('click', this.handler, true);\n }\n }\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {\n DOM.removeEventListener('click', this.handler, true);\n }\n\n /**\n * Gets the href and a \"should handle\" recommendation, given an Event.\n *\n * @param event The Event to inspect for target anchor and href.\n */\n static getEventInfo(event: Event): AnchorEventInfo {\n let $event = event as MouseEvent;\n let info = {\n shouldHandleEvent: false,\n href: null,\n anchor: null\n };\n\n let target = DefaultLinkHandler.findClosestAnchor($event.target as Element);\n if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) {\n return info;\n }\n\n if (hasAttribute(target, 'download')\n || hasAttribute(target, 'router-ignore')\n || hasAttribute(target, 'data-router-ignore')\n ) {\n return info;\n }\n\n if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) {\n return info;\n }\n\n let href = target.getAttribute('href');\n info.anchor = target;\n info.href = href;\n\n let leftButtonClicked = $event.which === 1;\n let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href));\n\n info.shouldHandleEvent = leftButtonClicked && isRelative;\n return info;\n }\n\n /**\n * Finds the closest ancestor that's an anchor element.\n *\n * @param el The element to search upward from.\n * @returns The link element that is the closest ancestor.\n */\n static findClosestAnchor(el: Element): Element {\n while (el) {\n if (el.tagName === 'A') {\n return el;\n }\n\n el = el.parentNode as Element;\n }\n }\n\n /**\n * Gets a value indicating whether or not an anchor targets the current window.\n *\n * @param target The anchor element whose target should be inspected.\n * @returns True if the target of the link element is this window; false otherwise.\n */\n static targetIsThisWindow(target: Element): boolean {\n let targetWindow = target.getAttribute('target');\n let win = PLATFORM.global;\n\n return !targetWindow ||\n targetWindow === win.name ||\n targetWindow === '_self';\n }\n}\n\nconst hasAttribute = (el: Element, attr: string) => el.hasAttribute(attr);\n","import { DOM, PLATFORM } from 'aurelia-pal';\nimport { LinkHandler } from './link-handler';\nimport { History } from 'aurelia-history';\n\n/**\n * An implementation of the basic history API.\n */\nexport class BrowserHistory extends History {\n /**@internal */\n static inject = [LinkHandler];\n\n /**@internal */\n _isActive: boolean;\n\n /**@internal*/\n _checkUrlCallback: any;\n /**@internal*/\n location: Location;\n /**@internal*/\n history: typeof PLATFORM['history'];\n /**@internal*/\n linkHandler: LinkHandler;\n /**@internal*/\n options: any;\n /**@internal*/\n root: string;\n /**@internal*/\n _wantsHashChange: boolean;\n /**@internal*/\n _hasPushState: boolean;\n /**@internal*/\n fragment: string;\n\n /**\n * Creates an instance of BrowserHistory\n * @param linkHandler An instance of LinkHandler.\n */\n constructor(linkHandler: LinkHandler) {\n super();\n\n this._isActive = false;\n this._checkUrlCallback = this._checkUrl.bind(this);\n\n this.location = PLATFORM.location;\n this.history = PLATFORM.history;\n this.linkHandler = linkHandler;\n }\n\n /**\n * Activates the history object.\n * @param options The set of options to activate history with.\n * @returns Whether or not activation occurred.\n */\n activate(options?: Object): boolean {\n if (this._isActive) {\n throw new Error('History has already been activated.');\n }\n\n let $history = this.history;\n let wantsPushState = !!(options as any).pushState;\n\n this._isActive = true;\n let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options);\n\n // Normalize root to always include a leading and trailing slash.\n let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/');\n\n let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false;\n let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState);\n\n // Determine how we check the URL state.\n let eventName: string;\n if (hasPushState) {\n eventName = 'popstate';\n } else if (wantsHashChange) {\n eventName = 'hashchange';\n }\n\n PLATFORM.addEventListener(eventName, this._checkUrlCallback);\n\n // Determine if we need to change the base url, for a pushState link\n // opened by a non-pushState browser.\n if (wantsHashChange && wantsPushState) {\n // Transition from hashChange to pushState or vice versa if both are requested.\n let $location = this.location;\n let atRoot = $location.pathname.replace(/[^\\/]$/, '$&/') === rootUrl;\n\n // If we've started off with a route from a `pushState`-enabled\n // browser, but we're currently in a browser that doesn't support it...\n if (!hasPushState && !atRoot) {\n let fragment = this.fragment = this._getFragment(null, true);\n $location.replace(rootUrl + $location.search + '#' + fragment);\n // Return immediately as browser will do redirect to new url\n return true;\n\n // Or if we've started out with a hash-based route, but we're currently\n // in a browser where it could be `pushState`-based instead...\n } else if (hasPushState && atRoot && $location.hash) {\n let fragment = this.fragment = this._getHash().replace(routeStripper, '');\n $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search);\n }\n }\n\n if (!this.fragment) {\n this.fragment = this._getFragment('');\n }\n\n this.linkHandler.activate(this);\n\n if (!normalizedOptions.silent) {\n return this._loadUrl('');\n }\n }\n\n /**\n * Deactivates the history object.\n */\n deactivate(): void {\n const handler = this._checkUrlCallback;\n PLATFORM.removeEventListener('popstate', handler);\n PLATFORM.removeEventListener('hashchange', handler);\n this._isActive = false;\n this.linkHandler.deactivate();\n }\n\n /**\n * Returns the fully-qualified root of the current history object.\n * @returns The absolute root of the application.\n */\n getAbsoluteRoot(): string {\n let $location = this.location;\n let origin = createOrigin($location.protocol, $location.hostname, $location.port);\n return `${origin}${this.root}`;\n }\n\n /**\n * Causes a history navigation to occur.\n *\n * @param fragment The history fragment to navigate to.\n * @param options The set of options that specify how the navigation should occur.\n * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred.\n */\n navigate(fragment?: string, {trigger = true, replace = false} = {}): boolean {\n let location = this.location;\n if (fragment && absoluteUrl.test(fragment)) {\n location.href = fragment;\n return true;\n }\n\n if (!this._isActive) {\n return false;\n }\n\n fragment = this._getFragment(fragment || '');\n\n if (this.fragment === fragment && !replace) {\n return false;\n }\n\n this.fragment = fragment;\n\n let url = this.root + fragment;\n\n // Don't include a trailing slash on the root.\n if (fragment === '' && url !== '/') {\n url = url.slice(0, -1);\n }\n\n // If pushState is available, we use it to set the fragment as a real URL.\n if (this._hasPushState) {\n url = url.replace('//', '/');\n this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url);\n } else if (this._wantsHashChange) {\n // If hash changes haven't been explicitly disabled, update the hash\n // fragment to store history.\n updateHash(location, fragment, replace);\n } else {\n // If you've told us that you explicitly don't want fallback hashchange-\n // based history, then `navigate` becomes a page refresh.\n location.assign(url);\n }\n\n if (trigger) {\n return this._loadUrl(fragment);\n }\n\n return true;\n }\n\n /**\n * Causes the history state to navigate back.\n */\n navigateBack(): void {\n this.history.back();\n }\n\n /**\n * Sets the document title.\n */\n setTitle(title: string): void {\n DOM.title = title;\n }\n\n /**\n * Sets a key in the history page state.\n * @param key The key for the value.\n * @param value The value to set.\n */\n setState(key: string, value: any): void {\n let $history = this.history;\n let state = Object.assign({}, $history.state);\n let { pathname, search, hash } = this.location;\n state[key] = value;\n $history.replaceState(state, null, `${pathname}${search}${hash}`);\n }\n\n /**\n * Gets a key in the history page state.\n * @param key The key for the value.\n * @return The value for the key.\n */\n getState(key: string): any {\n let state = Object.assign({}, this.history.state);\n return state[key];\n }\n\n /**\n * Returns the current index in the navigation history.\n * @returns The current index.\n */\n getHistoryIndex(): number {\n let historyIndex = this.getState('HistoryIndex');\n if (historyIndex === undefined) {\n historyIndex = this.history.length - 1;\n this.setState('HistoryIndex', historyIndex);\n }\n return historyIndex;\n }\n\n /**\n * Move to a specific position in the navigation history.\n * @param movement The amount of steps, positive or negative, to move.\n */\n go(movement: number): void {\n this.history.go(movement);\n }\n\n /**\n * @internal\n */\n _getHash(): string {\n return this.location.hash.substr(1);\n }\n\n /**\n * @internal\n */\n _getFragment(fragment: string, forcePushState?: boolean): string {\n let rootUrl: string;\n\n if (!fragment) {\n if (this._hasPushState || !this._wantsHashChange || forcePushState) {\n let location = this.location;\n fragment = location.pathname + location.search;\n rootUrl = this.root.replace(trailingSlash, '');\n if (!fragment.indexOf(rootUrl)) {\n fragment = fragment.substr(rootUrl.length);\n }\n } else {\n fragment = this._getHash();\n }\n }\n\n return '/' + fragment.replace(routeStripper, '');\n }\n\n /**\n * Url change handler.\n * Invoked when current fragment is different with previous fragment\n * @internal\n */\n _checkUrl(): void {\n let current = this._getFragment('');\n if (current !== this.fragment) {\n this._loadUrl('');\n }\n }\n\n /**\n * invoke routeHandler\n * @internal\n */\n _loadUrl(fragmentOverride: string): boolean {\n let fragment = this.fragment = this._getFragment(fragmentOverride);\n\n return this.options.routeHandler ?\n this.options.routeHandler(fragment) :\n false;\n }\n}\n\n// Cached regex for stripping a leading hash/slash and trailing space.\nconst routeStripper = /^#?\\/*|\\s+$/g;\n\n// Cached regex for stripping leading and trailing slashes.\nconst rootStripper = /^\\/+|\\/+$/g;\n\n// Cached regex for removing a trailing slash.\nconst trailingSlash = /\\/$/;\n\n// Cached regex for detecting if a URL is absolute,\n// i.e., starts with a scheme or is scheme-relative.\n// See http://www.ietf.org/rfc/rfc2396.txt section 3.1 for valid scheme format\nconst absoluteUrl = /^([a-z][a-z0-9+\\-.]*:)?\\/\\//i;\n\n// Update the hash location, either replacing the current entry, or adding\n// a new one to the browser history.\nfunction updateHash($location: Location, fragment: string, replace: boolean) {\n if (replace) {\n let href = $location.href.replace(/(javascript:|#).*$/, '');\n $location.replace(href + '#' + fragment);\n } else {\n // Some browsers require that `hash` contains a leading #.\n $location.hash = '#' + fragment;\n }\n}\n\nfunction createOrigin(protocol: string, hostname: string, port: string) {\n return `${protocol}//${hostname}${port ? ':' + port : ''}`;\n}\n","import {History} from 'aurelia-history';\nimport {LinkHandler, DefaultLinkHandler} from './link-handler';\nimport { BrowserHistory } from './browser-history';\n\n/**\n * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container.\n * @param config The FrameworkConfiguration object provided by Aurelia.\n */\nexport function configure(config: Object): void {\n // work around for converting to TS without breaking compat\n const $config = config as any;\n $config.singleton(History, BrowserHistory);\n $config.transient(LinkHandler, DefaultLinkHandler);\n}\n\nexport {\n LinkHandler,\n DefaultLinkHandler,\n BrowserHistory\n};\n"],"names":["tslib_1.__extends","DOM","PLATFORM","History"],"mappings":"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"} \ No newline at end of file diff --git a/dist/amd/index.js b/dist/amd/index.js deleted file mode 100644 index 4161cc5..0000000 --- a/dist/amd/index.js +++ /dev/null @@ -1,16 +0,0 @@ -define(['exports', './aurelia-history-browser'], function (exports, _aureliaHistoryBrowser) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - Object.keys(_aureliaHistoryBrowser).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _aureliaHistoryBrowser[key]; - } - }); - }); -}); \ No newline at end of file diff --git a/dist/aurelia-history-browser.d.ts b/dist/aurelia-history-browser.d.ts index d9cc6aa..948fc11 100644 --- a/dist/aurelia-history-browser.d.ts +++ b/dist/aurelia-history-browser.d.ts @@ -1,185 +1,145 @@ -import { - DOM, - PLATFORM -} from 'aurelia-pal'; -import { - History -} from 'aurelia-history'; +import { History } from 'aurelia-history'; +/** + * An implementation of the basic history API. + */ +export declare class BrowserHistory extends History { + /** + * Creates an instance of BrowserHistory + * @param linkHandler An instance of LinkHandler. + */ + constructor(linkHandler: LinkHandler); + /** + * Activates the history object. + * @param options The set of options to activate history with. + * @returns Whether or not activation occurred. + */ + activate(options?: Object): boolean; + /** + * Deactivates the history object. + */ + deactivate(): void; + /** + * Returns the fully-qualified root of the current history object. + * @returns The absolute root of the application. + */ + getAbsoluteRoot(): string; + /** + * Causes a history navigation to occur. + * + * @param fragment The history fragment to navigate to. + * @param options The set of options that specify how the navigation should occur. + * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred. + */ + navigate(fragment?: string, { trigger, replace }?: { + trigger?: boolean; + replace?: boolean; + }): boolean; + /** + * Causes the history state to navigate back. + */ + navigateBack(): void; + /** + * Sets the document title. + */ + setTitle(title: string): void; + /** + * Sets a key in the history page state. + * @param key The key for the value. + * @param value The value to set. + */ + setState(key: string, value: any): void; + /** + * Gets a key in the history page state. + * @param key The key for the value. + * @return The value for the key. + */ + getState(key: string): any; + /** + * Returns the current index in the navigation history. + * @returns The current index. + */ + getHistoryIndex(): number; + /** + * Move to a specific position in the navigation history. + * @param movement The amount of steps, positive or negative, to move. + */ + go(movement: number): void; +} /** * Provides information about how to handle an anchor event. */ -export declare interface AnchorEventInfo { - - /** - * Indicates whether the event should be handled or not. - */ - shouldHandleEvent: boolean; - - /** - * The href of the link or null if not-applicable. - */ - href: string; - - /** - * The anchor element or null if not-applicable. - */ - anchor: Element; +export interface AnchorEventInfo { + /** + * Indicates whether the event should be handled or not. + */ + shouldHandleEvent: boolean; + /** + * The href of the link or null if not-applicable. + */ + href: string; + /** + * The anchor element or null if not-applicable. + */ + anchor: Element; } - /** * Class responsible for handling interactions that should trigger browser history navigations. */ export declare class LinkHandler { - - /** - * Activate the instance. - * - * @param history The BrowserHistory instance that navigations should be dispatched to. - */ - activate(history: BrowserHistory): void; - - /** - * Deactivate the instance. Event handlers and other resources should be cleaned up here. - */ - deactivate(): void; + /** + * Activate the instance. + * + * @param history The BrowserHistory instance that navigations should be dispatched to. + */ + activate(history: BrowserHistory): void; + /** + * Deactivate the instance. Event handlers and other resources should be cleaned up here. + */ + deactivate(): void; } - -/** - * The default LinkHandler implementation. Navigations are triggered by click events on - * anchor elements with relative hrefs when the history instance is using pushstate. - */ /** * The default LinkHandler implementation. Navigations are triggered by click events on * anchor elements with relative hrefs when the history instance is using pushstate. */ export declare class DefaultLinkHandler extends LinkHandler { - - /** - * Creates an instance of DefaultLinkHandler. - */ - constructor(); - - /** - * Activate the instance. - * - * @param history The BrowserHistory instance that navigations should be dispatched to. - */ - activate(history: BrowserHistory): void; - - /** - * Deactivate the instance. Event handlers and other resources should be cleaned up here. - */ - deactivate(): void; - - /** - * Gets the href and a "should handle" recommendation, given an Event. - * - * @param event The Event to inspect for target anchor and href. - */ - static getEventInfo(event: Event): AnchorEventInfo; - - /** - * Finds the closest ancestor that's an anchor element. - * - * @param el The element to search upward from. - * @returns The link element that is the closest ancestor. - */ - static findClosestAnchor(el: Element): Element; - - /** - * Gets a value indicating whether or not an anchor targets the current window. - * - * @param target The anchor element whose target should be inspected. - * @returns True if the target of the link element is this window; false otherwise. - */ - static targetIsThisWindow(target: Element): boolean; + /** + * Creates an instance of DefaultLinkHandler. + */ + constructor(); + /** + * Activate the instance. + * + * @param history The BrowserHistory instance that navigations should be dispatched to. + */ + activate(history: BrowserHistory): void; + /** + * Deactivate the instance. Event handlers and other resources should be cleaned up here. + */ + deactivate(): void; + /** + * Gets the href and a "should handle" recommendation, given an Event. + * + * @param event The Event to inspect for target anchor and href. + */ + static getEventInfo(event: Event): AnchorEventInfo; + /** + * Finds the closest ancestor that's an anchor element. + * + * @param el The element to search upward from. + * @returns The link element that is the closest ancestor. + */ + static findClosestAnchor(el: Element): Element; + /** + * Gets a value indicating whether or not an anchor targets the current window. + * + * @param target The anchor element whose target should be inspected. + * @returns True if the target of the link element is this window; false otherwise. + */ + static targetIsThisWindow(target: Element): boolean; } - /** * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container. * @param config The FrameworkConfiguration object provided by Aurelia. */ -export declare function configure(config: Object): void; - -/** - * An implementation of the basic history API. - */ -export declare class BrowserHistory extends History { - static inject: any; - - /** - * Creates an instance of BrowserHistory - * @param linkHandler An instance of LinkHandler. - */ - constructor(linkHandler: LinkHandler); - - /** - * Activates the history object. - * @param options The set of options to activate history with. - * @returns Whether or not activation occurred. - */ - activate(options?: Object): boolean; - - /** - * Deactivates the history object. - */ - deactivate(): void; - - /** - * Returns the fully-qualified root of the current history object. - * @returns The absolute root of the application. - */ - getAbsoluteRoot(): string; - - /** - * Causes a history navigation to occur. - * - * @param fragment The history fragment to navigate to. - * @param options The set of options that specify how the navigation should occur. - * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred. - */ - navigate(fragment?: string, { - trigger, - replace - }?: { - trigger?: any, - replace?: any - }): boolean; - - /** - * Causes the history state to navigate back. - */ - navigateBack(): void; - - /** - * Sets the document title. - */ - setTitle(title: string): void; - - /** - * Sets a key in the history page state. - * @param key The key for the value. - * @param value The value to set. - */ - setState(key: string, value: any): void; - - /** - * Gets a key in the history page state. - * @param key The key for the value. - * @return The value for the key. - */ - getState(key: string): any; - - /** - * Returns the current index in the navigation history. - * @returns The current index. - */ - getHistoryIndex(): number; - - /** - * Move to a specific position in the navigation history. - * @param movement The amount of steps, positive or negative, to move. - */ - go(movement: number): void; -} \ No newline at end of file +export declare function configure(config: Object): void; \ No newline at end of file diff --git a/dist/aurelia-history-browser.js b/dist/aurelia-history-browser.js deleted file mode 100644 index c124e74..0000000 --- a/dist/aurelia-history-browser.js +++ /dev/null @@ -1,437 +0,0 @@ -import {DOM,PLATFORM} from 'aurelia-pal'; -import {History} from 'aurelia-history'; - -/** - * Class responsible for handling interactions that should trigger browser history navigations. - */ -export class LinkHandler { - /** - * Activate the instance. - * - * @param history The BrowserHistory instance that navigations should be dispatched to. - */ - activate(history: BrowserHistory): void {} - - /** - * Deactivate the instance. Event handlers and other resources should be cleaned up here. - */ - deactivate(): void {} -} - -/** - * Provides information about how to handle an anchor event. - */ -interface AnchorEventInfo { - /** - * Indicates whether the event should be handled or not. - */ - shouldHandleEvent: boolean; - /** - * The href of the link or null if not-applicable. - */ - href: string; - /** - * The anchor element or null if not-applicable. - */ - anchor: Element; -} - -/** - * The default LinkHandler implementation. Navigations are triggered by click events on - * anchor elements with relative hrefs when the history instance is using pushstate. - */ -export class DefaultLinkHandler extends LinkHandler { - /** - * Creates an instance of DefaultLinkHandler. - */ - constructor() { - super(); - - this.handler = (e) => { - let {shouldHandleEvent, href} = DefaultLinkHandler.getEventInfo(e); - - if (shouldHandleEvent) { - e.preventDefault(); - this.history.navigate(href); - } - }; - } - - /** - * Activate the instance. - * - * @param history The BrowserHistory instance that navigations should be dispatched to. - */ - activate(history: BrowserHistory): void { - if (history._hasPushState) { - this.history = history; - DOM.addEventListener('click', this.handler, true); - } - } - - /** - * Deactivate the instance. Event handlers and other resources should be cleaned up here. - */ - deactivate(): void { - DOM.removeEventListener('click', this.handler); - } - - /** - * Gets the href and a "should handle" recommendation, given an Event. - * - * @param event The Event to inspect for target anchor and href. - */ - static getEventInfo(event: Event): AnchorEventInfo { - let info = { - shouldHandleEvent: false, - href: null, - anchor: null - }; - - let target = DefaultLinkHandler.findClosestAnchor(event.target); - if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { - return info; - } - - if (target.hasAttribute('download') || target.hasAttribute('router-ignore') || target.hasAttribute('data-router-ignore')) { - return info; - } - - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return info; - } - - let href = target.getAttribute('href'); - info.anchor = target; - info.href = href; - - let leftButtonClicked = event.which === 1; - let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); - - info.shouldHandleEvent = leftButtonClicked && isRelative; - return info; - } - - /** - * Finds the closest ancestor that's an anchor element. - * - * @param el The element to search upward from. - * @returns The link element that is the closest ancestor. - */ - static findClosestAnchor(el: Element): Element { - while (el) { - if (el.tagName === 'A') { - return el; - } - - el = el.parentNode; - } - } - - /** - * Gets a value indicating whether or not an anchor targets the current window. - * - * @param target The anchor element whose target should be inspected. - * @returns True if the target of the link element is this window; false otherwise. - */ - static targetIsThisWindow(target: Element): boolean { - let targetWindow = target.getAttribute('target'); - let win = PLATFORM.global; - - return !targetWindow || - targetWindow === win.name || - targetWindow === '_self'; - } -} - -/** - * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container. - * @param config The FrameworkConfiguration object provided by Aurelia. - */ -export function configure(config: Object): void { - config.singleton(History, BrowserHistory); - config.transient(LinkHandler, DefaultLinkHandler); -} - -/** - * An implementation of the basic history API. - */ -export class BrowserHistory extends History { - static inject = [LinkHandler]; - - /** - * Creates an instance of BrowserHistory - * @param linkHandler An instance of LinkHandler. - */ - constructor(linkHandler: LinkHandler) { - super(); - - this._isActive = false; - this._checkUrlCallback = this._checkUrl.bind(this); - - this.location = PLATFORM.location; - this.history = PLATFORM.history; - this.linkHandler = linkHandler; - } - - /** - * Activates the history object. - * @param options The set of options to activate history with. - * @returns Whether or not activation occurred. - */ - activate(options?: Object): boolean { - if (this._isActive) { - throw new Error('History has already been activated.'); - } - - let wantsPushState = !!options.pushState; - - this._isActive = true; - this.options = Object.assign({}, { root: '/' }, this.options, options); - - // Normalize root to always include a leading and trailing slash. - this.root = ('/' + this.options.root + '/').replace(rootStripper, '/'); - - this._wantsHashChange = this.options.hashChange !== false; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - - // Determine how we check the URL state. - let eventName; - if (this._hasPushState) { - eventName = 'popstate'; - } else if (this._wantsHashChange) { - eventName = 'hashchange'; - } - - PLATFORM.addEventListener(eventName, this._checkUrlCallback); - - // Determine if we need to change the base url, for a pushState link - // opened by a non-pushState browser. - if (this._wantsHashChange && wantsPushState) { - // Transition from hashChange to pushState or vice versa if both are requested. - let loc = this.location; - let atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; - - // If we've started off with a route from a `pushState`-enabled - // browser, but we're currently in a browser that doesn't support it... - if (!this._hasPushState && !atRoot) { - this.fragment = this._getFragment(null, true); - this.location.replace(this.root + this.location.search + '#' + this.fragment); - // Return immediately as browser will do redirect to new url - return true; - - // Or if we've started out with a hash-based route, but we're currently - // in a browser where it could be `pushState`-based instead... - } else if (this._hasPushState && atRoot && loc.hash) { - this.fragment = this._getHash().replace(routeStripper, ''); - this.history.replaceState({}, DOM.title, this.root + this.fragment + loc.search); - } - } - - if (!this.fragment) { - this.fragment = this._getFragment(); - } - - this.linkHandler.activate(this); - - if (!this.options.silent) { - return this._loadUrl(); - } - } - - /** - * Deactivates the history object. - */ - deactivate(): void { - PLATFORM.removeEventListener('popstate', this._checkUrlCallback); - PLATFORM.removeEventListener('hashchange', this._checkUrlCallback); - this._isActive = false; - this.linkHandler.deactivate(); - } - - /** - * Returns the fully-qualified root of the current history object. - * @returns The absolute root of the application. - */ - getAbsoluteRoot(): string { - let origin = createOrigin(this.location.protocol, this.location.hostname, this.location.port); - return `${origin}${this.root}`; - } - - /** - * Causes a history navigation to occur. - * - * @param fragment The history fragment to navigate to. - * @param options The set of options that specify how the navigation should occur. - * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred. - */ - navigate(fragment?: string, {trigger = true, replace = false} = {}): boolean { - if (fragment && absoluteUrl.test(fragment)) { - this.location.href = fragment; - return true; - } - - if (!this._isActive) { - return false; - } - - fragment = this._getFragment(fragment || ''); - - if (this.fragment === fragment && !replace) { - return false; - } - - this.fragment = fragment; - - let url = this.root + fragment; - - // Don't include a trailing slash on the root. - if (fragment === '' && url !== '/') { - url = url.slice(0, -1); - } - - // If pushState is available, we use it to set the fragment as a real URL. - if (this._hasPushState) { - url = url.replace('//', '/'); - this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); - } else if (this._wantsHashChange) { - // If hash changes haven't been explicitly disabled, update the hash - // fragment to store history. - updateHash(this.location, fragment, replace); - } else { - // If you've told us that you explicitly don't want fallback hashchange- - // based history, then `navigate` becomes a page refresh. - this.location.assign(url); - } - - if (trigger) { - return this._loadUrl(fragment); - } - - return true; - } - - /** - * Causes the history state to navigate back. - */ - navigateBack(): void { - this.history.back(); - } - - /** - * Sets the document title. - */ - setTitle(title: string): void { - DOM.title = title; - } - - /** - * Sets a key in the history page state. - * @param key The key for the value. - * @param value The value to set. - */ - setState(key: string, value: any): void { - let state = Object.assign({}, this.history.state); - let { pathname, search, hash } = this.location; - state[key] = value; - this.history.replaceState(state, null, `${pathname}${search}${hash}`); - } - - /** - * Gets a key in the history page state. - * @param key The key for the value. - * @return The value for the key. - */ - getState(key: string): any { - let state = Object.assign({}, this.history.state); - return state[key]; - } - - /** - * Returns the current index in the navigation history. - * @returns The current index. - */ - getHistoryIndex(): number { - let historyIndex = this.getState('HistoryIndex'); - if (historyIndex === undefined) { - historyIndex = this.history.length - 1; - this.setState('HistoryIndex', historyIndex); - } - return historyIndex; - } - - /** - * Move to a specific position in the navigation history. - * @param movement The amount of steps, positive or negative, to move. - */ - go(movement: number): void { - this.history.go(movement); - } - - _getHash(): string { - return this.location.hash.substr(1); - } - - _getFragment(fragment: string, forcePushState?: boolean): string { - let root; - - if (!fragment) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname + this.location.search; - root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) { - fragment = fragment.substr(root.length); - } - } else { - fragment = this._getHash(); - } - } - - return '/' + fragment.replace(routeStripper, ''); - } - - _checkUrl(): boolean { - let current = this._getFragment(); - if (current !== this.fragment) { - this._loadUrl(); - } - } - - _loadUrl(fragmentOverride: string): boolean { - let fragment = this.fragment = this._getFragment(fragmentOverride); - - return this.options.routeHandler ? - this.options.routeHandler(fragment) : - false; - } -} - -// Cached regex for stripping a leading hash/slash and trailing space. -const routeStripper = /^#?\/*|\s+$/g; - -// Cached regex for stripping leading and trailing slashes. -const rootStripper = /^\/+|\/+$/g; - -// Cached regex for removing a trailing slash. -const trailingSlash = /\/$/; - -// Cached regex for detecting if a URL is absolute, -// i.e., starts with a scheme or is scheme-relative. -// See http://www.ietf.org/rfc/rfc2396.txt section 3.1 for valid scheme format -const absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; - -// Update the hash location, either replacing the current entry, or adding -// a new one to the browser history. -function updateHash(location, fragment, replace) { - if (replace) { - let href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(href + '#' + fragment); - } else { - // Some browsers require that `hash` contains a leading #. - location.hash = '#' + fragment; - } -} - -function createOrigin(protocol: string, hostname: string, port: string) { - return `${protocol}//${hostname}${port ? ':' + port : ''}`; -} diff --git a/dist/commonjs/aurelia-history-browser.js b/dist/commonjs/aurelia-history-browser.js index 3d99ed8..7f8ef04 100644 --- a/dist/commonjs/aurelia-history-browser.js +++ b/dist/commonjs/aurelia-history-browser.js @@ -1,341 +1,299 @@ 'use strict'; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.BrowserHistory = exports.DefaultLinkHandler = exports.LinkHandler = undefined; - -var _class, _temp; - -exports.configure = configure; - -var _aureliaPal = require('aurelia-pal'); - -var _aureliaHistory = require('aurelia-history'); - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - - -var LinkHandler = exports.LinkHandler = function () { - function LinkHandler() { - - } - - LinkHandler.prototype.activate = function activate(history) {}; - - LinkHandler.prototype.deactivate = function deactivate() {}; - - return LinkHandler; -}(); - -var DefaultLinkHandler = exports.DefaultLinkHandler = function (_LinkHandler) { - _inherits(DefaultLinkHandler, _LinkHandler); - - function DefaultLinkHandler() { - - - var _this = _possibleConstructorReturn(this, _LinkHandler.call(this)); - - _this.handler = function (e) { - var _DefaultLinkHandler$g = DefaultLinkHandler.getEventInfo(e), - shouldHandleEvent = _DefaultLinkHandler$g.shouldHandleEvent, - href = _DefaultLinkHandler$g.href; - - if (shouldHandleEvent) { - e.preventDefault(); - _this.history.navigate(href); - } - }; - return _this; - } - - DefaultLinkHandler.prototype.activate = function activate(history) { - if (history._hasPushState) { - this.history = history; - _aureliaPal.DOM.addEventListener('click', this.handler, true); - } - }; - - DefaultLinkHandler.prototype.deactivate = function deactivate() { - _aureliaPal.DOM.removeEventListener('click', this.handler); - }; - - DefaultLinkHandler.getEventInfo = function getEventInfo(event) { - var info = { - shouldHandleEvent: false, - href: null, - anchor: null - }; - - var target = DefaultLinkHandler.findClosestAnchor(event.target); - if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { - return info; - } - - if (target.hasAttribute('download') || target.hasAttribute('router-ignore') || target.hasAttribute('data-router-ignore')) { - return info; - } - - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return info; - } - - var href = target.getAttribute('href'); - info.anchor = target; - info.href = href; - - var leftButtonClicked = event.which === 1; - var isRelative = href && !(href.charAt(0) === '#' || /^[a-z]+:/i.test(href)); - - info.shouldHandleEvent = leftButtonClicked && isRelative; - return info; - }; - - DefaultLinkHandler.findClosestAnchor = function findClosestAnchor(el) { - while (el) { - if (el.tagName === 'A') { - return el; - } - - el = el.parentNode; - } - }; - - DefaultLinkHandler.targetIsThisWindow = function targetIsThisWindow(target) { - var targetWindow = target.getAttribute('target'); - var win = _aureliaPal.PLATFORM.global; - - return !targetWindow || targetWindow === win.name || targetWindow === '_self'; - }; - - return DefaultLinkHandler; -}(LinkHandler); - -function configure(config) { - config.singleton(_aureliaHistory.History, BrowserHistory); - config.transient(LinkHandler, DefaultLinkHandler); +Object.defineProperty(exports, '__esModule', { value: true }); + +var aureliaHistory = require('aurelia-history'); +var aureliaPal = require('aurelia-pal'); + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } -var BrowserHistory = exports.BrowserHistory = (_temp = _class = function (_History) { - _inherits(BrowserHistory, _History); - - function BrowserHistory(linkHandler) { - - - var _this2 = _possibleConstructorReturn(this, _History.call(this)); - - _this2._isActive = false; - _this2._checkUrlCallback = _this2._checkUrl.bind(_this2); - - _this2.location = _aureliaPal.PLATFORM.location; - _this2.history = _aureliaPal.PLATFORM.history; - _this2.linkHandler = linkHandler; - return _this2; - } - - BrowserHistory.prototype.activate = function activate(options) { - if (this._isActive) { - throw new Error('History has already been activated.'); - } - - var wantsPushState = !!options.pushState; - - this._isActive = true; - this.options = Object.assign({}, { root: '/' }, this.options, options); - - this.root = ('/' + this.options.root + '/').replace(rootStripper, '/'); - - this._wantsHashChange = this.options.hashChange !== false; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - - var eventName = void 0; - if (this._hasPushState) { - eventName = 'popstate'; - } else if (this._wantsHashChange) { - eventName = 'hashchange'; - } - - _aureliaPal.PLATFORM.addEventListener(eventName, this._checkUrlCallback); - - if (this._wantsHashChange && wantsPushState) { - var loc = this.location; - var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; - - if (!this._hasPushState && !atRoot) { - this.fragment = this._getFragment(null, true); - this.location.replace(this.root + this.location.search + '#' + this.fragment); - - return true; - } else if (this._hasPushState && atRoot && loc.hash) { - this.fragment = this._getHash().replace(routeStripper, ''); - this.history.replaceState({}, _aureliaPal.DOM.title, this.root + this.fragment + loc.search); - } - } - - if (!this.fragment) { - this.fragment = this._getFragment(); - } - - this.linkHandler.activate(this); - - if (!this.options.silent) { - return this._loadUrl(); - } - }; - - BrowserHistory.prototype.deactivate = function deactivate() { - _aureliaPal.PLATFORM.removeEventListener('popstate', this._checkUrlCallback); - _aureliaPal.PLATFORM.removeEventListener('hashchange', this._checkUrlCallback); - this._isActive = false; - this.linkHandler.deactivate(); - }; - - BrowserHistory.prototype.getAbsoluteRoot = function getAbsoluteRoot() { - var origin = createOrigin(this.location.protocol, this.location.hostname, this.location.port); - return '' + origin + this.root; - }; - - BrowserHistory.prototype.navigate = function navigate(fragment) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$trigger = _ref.trigger, - trigger = _ref$trigger === undefined ? true : _ref$trigger, - _ref$replace = _ref.replace, - replace = _ref$replace === undefined ? false : _ref$replace; - - if (fragment && absoluteUrl.test(fragment)) { - this.location.href = fragment; - return true; - } - - if (!this._isActive) { - return false; - } - - fragment = this._getFragment(fragment || ''); - - if (this.fragment === fragment && !replace) { - return false; - } - - this.fragment = fragment; - - var url = this.root + fragment; - - if (fragment === '' && url !== '/') { - url = url.slice(0, -1); - } - - if (this._hasPushState) { - url = url.replace('//', '/'); - this.history[replace ? 'replaceState' : 'pushState']({}, _aureliaPal.DOM.title, url); - } else if (this._wantsHashChange) { - updateHash(this.location, fragment, replace); - } else { - this.location.assign(url); - } - - if (trigger) { - return this._loadUrl(fragment); - } - - return true; - }; - - BrowserHistory.prototype.navigateBack = function navigateBack() { - this.history.back(); - }; - - BrowserHistory.prototype.setTitle = function setTitle(title) { - _aureliaPal.DOM.title = title; - }; - - BrowserHistory.prototype.setState = function setState(key, value) { - var state = Object.assign({}, this.history.state); - var _location = this.location, - pathname = _location.pathname, - search = _location.search, - hash = _location.hash; - - state[key] = value; - this.history.replaceState(state, null, '' + pathname + search + hash); - }; - - BrowserHistory.prototype.getState = function getState(key) { - var state = Object.assign({}, this.history.state); - return state[key]; - }; - - BrowserHistory.prototype.getHistoryIndex = function getHistoryIndex() { - var historyIndex = this.getState('HistoryIndex'); - if (historyIndex === undefined) { - historyIndex = this.history.length - 1; - this.setState('HistoryIndex', historyIndex); - } - return historyIndex; - }; - - BrowserHistory.prototype.go = function go(movement) { - this.history.go(movement); - }; - - BrowserHistory.prototype._getHash = function _getHash() { - return this.location.hash.substr(1); - }; - - BrowserHistory.prototype._getFragment = function _getFragment(fragment, forcePushState) { - var root = void 0; - - if (!fragment) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname + this.location.search; - root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) { - fragment = fragment.substr(root.length); - } - } else { - fragment = this._getHash(); - } - } - - return '/' + fragment.replace(routeStripper, ''); - }; - - BrowserHistory.prototype._checkUrl = function _checkUrl() { - var current = this._getFragment(); - if (current !== this.fragment) { - this._loadUrl(); - } - }; - - BrowserHistory.prototype._loadUrl = function _loadUrl(fragmentOverride) { - var fragment = this.fragment = this._getFragment(fragmentOverride); - - return this.options.routeHandler ? this.options.routeHandler(fragment) : false; - }; - - return BrowserHistory; -}(_aureliaHistory.History), _class.inject = [LinkHandler], _temp); - -var routeStripper = /^#?\/*|\s+$/g; - -var rootStripper = /^\/+|\/+$/g; - -var trailingSlash = /\/$/; - -var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; +var LinkHandler = (function () { + function LinkHandler() { + } + LinkHandler.prototype.activate = function (history) { }; + LinkHandler.prototype.deactivate = function () { }; + return LinkHandler; +}()); +var DefaultLinkHandler = (function (_super) { + __extends(DefaultLinkHandler, _super); + function DefaultLinkHandler() { + var _this = _super.call(this) || this; + _this.handler = function (e) { + var _a = DefaultLinkHandler.getEventInfo(e), shouldHandleEvent = _a.shouldHandleEvent, href = _a.href; + if (shouldHandleEvent) { + e.preventDefault(); + _this.history.navigate(href); + } + }; + return _this; + } + DefaultLinkHandler.prototype.activate = function (history) { + if (history._hasPushState) { + this.history = history; + aureliaPal.DOM.addEventListener('click', this.handler, true); + } + }; + DefaultLinkHandler.prototype.deactivate = function () { + aureliaPal.DOM.removeEventListener('click', this.handler, true); + }; + DefaultLinkHandler.getEventInfo = function (event) { + var $event = event; + var info = { + shouldHandleEvent: false, + href: null, + anchor: null + }; + var target = DefaultLinkHandler.findClosestAnchor($event.target); + if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { + return info; + } + if (hasAttribute(target, 'download') + || hasAttribute(target, 'router-ignore') + || hasAttribute(target, 'data-router-ignore')) { + return info; + } + if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) { + return info; + } + var href = target.getAttribute('href'); + info.anchor = target; + info.href = href; + var leftButtonClicked = $event.which === 1; + var isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); + info.shouldHandleEvent = leftButtonClicked && isRelative; + return info; + }; + DefaultLinkHandler.findClosestAnchor = function (el) { + while (el) { + if (el.tagName === 'A') { + return el; + } + el = el.parentNode; + } + }; + DefaultLinkHandler.targetIsThisWindow = function (target) { + var targetWindow = target.getAttribute('target'); + var win = aureliaPal.PLATFORM.global; + return !targetWindow || + targetWindow === win.name || + targetWindow === '_self'; + }; + return DefaultLinkHandler; +}(LinkHandler)); +var hasAttribute = function (el, attr) { return el.hasAttribute(attr); }; + +var BrowserHistory = (function (_super) { + __extends(BrowserHistory, _super); + function BrowserHistory(linkHandler) { + var _this = _super.call(this) || this; + _this._isActive = false; + _this._checkUrlCallback = _this._checkUrl.bind(_this); + _this.location = aureliaPal.PLATFORM.location; + _this.history = aureliaPal.PLATFORM.history; + _this.linkHandler = linkHandler; + return _this; + } + BrowserHistory.prototype.activate = function (options) { + if (this._isActive) { + throw new Error('History has already been activated.'); + } + var $history = this.history; + var wantsPushState = !!options.pushState; + this._isActive = true; + var normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options); + var rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/'); + var wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false; + var hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState); + var eventName; + if (hasPushState) { + eventName = 'popstate'; + } + else if (wantsHashChange) { + eventName = 'hashchange'; + } + aureliaPal.PLATFORM.addEventListener(eventName, this._checkUrlCallback); + if (wantsHashChange && wantsPushState) { + var $location = this.location; + var atRoot = $location.pathname.replace(/[^\/]$/, '$&/') === rootUrl; + if (!hasPushState && !atRoot) { + var fragment = this.fragment = this._getFragment(null, true); + $location.replace(rootUrl + $location.search + '#' + fragment); + return true; + } + else if (hasPushState && atRoot && $location.hash) { + var fragment = this.fragment = this._getHash().replace(routeStripper, ''); + $history.replaceState({}, aureliaPal.DOM.title, rootUrl + fragment + $location.search); + } + } + if (!this.fragment) { + this.fragment = this._getFragment(''); + } + this.linkHandler.activate(this); + if (!normalizedOptions.silent) { + return this._loadUrl(''); + } + }; + BrowserHistory.prototype.deactivate = function () { + var handler = this._checkUrlCallback; + aureliaPal.PLATFORM.removeEventListener('popstate', handler); + aureliaPal.PLATFORM.removeEventListener('hashchange', handler); + this._isActive = false; + this.linkHandler.deactivate(); + }; + BrowserHistory.prototype.getAbsoluteRoot = function () { + var $location = this.location; + var origin = createOrigin($location.protocol, $location.hostname, $location.port); + return "" + origin + this.root; + }; + BrowserHistory.prototype.navigate = function (fragment, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b.trigger, trigger = _c === void 0 ? true : _c, _d = _b.replace, replace = _d === void 0 ? false : _d; + var location = this.location; + if (fragment && absoluteUrl.test(fragment)) { + location.href = fragment; + return true; + } + if (!this._isActive) { + return false; + } + fragment = this._getFragment(fragment || ''); + if (this.fragment === fragment && !replace) { + return false; + } + this.fragment = fragment; + var url = this.root + fragment; + if (fragment === '' && url !== '/') { + url = url.slice(0, -1); + } + if (this._hasPushState) { + url = url.replace('//', '/'); + this.history[replace ? 'replaceState' : 'pushState']({}, aureliaPal.DOM.title, url); + } + else if (this._wantsHashChange) { + updateHash(location, fragment, replace); + } + else { + location.assign(url); + } + if (trigger) { + return this._loadUrl(fragment); + } + return true; + }; + BrowserHistory.prototype.navigateBack = function () { + this.history.back(); + }; + BrowserHistory.prototype.setTitle = function (title) { + aureliaPal.DOM.title = title; + }; + BrowserHistory.prototype.setState = function (key, value) { + var $history = this.history; + var state = Object.assign({}, $history.state); + var _a = this.location, pathname = _a.pathname, search = _a.search, hash = _a.hash; + state[key] = value; + $history.replaceState(state, null, "" + pathname + search + hash); + }; + BrowserHistory.prototype.getState = function (key) { + var state = Object.assign({}, this.history.state); + return state[key]; + }; + BrowserHistory.prototype.getHistoryIndex = function () { + var historyIndex = this.getState('HistoryIndex'); + if (historyIndex === undefined) { + historyIndex = this.history.length - 1; + this.setState('HistoryIndex', historyIndex); + } + return historyIndex; + }; + BrowserHistory.prototype.go = function (movement) { + this.history.go(movement); + }; + BrowserHistory.prototype._getHash = function () { + return this.location.hash.substr(1); + }; + BrowserHistory.prototype._getFragment = function (fragment, forcePushState) { + var rootUrl; + if (!fragment) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + var location_1 = this.location; + fragment = location_1.pathname + location_1.search; + rootUrl = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(rootUrl)) { + fragment = fragment.substr(rootUrl.length); + } + } + else { + fragment = this._getHash(); + } + } + return '/' + fragment.replace(routeStripper, ''); + }; + BrowserHistory.prototype._checkUrl = function () { + var current = this._getFragment(''); + if (current !== this.fragment) { + this._loadUrl(''); + } + }; + BrowserHistory.prototype._loadUrl = function (fragmentOverride) { + var fragment = this.fragment = this._getFragment(fragmentOverride); + return this.options.routeHandler ? + this.options.routeHandler(fragment) : + false; + }; + BrowserHistory.inject = [LinkHandler]; + return BrowserHistory; +}(aureliaHistory.History)); +var routeStripper = /^#?\/*|\s+$/g; +var rootStripper = /^\/+|\/+$/g; +var trailingSlash = /\/$/; +var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; +function updateHash($location, fragment, replace) { + if (replace) { + var href = $location.href.replace(/(javascript:|#).*$/, ''); + $location.replace(href + '#' + fragment); + } + else { + $location.hash = '#' + fragment; + } +} +function createOrigin(protocol, hostname, port) { + return protocol + "//" + hostname + (port ? ':' + port : ''); +} -function updateHash(location, fragment, replace) { - if (replace) { - var _href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(_href + '#' + fragment); - } else { - location.hash = '#' + fragment; - } +function configure(config) { + var $config = config; + $config.singleton(aureliaHistory.History, BrowserHistory); + $config.transient(LinkHandler, DefaultLinkHandler); } -function createOrigin(protocol, hostname, port) { - return protocol + '//' + hostname + (port ? ':' + port : ''); -} \ No newline at end of file +exports.BrowserHistory = BrowserHistory; +exports.DefaultLinkHandler = DefaultLinkHandler; +exports.LinkHandler = LinkHandler; +exports.configure = configure; +//# sourceMappingURL=aurelia-history-browser.js.map diff --git a/dist/commonjs/aurelia-history-browser.js.map b/dist/commonjs/aurelia-history-browser.js.map new file mode 100644 index 0000000..830cf0d --- /dev/null +++ b/dist/commonjs/aurelia-history-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"aurelia-history-browser.js","sources":["../../src/link-handler.ts","../../src/browser-history.ts","../../src/aurelia-history-browser.ts"],"sourcesContent":["import { DOM, PLATFORM } from 'aurelia-pal';\nimport { BrowserHistory } from './browser-history';\nimport { AnchorEventInfo } from './interfaces';\n\n/**\n * Class responsible for handling interactions that should trigger browser history navigations.\n */\nexport class LinkHandler {\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {/**/}\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {/**/}\n}\n\n/**\n * The default LinkHandler implementation. Navigations are triggered by click events on\n * anchor elements with relative hrefs when the history instance is using pushstate.\n */\nexport class DefaultLinkHandler extends LinkHandler {\n\n /**@internal */\n handler: (e: Event) => void;\n\n /**@internal */\n history: BrowserHistory;\n /**\n * Creates an instance of DefaultLinkHandler.\n */\n constructor() {\n super();\n\n this.handler = (e) => {\n let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e);\n\n if (shouldHandleEvent) {\n e.preventDefault();\n this.history.navigate(href);\n }\n };\n }\n\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {\n if (history._hasPushState) {\n this.history = history;\n DOM.addEventListener('click', this.handler, true);\n }\n }\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {\n DOM.removeEventListener('click', this.handler, true);\n }\n\n /**\n * Gets the href and a \"should handle\" recommendation, given an Event.\n *\n * @param event The Event to inspect for target anchor and href.\n */\n static getEventInfo(event: Event): AnchorEventInfo {\n let $event = event as MouseEvent;\n let info = {\n shouldHandleEvent: false,\n href: null,\n anchor: null\n };\n\n let target = DefaultLinkHandler.findClosestAnchor($event.target as Element);\n if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) {\n return info;\n }\n\n if (hasAttribute(target, 'download')\n || hasAttribute(target, 'router-ignore')\n || hasAttribute(target, 'data-router-ignore')\n ) {\n return info;\n }\n\n if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) {\n return info;\n }\n\n let href = target.getAttribute('href');\n info.anchor = target;\n info.href = href;\n\n let leftButtonClicked = $event.which === 1;\n let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href));\n\n info.shouldHandleEvent = leftButtonClicked && isRelative;\n return info;\n }\n\n /**\n * Finds the closest ancestor that's an anchor element.\n *\n * @param el The element to search upward from.\n * @returns The link element that is the closest ancestor.\n */\n static findClosestAnchor(el: Element): Element {\n while (el) {\n if (el.tagName === 'A') {\n return el;\n }\n\n el = el.parentNode as Element;\n }\n }\n\n /**\n * Gets a value indicating whether or not an anchor targets the current window.\n *\n * @param target The anchor element whose target should be inspected.\n * @returns True if the target of the link element is this window; false otherwise.\n */\n static targetIsThisWindow(target: Element): boolean {\n let targetWindow = target.getAttribute('target');\n let win = PLATFORM.global;\n\n return !targetWindow ||\n targetWindow === win.name ||\n targetWindow === '_self';\n }\n}\n\nconst hasAttribute = (el: Element, attr: string) => el.hasAttribute(attr);\n","import { DOM, PLATFORM } from 'aurelia-pal';\nimport { LinkHandler } from './link-handler';\nimport { History } from 'aurelia-history';\n\n/**\n * An implementation of the basic history API.\n */\nexport class BrowserHistory extends History {\n /**@internal */\n static inject = [LinkHandler];\n\n /**@internal */\n _isActive: boolean;\n\n /**@internal*/\n _checkUrlCallback: any;\n /**@internal*/\n location: Location;\n /**@internal*/\n history: typeof PLATFORM['history'];\n /**@internal*/\n linkHandler: LinkHandler;\n /**@internal*/\n options: any;\n /**@internal*/\n root: string;\n /**@internal*/\n _wantsHashChange: boolean;\n /**@internal*/\n _hasPushState: boolean;\n /**@internal*/\n fragment: string;\n\n /**\n * Creates an instance of BrowserHistory\n * @param linkHandler An instance of LinkHandler.\n */\n constructor(linkHandler: LinkHandler) {\n super();\n\n this._isActive = false;\n this._checkUrlCallback = this._checkUrl.bind(this);\n\n this.location = PLATFORM.location;\n this.history = PLATFORM.history;\n this.linkHandler = linkHandler;\n }\n\n /**\n * Activates the history object.\n * @param options The set of options to activate history with.\n * @returns Whether or not activation occurred.\n */\n activate(options?: Object): boolean {\n if (this._isActive) {\n throw new Error('History has already been activated.');\n }\n\n let $history = this.history;\n let wantsPushState = !!(options as any).pushState;\n\n this._isActive = true;\n let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options);\n\n // Normalize root to always include a leading and trailing slash.\n let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/');\n\n let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false;\n let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState);\n\n // Determine how we check the URL state.\n let eventName: string;\n if (hasPushState) {\n eventName = 'popstate';\n } else if (wantsHashChange) {\n eventName = 'hashchange';\n }\n\n PLATFORM.addEventListener(eventName, this._checkUrlCallback);\n\n // Determine if we need to change the base url, for a pushState link\n // opened by a non-pushState browser.\n if (wantsHashChange && wantsPushState) {\n // Transition from hashChange to pushState or vice versa if both are requested.\n let $location = this.location;\n let atRoot = $location.pathname.replace(/[^\\/]$/, '$&/') === rootUrl;\n\n // If we've started off with a route from a `pushState`-enabled\n // browser, but we're currently in a browser that doesn't support it...\n if (!hasPushState && !atRoot) {\n let fragment = this.fragment = this._getFragment(null, true);\n $location.replace(rootUrl + $location.search + '#' + fragment);\n // Return immediately as browser will do redirect to new url\n return true;\n\n // Or if we've started out with a hash-based route, but we're currently\n // in a browser where it could be `pushState`-based instead...\n } else if (hasPushState && atRoot && $location.hash) {\n let fragment = this.fragment = this._getHash().replace(routeStripper, '');\n $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search);\n }\n }\n\n if (!this.fragment) {\n this.fragment = this._getFragment('');\n }\n\n this.linkHandler.activate(this);\n\n if (!normalizedOptions.silent) {\n return this._loadUrl('');\n }\n }\n\n /**\n * Deactivates the history object.\n */\n deactivate(): void {\n const handler = this._checkUrlCallback;\n PLATFORM.removeEventListener('popstate', handler);\n PLATFORM.removeEventListener('hashchange', handler);\n this._isActive = false;\n this.linkHandler.deactivate();\n }\n\n /**\n * Returns the fully-qualified root of the current history object.\n * @returns The absolute root of the application.\n */\n getAbsoluteRoot(): string {\n let $location = this.location;\n let origin = createOrigin($location.protocol, $location.hostname, $location.port);\n return `${origin}${this.root}`;\n }\n\n /**\n * Causes a history navigation to occur.\n *\n * @param fragment The history fragment to navigate to.\n * @param options The set of options that specify how the navigation should occur.\n * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred.\n */\n navigate(fragment?: string, {trigger = true, replace = false} = {}): boolean {\n let location = this.location;\n if (fragment && absoluteUrl.test(fragment)) {\n location.href = fragment;\n return true;\n }\n\n if (!this._isActive) {\n return false;\n }\n\n fragment = this._getFragment(fragment || '');\n\n if (this.fragment === fragment && !replace) {\n return false;\n }\n\n this.fragment = fragment;\n\n let url = this.root + fragment;\n\n // Don't include a trailing slash on the root.\n if (fragment === '' && url !== '/') {\n url = url.slice(0, -1);\n }\n\n // If pushState is available, we use it to set the fragment as a real URL.\n if (this._hasPushState) {\n url = url.replace('//', '/');\n this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url);\n } else if (this._wantsHashChange) {\n // If hash changes haven't been explicitly disabled, update the hash\n // fragment to store history.\n updateHash(location, fragment, replace);\n } else {\n // If you've told us that you explicitly don't want fallback hashchange-\n // based history, then `navigate` becomes a page refresh.\n location.assign(url);\n }\n\n if (trigger) {\n return this._loadUrl(fragment);\n }\n\n return true;\n }\n\n /**\n * Causes the history state to navigate back.\n */\n navigateBack(): void {\n this.history.back();\n }\n\n /**\n * Sets the document title.\n */\n setTitle(title: string): void {\n DOM.title = title;\n }\n\n /**\n * Sets a key in the history page state.\n * @param key The key for the value.\n * @param value The value to set.\n */\n setState(key: string, value: any): void {\n let $history = this.history;\n let state = Object.assign({}, $history.state);\n let { pathname, search, hash } = this.location;\n state[key] = value;\n $history.replaceState(state, null, `${pathname}${search}${hash}`);\n }\n\n /**\n * Gets a key in the history page state.\n * @param key The key for the value.\n * @return The value for the key.\n */\n getState(key: string): any {\n let state = Object.assign({}, this.history.state);\n return state[key];\n }\n\n /**\n * Returns the current index in the navigation history.\n * @returns The current index.\n */\n getHistoryIndex(): number {\n let historyIndex = this.getState('HistoryIndex');\n if (historyIndex === undefined) {\n historyIndex = this.history.length - 1;\n this.setState('HistoryIndex', historyIndex);\n }\n return historyIndex;\n }\n\n /**\n * Move to a specific position in the navigation history.\n * @param movement The amount of steps, positive or negative, to move.\n */\n go(movement: number): void {\n this.history.go(movement);\n }\n\n /**\n * @internal\n */\n _getHash(): string {\n return this.location.hash.substr(1);\n }\n\n /**\n * @internal\n */\n _getFragment(fragment: string, forcePushState?: boolean): string {\n let rootUrl: string;\n\n if (!fragment) {\n if (this._hasPushState || !this._wantsHashChange || forcePushState) {\n let location = this.location;\n fragment = location.pathname + location.search;\n rootUrl = this.root.replace(trailingSlash, '');\n if (!fragment.indexOf(rootUrl)) {\n fragment = fragment.substr(rootUrl.length);\n }\n } else {\n fragment = this._getHash();\n }\n }\n\n return '/' + fragment.replace(routeStripper, '');\n }\n\n /**\n * Url change handler.\n * Invoked when current fragment is different with previous fragment\n * @internal\n */\n _checkUrl(): void {\n let current = this._getFragment('');\n if (current !== this.fragment) {\n this._loadUrl('');\n }\n }\n\n /**\n * invoke routeHandler\n * @internal\n */\n _loadUrl(fragmentOverride: string): boolean {\n let fragment = this.fragment = this._getFragment(fragmentOverride);\n\n return this.options.routeHandler ?\n this.options.routeHandler(fragment) :\n false;\n }\n}\n\n// Cached regex for stripping a leading hash/slash and trailing space.\nconst routeStripper = /^#?\\/*|\\s+$/g;\n\n// Cached regex for stripping leading and trailing slashes.\nconst rootStripper = /^\\/+|\\/+$/g;\n\n// Cached regex for removing a trailing slash.\nconst trailingSlash = /\\/$/;\n\n// Cached regex for detecting if a URL is absolute,\n// i.e., starts with a scheme or is scheme-relative.\n// See http://www.ietf.org/rfc/rfc2396.txt section 3.1 for valid scheme format\nconst absoluteUrl = /^([a-z][a-z0-9+\\-.]*:)?\\/\\//i;\n\n// Update the hash location, either replacing the current entry, or adding\n// a new one to the browser history.\nfunction updateHash($location: Location, fragment: string, replace: boolean) {\n if (replace) {\n let href = $location.href.replace(/(javascript:|#).*$/, '');\n $location.replace(href + '#' + fragment);\n } else {\n // Some browsers require that `hash` contains a leading #.\n $location.hash = '#' + fragment;\n }\n}\n\nfunction createOrigin(protocol: string, hostname: string, port: string) {\n return `${protocol}//${hostname}${port ? ':' + port : ''}`;\n}\n","import {History} from 'aurelia-history';\nimport {LinkHandler, DefaultLinkHandler} from './link-handler';\nimport { BrowserHistory } from './browser-history';\n\n/**\n * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container.\n * @param config The FrameworkConfiguration object provided by Aurelia.\n */\nexport function configure(config: Object): void {\n // work around for converting to TS without breaking compat\n const $config = config as any;\n $config.singleton(History, BrowserHistory);\n $config.transient(LinkHandler, DefaultLinkHandler);\n}\n\nexport {\n LinkHandler,\n DefaultLinkHandler,\n BrowserHistory\n};\n"],"names":["tslib_1.__extends","DOM","PLATFORM","History"],"mappings":"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"} \ No newline at end of file diff --git a/dist/commonjs/index.js b/dist/commonjs/index.js deleted file mode 100644 index 0d89940..0000000 --- a/dist/commonjs/index.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _aureliaHistoryBrowser = require('./aurelia-history-browser'); - -Object.keys(_aureliaHistoryBrowser).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function get() { - return _aureliaHistoryBrowser[key]; - } - }); -}); \ No newline at end of file diff --git a/dist/es2015/aurelia-history-browser.js b/dist/es2015/aurelia-history-browser.js index ea84d75..f5b42f4 100644 --- a/dist/es2015/aurelia-history-browser.js +++ b/dist/es2015/aurelia-history-browser.js @@ -1,293 +1,253 @@ -var _class, _temp; - -import { DOM, PLATFORM } from 'aurelia-pal'; import { History } from 'aurelia-history'; +import { DOM, PLATFORM } from 'aurelia-pal'; -export let LinkHandler = class LinkHandler { - activate(history) {} - - deactivate() {} -}; - -export let DefaultLinkHandler = class DefaultLinkHandler extends LinkHandler { - constructor() { - super(); - - this.handler = e => { - let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e); - - if (shouldHandleEvent) { - e.preventDefault(); - this.history.navigate(href); - } - }; - } - - activate(history) { - if (history._hasPushState) { - this.history = history; - DOM.addEventListener('click', this.handler, true); - } - } - - deactivate() { - DOM.removeEventListener('click', this.handler); - } - - static getEventInfo(event) { - let info = { - shouldHandleEvent: false, - href: null, - anchor: null - }; - - let target = DefaultLinkHandler.findClosestAnchor(event.target); - if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { - return info; - } - - if (target.hasAttribute('download') || target.hasAttribute('router-ignore') || target.hasAttribute('data-router-ignore')) { - return info; - } - - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return info; - } - - let href = target.getAttribute('href'); - info.anchor = target; - info.href = href; - - let leftButtonClicked = event.which === 1; - let isRelative = href && !(href.charAt(0) === '#' || /^[a-z]+:/i.test(href)); - - info.shouldHandleEvent = leftButtonClicked && isRelative; - return info; - } - - static findClosestAnchor(el) { - while (el) { - if (el.tagName === 'A') { - return el; - } - - el = el.parentNode; - } - } - - static targetIsThisWindow(target) { - let targetWindow = target.getAttribute('target'); - let win = PLATFORM.global; - - return !targetWindow || targetWindow === win.name || targetWindow === '_self'; - } -}; - -export function configure(config) { - config.singleton(History, BrowserHistory); - config.transient(LinkHandler, DefaultLinkHandler); +class LinkHandler { + activate(history) { } + deactivate() { } +} +class DefaultLinkHandler extends LinkHandler { + constructor() { + super(); + this.handler = (e) => { + let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e); + if (shouldHandleEvent) { + e.preventDefault(); + this.history.navigate(href); + } + }; + } + activate(history) { + if (history._hasPushState) { + this.history = history; + DOM.addEventListener('click', this.handler, true); + } + } + deactivate() { + DOM.removeEventListener('click', this.handler, true); + } + static getEventInfo(event) { + let $event = event; + let info = { + shouldHandleEvent: false, + href: null, + anchor: null + }; + let target = DefaultLinkHandler.findClosestAnchor($event.target); + if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { + return info; + } + if (hasAttribute(target, 'download') + || hasAttribute(target, 'router-ignore') + || hasAttribute(target, 'data-router-ignore')) { + return info; + } + if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) { + return info; + } + let href = target.getAttribute('href'); + info.anchor = target; + info.href = href; + let leftButtonClicked = $event.which === 1; + let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); + info.shouldHandleEvent = leftButtonClicked && isRelative; + return info; + } + static findClosestAnchor(el) { + while (el) { + if (el.tagName === 'A') { + return el; + } + el = el.parentNode; + } + } + static targetIsThisWindow(target) { + let targetWindow = target.getAttribute('target'); + let win = PLATFORM.global; + return !targetWindow || + targetWindow === win.name || + targetWindow === '_self'; + } +} +const hasAttribute = (el, attr) => el.hasAttribute(attr); + +class BrowserHistory extends History { + constructor(linkHandler) { + super(); + this._isActive = false; + this._checkUrlCallback = this._checkUrl.bind(this); + this.location = PLATFORM.location; + this.history = PLATFORM.history; + this.linkHandler = linkHandler; + } + activate(options) { + if (this._isActive) { + throw new Error('History has already been activated.'); + } + let $history = this.history; + let wantsPushState = !!options.pushState; + this._isActive = true; + let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options); + let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/'); + let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false; + let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState); + let eventName; + if (hasPushState) { + eventName = 'popstate'; + } + else if (wantsHashChange) { + eventName = 'hashchange'; + } + PLATFORM.addEventListener(eventName, this._checkUrlCallback); + if (wantsHashChange && wantsPushState) { + let $location = this.location; + let atRoot = $location.pathname.replace(/[^\/]$/, '$&/') === rootUrl; + if (!hasPushState && !atRoot) { + let fragment = this.fragment = this._getFragment(null, true); + $location.replace(rootUrl + $location.search + '#' + fragment); + return true; + } + else if (hasPushState && atRoot && $location.hash) { + let fragment = this.fragment = this._getHash().replace(routeStripper, ''); + $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search); + } + } + if (!this.fragment) { + this.fragment = this._getFragment(''); + } + this.linkHandler.activate(this); + if (!normalizedOptions.silent) { + return this._loadUrl(''); + } + } + deactivate() { + const handler = this._checkUrlCallback; + PLATFORM.removeEventListener('popstate', handler); + PLATFORM.removeEventListener('hashchange', handler); + this._isActive = false; + this.linkHandler.deactivate(); + } + getAbsoluteRoot() { + let $location = this.location; + let origin = createOrigin($location.protocol, $location.hostname, $location.port); + return `${origin}${this.root}`; + } + navigate(fragment, { trigger = true, replace = false } = {}) { + let location = this.location; + if (fragment && absoluteUrl.test(fragment)) { + location.href = fragment; + return true; + } + if (!this._isActive) { + return false; + } + fragment = this._getFragment(fragment || ''); + if (this.fragment === fragment && !replace) { + return false; + } + this.fragment = fragment; + let url = this.root + fragment; + if (fragment === '' && url !== '/') { + url = url.slice(0, -1); + } + if (this._hasPushState) { + url = url.replace('//', '/'); + this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); + } + else if (this._wantsHashChange) { + updateHash(location, fragment, replace); + } + else { + location.assign(url); + } + if (trigger) { + return this._loadUrl(fragment); + } + return true; + } + navigateBack() { + this.history.back(); + } + setTitle(title) { + DOM.title = title; + } + setState(key, value) { + let $history = this.history; + let state = Object.assign({}, $history.state); + let { pathname, search, hash } = this.location; + state[key] = value; + $history.replaceState(state, null, `${pathname}${search}${hash}`); + } + getState(key) { + let state = Object.assign({}, this.history.state); + return state[key]; + } + getHistoryIndex() { + let historyIndex = this.getState('HistoryIndex'); + if (historyIndex === undefined) { + historyIndex = this.history.length - 1; + this.setState('HistoryIndex', historyIndex); + } + return historyIndex; + } + go(movement) { + this.history.go(movement); + } + _getHash() { + return this.location.hash.substr(1); + } + _getFragment(fragment, forcePushState) { + let rootUrl; + if (!fragment) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + let location = this.location; + fragment = location.pathname + location.search; + rootUrl = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(rootUrl)) { + fragment = fragment.substr(rootUrl.length); + } + } + else { + fragment = this._getHash(); + } + } + return '/' + fragment.replace(routeStripper, ''); + } + _checkUrl() { + let current = this._getFragment(''); + if (current !== this.fragment) { + this._loadUrl(''); + } + } + _loadUrl(fragmentOverride) { + let fragment = this.fragment = this._getFragment(fragmentOverride); + return this.options.routeHandler ? + this.options.routeHandler(fragment) : + false; + } +} +BrowserHistory.inject = [LinkHandler]; +const routeStripper = /^#?\/*|\s+$/g; +const rootStripper = /^\/+|\/+$/g; +const trailingSlash = /\/$/; +const absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; +function updateHash($location, fragment, replace) { + if (replace) { + let href = $location.href.replace(/(javascript:|#).*$/, ''); + $location.replace(href + '#' + fragment); + } + else { + $location.hash = '#' + fragment; + } +} +function createOrigin(protocol, hostname, port) { + return `${protocol}//${hostname}${port ? ':' + port : ''}`; } -export let BrowserHistory = (_temp = _class = class BrowserHistory extends History { - constructor(linkHandler) { - super(); - - this._isActive = false; - this._checkUrlCallback = this._checkUrl.bind(this); - - this.location = PLATFORM.location; - this.history = PLATFORM.history; - this.linkHandler = linkHandler; - } - - activate(options) { - if (this._isActive) { - throw new Error('History has already been activated.'); - } - - let wantsPushState = !!options.pushState; - - this._isActive = true; - this.options = Object.assign({}, { root: '/' }, this.options, options); - - this.root = ('/' + this.options.root + '/').replace(rootStripper, '/'); - - this._wantsHashChange = this.options.hashChange !== false; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - - let eventName; - if (this._hasPushState) { - eventName = 'popstate'; - } else if (this._wantsHashChange) { - eventName = 'hashchange'; - } - - PLATFORM.addEventListener(eventName, this._checkUrlCallback); - - if (this._wantsHashChange && wantsPushState) { - let loc = this.location; - let atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; - - if (!this._hasPushState && !atRoot) { - this.fragment = this._getFragment(null, true); - this.location.replace(this.root + this.location.search + '#' + this.fragment); - - return true; - } else if (this._hasPushState && atRoot && loc.hash) { - this.fragment = this._getHash().replace(routeStripper, ''); - this.history.replaceState({}, DOM.title, this.root + this.fragment + loc.search); - } - } - - if (!this.fragment) { - this.fragment = this._getFragment(); - } - - this.linkHandler.activate(this); - - if (!this.options.silent) { - return this._loadUrl(); - } - } - - deactivate() { - PLATFORM.removeEventListener('popstate', this._checkUrlCallback); - PLATFORM.removeEventListener('hashchange', this._checkUrlCallback); - this._isActive = false; - this.linkHandler.deactivate(); - } - - getAbsoluteRoot() { - let origin = createOrigin(this.location.protocol, this.location.hostname, this.location.port); - return `${origin}${this.root}`; - } - - navigate(fragment, { trigger = true, replace = false } = {}) { - if (fragment && absoluteUrl.test(fragment)) { - this.location.href = fragment; - return true; - } - - if (!this._isActive) { - return false; - } - - fragment = this._getFragment(fragment || ''); - - if (this.fragment === fragment && !replace) { - return false; - } - - this.fragment = fragment; - - let url = this.root + fragment; - - if (fragment === '' && url !== '/') { - url = url.slice(0, -1); - } - - if (this._hasPushState) { - url = url.replace('//', '/'); - this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); - } else if (this._wantsHashChange) { - updateHash(this.location, fragment, replace); - } else { - this.location.assign(url); - } - - if (trigger) { - return this._loadUrl(fragment); - } - - return true; - } - - navigateBack() { - this.history.back(); - } - - setTitle(title) { - DOM.title = title; - } - - setState(key, value) { - let state = Object.assign({}, this.history.state); - let { pathname, search, hash } = this.location; - state[key] = value; - this.history.replaceState(state, null, `${pathname}${search}${hash}`); - } - - getState(key) { - let state = Object.assign({}, this.history.state); - return state[key]; - } - - getHistoryIndex() { - let historyIndex = this.getState('HistoryIndex'); - if (historyIndex === undefined) { - historyIndex = this.history.length - 1; - this.setState('HistoryIndex', historyIndex); - } - return historyIndex; - } - - go(movement) { - this.history.go(movement); - } - - _getHash() { - return this.location.hash.substr(1); - } - - _getFragment(fragment, forcePushState) { - let root; - - if (!fragment) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname + this.location.search; - root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) { - fragment = fragment.substr(root.length); - } - } else { - fragment = this._getHash(); - } - } - - return '/' + fragment.replace(routeStripper, ''); - } - - _checkUrl() { - let current = this._getFragment(); - if (current !== this.fragment) { - this._loadUrl(); - } - } - - _loadUrl(fragmentOverride) { - let fragment = this.fragment = this._getFragment(fragmentOverride); - - return this.options.routeHandler ? this.options.routeHandler(fragment) : false; - } -}, _class.inject = [LinkHandler], _temp); - -const routeStripper = /^#?\/*|\s+$/g; - -const rootStripper = /^\/+|\/+$/g; - -const trailingSlash = /\/$/; - -const absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; - -function updateHash(location, fragment, replace) { - if (replace) { - let href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(href + '#' + fragment); - } else { - location.hash = '#' + fragment; - } +function configure(config) { + const $config = config; + $config.singleton(History, BrowserHistory); + $config.transient(LinkHandler, DefaultLinkHandler); } -function createOrigin(protocol, hostname, port) { - return `${protocol}//${hostname}${port ? ':' + port : ''}`; -} \ No newline at end of file +export { BrowserHistory, DefaultLinkHandler, LinkHandler, configure }; +//# sourceMappingURL=aurelia-history-browser.js.map diff --git a/dist/es2015/aurelia-history-browser.js.map b/dist/es2015/aurelia-history-browser.js.map new file mode 100644 index 0000000..070e484 --- /dev/null +++ b/dist/es2015/aurelia-history-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"aurelia-history-browser.js","sources":["../../src/link-handler.ts","../../src/browser-history.ts","../../src/aurelia-history-browser.ts"],"sourcesContent":["import { DOM, PLATFORM } from 'aurelia-pal';\nimport { BrowserHistory } from './browser-history';\nimport { AnchorEventInfo } from './interfaces';\n\n/**\n * Class responsible for handling interactions that should trigger browser history navigations.\n */\nexport class LinkHandler {\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {/**/}\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {/**/}\n}\n\n/**\n * The default LinkHandler implementation. Navigations are triggered by click events on\n * anchor elements with relative hrefs when the history instance is using pushstate.\n */\nexport class DefaultLinkHandler extends LinkHandler {\n\n /**@internal */\n handler: (e: Event) => void;\n\n /**@internal */\n history: BrowserHistory;\n /**\n * Creates an instance of DefaultLinkHandler.\n */\n constructor() {\n super();\n\n this.handler = (e) => {\n let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e);\n\n if (shouldHandleEvent) {\n e.preventDefault();\n this.history.navigate(href);\n }\n };\n }\n\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {\n if (history._hasPushState) {\n this.history = history;\n DOM.addEventListener('click', this.handler, true);\n }\n }\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {\n DOM.removeEventListener('click', this.handler, true);\n }\n\n /**\n * Gets the href and a \"should handle\" recommendation, given an Event.\n *\n * @param event The Event to inspect for target anchor and href.\n */\n static getEventInfo(event: Event): AnchorEventInfo {\n let $event = event as MouseEvent;\n let info = {\n shouldHandleEvent: false,\n href: null,\n anchor: null\n };\n\n let target = DefaultLinkHandler.findClosestAnchor($event.target as Element);\n if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) {\n return info;\n }\n\n if (hasAttribute(target, 'download')\n || hasAttribute(target, 'router-ignore')\n || hasAttribute(target, 'data-router-ignore')\n ) {\n return info;\n }\n\n if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) {\n return info;\n }\n\n let href = target.getAttribute('href');\n info.anchor = target;\n info.href = href;\n\n let leftButtonClicked = $event.which === 1;\n let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href));\n\n info.shouldHandleEvent = leftButtonClicked && isRelative;\n return info;\n }\n\n /**\n * Finds the closest ancestor that's an anchor element.\n *\n * @param el The element to search upward from.\n * @returns The link element that is the closest ancestor.\n */\n static findClosestAnchor(el: Element): Element {\n while (el) {\n if (el.tagName === 'A') {\n return el;\n }\n\n el = el.parentNode as Element;\n }\n }\n\n /**\n * Gets a value indicating whether or not an anchor targets the current window.\n *\n * @param target The anchor element whose target should be inspected.\n * @returns True if the target of the link element is this window; false otherwise.\n */\n static targetIsThisWindow(target: Element): boolean {\n let targetWindow = target.getAttribute('target');\n let win = PLATFORM.global;\n\n return !targetWindow ||\n targetWindow === win.name ||\n targetWindow === '_self';\n }\n}\n\nconst hasAttribute = (el: Element, attr: string) => el.hasAttribute(attr);\n","import { DOM, PLATFORM } from 'aurelia-pal';\nimport { LinkHandler } from './link-handler';\nimport { History } from 'aurelia-history';\n\n/**\n * An implementation of the basic history API.\n */\nexport class BrowserHistory extends History {\n /**@internal */\n static inject = [LinkHandler];\n\n /**@internal */\n _isActive: boolean;\n\n /**@internal*/\n _checkUrlCallback: any;\n /**@internal*/\n location: Location;\n /**@internal*/\n history: typeof PLATFORM['history'];\n /**@internal*/\n linkHandler: LinkHandler;\n /**@internal*/\n options: any;\n /**@internal*/\n root: string;\n /**@internal*/\n _wantsHashChange: boolean;\n /**@internal*/\n _hasPushState: boolean;\n /**@internal*/\n fragment: string;\n\n /**\n * Creates an instance of BrowserHistory\n * @param linkHandler An instance of LinkHandler.\n */\n constructor(linkHandler: LinkHandler) {\n super();\n\n this._isActive = false;\n this._checkUrlCallback = this._checkUrl.bind(this);\n\n this.location = PLATFORM.location;\n this.history = PLATFORM.history;\n this.linkHandler = linkHandler;\n }\n\n /**\n * Activates the history object.\n * @param options The set of options to activate history with.\n * @returns Whether or not activation occurred.\n */\n activate(options?: Object): boolean {\n if (this._isActive) {\n throw new Error('History has already been activated.');\n }\n\n let $history = this.history;\n let wantsPushState = !!(options as any).pushState;\n\n this._isActive = true;\n let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options);\n\n // Normalize root to always include a leading and trailing slash.\n let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/');\n\n let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false;\n let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState);\n\n // Determine how we check the URL state.\n let eventName: string;\n if (hasPushState) {\n eventName = 'popstate';\n } else if (wantsHashChange) {\n eventName = 'hashchange';\n }\n\n PLATFORM.addEventListener(eventName, this._checkUrlCallback);\n\n // Determine if we need to change the base url, for a pushState link\n // opened by a non-pushState browser.\n if (wantsHashChange && wantsPushState) {\n // Transition from hashChange to pushState or vice versa if both are requested.\n let $location = this.location;\n let atRoot = $location.pathname.replace(/[^\\/]$/, '$&/') === rootUrl;\n\n // If we've started off with a route from a `pushState`-enabled\n // browser, but we're currently in a browser that doesn't support it...\n if (!hasPushState && !atRoot) {\n let fragment = this.fragment = this._getFragment(null, true);\n $location.replace(rootUrl + $location.search + '#' + fragment);\n // Return immediately as browser will do redirect to new url\n return true;\n\n // Or if we've started out with a hash-based route, but we're currently\n // in a browser where it could be `pushState`-based instead...\n } else if (hasPushState && atRoot && $location.hash) {\n let fragment = this.fragment = this._getHash().replace(routeStripper, '');\n $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search);\n }\n }\n\n if (!this.fragment) {\n this.fragment = this._getFragment('');\n }\n\n this.linkHandler.activate(this);\n\n if (!normalizedOptions.silent) {\n return this._loadUrl('');\n }\n }\n\n /**\n * Deactivates the history object.\n */\n deactivate(): void {\n const handler = this._checkUrlCallback;\n PLATFORM.removeEventListener('popstate', handler);\n PLATFORM.removeEventListener('hashchange', handler);\n this._isActive = false;\n this.linkHandler.deactivate();\n }\n\n /**\n * Returns the fully-qualified root of the current history object.\n * @returns The absolute root of the application.\n */\n getAbsoluteRoot(): string {\n let $location = this.location;\n let origin = createOrigin($location.protocol, $location.hostname, $location.port);\n return `${origin}${this.root}`;\n }\n\n /**\n * Causes a history navigation to occur.\n *\n * @param fragment The history fragment to navigate to.\n * @param options The set of options that specify how the navigation should occur.\n * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred.\n */\n navigate(fragment?: string, {trigger = true, replace = false} = {}): boolean {\n let location = this.location;\n if (fragment && absoluteUrl.test(fragment)) {\n location.href = fragment;\n return true;\n }\n\n if (!this._isActive) {\n return false;\n }\n\n fragment = this._getFragment(fragment || '');\n\n if (this.fragment === fragment && !replace) {\n return false;\n }\n\n this.fragment = fragment;\n\n let url = this.root + fragment;\n\n // Don't include a trailing slash on the root.\n if (fragment === '' && url !== '/') {\n url = url.slice(0, -1);\n }\n\n // If pushState is available, we use it to set the fragment as a real URL.\n if (this._hasPushState) {\n url = url.replace('//', '/');\n this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url);\n } else if (this._wantsHashChange) {\n // If hash changes haven't been explicitly disabled, update the hash\n // fragment to store history.\n updateHash(location, fragment, replace);\n } else {\n // If you've told us that you explicitly don't want fallback hashchange-\n // based history, then `navigate` becomes a page refresh.\n location.assign(url);\n }\n\n if (trigger) {\n return this._loadUrl(fragment);\n }\n\n return true;\n }\n\n /**\n * Causes the history state to navigate back.\n */\n navigateBack(): void {\n this.history.back();\n }\n\n /**\n * Sets the document title.\n */\n setTitle(title: string): void {\n DOM.title = title;\n }\n\n /**\n * Sets a key in the history page state.\n * @param key The key for the value.\n * @param value The value to set.\n */\n setState(key: string, value: any): void {\n let $history = this.history;\n let state = Object.assign({}, $history.state);\n let { pathname, search, hash } = this.location;\n state[key] = value;\n $history.replaceState(state, null, `${pathname}${search}${hash}`);\n }\n\n /**\n * Gets a key in the history page state.\n * @param key The key for the value.\n * @return The value for the key.\n */\n getState(key: string): any {\n let state = Object.assign({}, this.history.state);\n return state[key];\n }\n\n /**\n * Returns the current index in the navigation history.\n * @returns The current index.\n */\n getHistoryIndex(): number {\n let historyIndex = this.getState('HistoryIndex');\n if (historyIndex === undefined) {\n historyIndex = this.history.length - 1;\n this.setState('HistoryIndex', historyIndex);\n }\n return historyIndex;\n }\n\n /**\n * Move to a specific position in the navigation history.\n * @param movement The amount of steps, positive or negative, to move.\n */\n go(movement: number): void {\n this.history.go(movement);\n }\n\n /**\n * @internal\n */\n _getHash(): string {\n return this.location.hash.substr(1);\n }\n\n /**\n * @internal\n */\n _getFragment(fragment: string, forcePushState?: boolean): string {\n let rootUrl: string;\n\n if (!fragment) {\n if (this._hasPushState || !this._wantsHashChange || forcePushState) {\n let location = this.location;\n fragment = location.pathname + location.search;\n rootUrl = this.root.replace(trailingSlash, '');\n if (!fragment.indexOf(rootUrl)) {\n fragment = fragment.substr(rootUrl.length);\n }\n } else {\n fragment = this._getHash();\n }\n }\n\n return '/' + fragment.replace(routeStripper, '');\n }\n\n /**\n * Url change handler.\n * Invoked when current fragment is different with previous fragment\n * @internal\n */\n _checkUrl(): void {\n let current = this._getFragment('');\n if (current !== this.fragment) {\n this._loadUrl('');\n }\n }\n\n /**\n * invoke routeHandler\n * @internal\n */\n _loadUrl(fragmentOverride: string): boolean {\n let fragment = this.fragment = this._getFragment(fragmentOverride);\n\n return this.options.routeHandler ?\n this.options.routeHandler(fragment) :\n false;\n }\n}\n\n// Cached regex for stripping a leading hash/slash and trailing space.\nconst routeStripper = /^#?\\/*|\\s+$/g;\n\n// Cached regex for stripping leading and trailing slashes.\nconst rootStripper = /^\\/+|\\/+$/g;\n\n// Cached regex for removing a trailing slash.\nconst trailingSlash = /\\/$/;\n\n// Cached regex for detecting if a URL is absolute,\n// i.e., starts with a scheme or is scheme-relative.\n// See http://www.ietf.org/rfc/rfc2396.txt section 3.1 for valid scheme format\nconst absoluteUrl = /^([a-z][a-z0-9+\\-.]*:)?\\/\\//i;\n\n// Update the hash location, either replacing the current entry, or adding\n// a new one to the browser history.\nfunction updateHash($location: Location, fragment: string, replace: boolean) {\n if (replace) {\n let href = $location.href.replace(/(javascript:|#).*$/, '');\n $location.replace(href + '#' + fragment);\n } else {\n // Some browsers require that `hash` contains a leading #.\n $location.hash = '#' + fragment;\n }\n}\n\nfunction createOrigin(protocol: string, hostname: string, port: string) {\n return `${protocol}//${hostname}${port ? ':' + port : ''}`;\n}\n","import {History} from 'aurelia-history';\nimport {LinkHandler, DefaultLinkHandler} from './link-handler';\nimport { BrowserHistory } from './browser-history';\n\n/**\n * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container.\n * @param config The FrameworkConfiguration object provided by Aurelia.\n */\nexport function configure(config: Object): void {\n // work around for converting to TS without breaking compat\n const $config = config as any;\n $config.singleton(History, BrowserHistory);\n $config.transient(LinkHandler, DefaultLinkHandler);\n}\n\nexport {\n LinkHandler,\n DefaultLinkHandler,\n BrowserHistory\n};\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/es2015/index.js b/dist/es2015/index.js deleted file mode 100644 index 4c74765..0000000 --- a/dist/es2015/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './aurelia-history-browser'; \ No newline at end of file diff --git a/dist/es2017/aurelia-history-browser.js b/dist/es2017/aurelia-history-browser.js new file mode 100644 index 0000000..9e51e5b --- /dev/null +++ b/dist/es2017/aurelia-history-browser.js @@ -0,0 +1,252 @@ +import { History } from 'aurelia-history'; +import { DOM, PLATFORM } from 'aurelia-pal'; + +class LinkHandler { + activate(history) { } + deactivate() { } +} +class DefaultLinkHandler extends LinkHandler { + constructor() { + super(); + this.handler = (e) => { + let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e); + if (shouldHandleEvent) { + e.preventDefault(); + this.history.navigate(href); + } + }; + } + activate(history) { + if (history._hasPushState) { + this.history = history; + DOM.addEventListener('click', this.handler, true); + } + } + deactivate() { + DOM.removeEventListener('click', this.handler, true); + } + static getEventInfo(event) { + let $event = event; + let info = { + shouldHandleEvent: false, + href: null, + anchor: null + }; + let target = DefaultLinkHandler.findClosestAnchor($event.target); + if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { + return info; + } + if (hasAttribute(target, 'download') + || hasAttribute(target, 'router-ignore') + || hasAttribute(target, 'data-router-ignore')) { + return info; + } + if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) { + return info; + } + let href = target.getAttribute('href'); + info.anchor = target; + info.href = href; + let leftButtonClicked = $event.which === 1; + let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); + info.shouldHandleEvent = leftButtonClicked && isRelative; + return info; + } + static findClosestAnchor(el) { + while (el) { + if (el.tagName === 'A') { + return el; + } + el = el.parentNode; + } + } + static targetIsThisWindow(target) { + let targetWindow = target.getAttribute('target'); + let win = PLATFORM.global; + return !targetWindow || + targetWindow === win.name || + targetWindow === '_self'; + } +} +const hasAttribute = (el, attr) => el.hasAttribute(attr); + +class BrowserHistory extends History { + constructor(linkHandler) { + super(); + this._isActive = false; + this._checkUrlCallback = this._checkUrl.bind(this); + this.location = PLATFORM.location; + this.history = PLATFORM.history; + this.linkHandler = linkHandler; + } + activate(options) { + if (this._isActive) { + throw new Error('History has already been activated.'); + } + let $history = this.history; + let wantsPushState = !!options.pushState; + this._isActive = true; + let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options); + let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/'); + let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false; + let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState); + let eventName; + if (hasPushState) { + eventName = 'popstate'; + } + else if (wantsHashChange) { + eventName = 'hashchange'; + } + PLATFORM.addEventListener(eventName, this._checkUrlCallback); + if (wantsHashChange && wantsPushState) { + let $location = this.location; + let atRoot = $location.pathname.replace(/[^\/]$/, '$&/') === rootUrl; + if (!hasPushState && !atRoot) { + let fragment = this.fragment = this._getFragment(null, true); + $location.replace(rootUrl + $location.search + '#' + fragment); + return true; + } + else if (hasPushState && atRoot && $location.hash) { + let fragment = this.fragment = this._getHash().replace(routeStripper, ''); + $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search); + } + } + if (!this.fragment) { + this.fragment = this._getFragment(''); + } + this.linkHandler.activate(this); + if (!normalizedOptions.silent) { + return this._loadUrl(''); + } + } + deactivate() { + const handler = this._checkUrlCallback; + PLATFORM.removeEventListener('popstate', handler); + PLATFORM.removeEventListener('hashchange', handler); + this._isActive = false; + this.linkHandler.deactivate(); + } + getAbsoluteRoot() { + let $location = this.location; + let origin = createOrigin($location.protocol, $location.hostname, $location.port); + return `${origin}${this.root}`; + } + navigate(fragment, { trigger = true, replace = false } = {}) { + let location = this.location; + if (fragment && absoluteUrl.test(fragment)) { + location.href = fragment; + return true; + } + if (!this._isActive) { + return false; + } + fragment = this._getFragment(fragment || ''); + if (this.fragment === fragment && !replace) { + return false; + } + this.fragment = fragment; + let url = this.root + fragment; + if (fragment === '' && url !== '/') { + url = url.slice(0, -1); + } + if (this._hasPushState) { + url = url.replace('//', '/'); + this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); + } + else if (this._wantsHashChange) { + updateHash(location, fragment, replace); + } + else { + location.assign(url); + } + if (trigger) { + return this._loadUrl(fragment); + } + return true; + } + navigateBack() { + this.history.back(); + } + setTitle(title) { + DOM.title = title; + } + setState(key, value) { + let $history = this.history; + let state = Object.assign({}, $history.state); + let { pathname, search, hash } = this.location; + state[key] = value; + $history.replaceState(state, null, `${pathname}${search}${hash}`); + } + getState(key) { + let state = Object.assign({}, this.history.state); + return state[key]; + } + getHistoryIndex() { + let historyIndex = this.getState('HistoryIndex'); + if (historyIndex === undefined) { + historyIndex = this.history.length - 1; + this.setState('HistoryIndex', historyIndex); + } + return historyIndex; + } + go(movement) { + this.history.go(movement); + } + _getHash() { + return this.location.hash.substr(1); + } + _getFragment(fragment, forcePushState) { + let rootUrl; + if (!fragment) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + let location = this.location; + fragment = location.pathname + location.search; + rootUrl = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(rootUrl)) { + fragment = fragment.substr(rootUrl.length); + } + } + else { + fragment = this._getHash(); + } + } + return '/' + fragment.replace(routeStripper, ''); + } + _checkUrl() { + let current = this._getFragment(''); + if (current !== this.fragment) { + this._loadUrl(''); + } + } + _loadUrl(fragmentOverride) { + let fragment = this.fragment = this._getFragment(fragmentOverride); + return this.options.routeHandler ? + this.options.routeHandler(fragment) : + false; + } +} +BrowserHistory.inject = [LinkHandler]; +const routeStripper = /^#?\/*|\s+$/g; +const rootStripper = /^\/+|\/+$/g; +const trailingSlash = /\/$/; +const absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; +function updateHash($location, fragment, replace) { + if (replace) { + let href = $location.href.replace(/(javascript:|#).*$/, ''); + $location.replace(href + '#' + fragment); + } + else { + $location.hash = '#' + fragment; + } +} +function createOrigin(protocol, hostname, port) { + return `${protocol}//${hostname}${port ? ':' + port : ''}`; +} + +function configure(config) { + const $config = config; + $config.singleton(History, BrowserHistory); + $config.transient(LinkHandler, DefaultLinkHandler); +} + +export { BrowserHistory, DefaultLinkHandler, LinkHandler, configure }; diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index 4e4b3fd..0000000 --- a/dist/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from 'aurelia-history-browser/aurelia-history-browser'; \ No newline at end of file diff --git a/dist/native-modules/aurelia-history-browser.js b/dist/native-modules/aurelia-history-browser.js index 9c557bc..000aeb5 100644 --- a/dist/native-modules/aurelia-history-browser.js +++ b/dist/native-modules/aurelia-history-browser.js @@ -1,331 +1,292 @@ -var _class, _temp; - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - - -import { DOM, PLATFORM } from 'aurelia-pal'; import { History } from 'aurelia-history'; +import { DOM, PLATFORM } from 'aurelia-pal'; -export var LinkHandler = function () { - function LinkHandler() { - - } - - LinkHandler.prototype.activate = function activate(history) {}; - - LinkHandler.prototype.deactivate = function deactivate() {}; - - return LinkHandler; -}(); - -export var DefaultLinkHandler = function (_LinkHandler) { - _inherits(DefaultLinkHandler, _LinkHandler); - - function DefaultLinkHandler() { - - - var _this = _possibleConstructorReturn(this, _LinkHandler.call(this)); - - _this.handler = function (e) { - var _DefaultLinkHandler$g = DefaultLinkHandler.getEventInfo(e), - shouldHandleEvent = _DefaultLinkHandler$g.shouldHandleEvent, - href = _DefaultLinkHandler$g.href; - - if (shouldHandleEvent) { - e.preventDefault(); - _this.history.navigate(href); - } - }; - return _this; - } - - DefaultLinkHandler.prototype.activate = function activate(history) { - if (history._hasPushState) { - this.history = history; - DOM.addEventListener('click', this.handler, true); - } - }; - - DefaultLinkHandler.prototype.deactivate = function deactivate() { - DOM.removeEventListener('click', this.handler); - }; - - DefaultLinkHandler.getEventInfo = function getEventInfo(event) { - var info = { - shouldHandleEvent: false, - href: null, - anchor: null - }; - - var target = DefaultLinkHandler.findClosestAnchor(event.target); - if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { - return info; - } - - if (target.hasAttribute('download') || target.hasAttribute('router-ignore') || target.hasAttribute('data-router-ignore')) { - return info; - } - - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return info; - } - - var href = target.getAttribute('href'); - info.anchor = target; - info.href = href; - - var leftButtonClicked = event.which === 1; - var isRelative = href && !(href.charAt(0) === '#' || /^[a-z]+:/i.test(href)); - - info.shouldHandleEvent = leftButtonClicked && isRelative; - return info; - }; - - DefaultLinkHandler.findClosestAnchor = function findClosestAnchor(el) { - while (el) { - if (el.tagName === 'A') { - return el; - } - - el = el.parentNode; - } - }; - - DefaultLinkHandler.targetIsThisWindow = function targetIsThisWindow(target) { - var targetWindow = target.getAttribute('target'); - var win = PLATFORM.global; - - return !targetWindow || targetWindow === win.name || targetWindow === '_self'; - }; - - return DefaultLinkHandler; -}(LinkHandler); - -export function configure(config) { - config.singleton(History, BrowserHistory); - config.transient(LinkHandler, DefaultLinkHandler); +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } -export var BrowserHistory = (_temp = _class = function (_History) { - _inherits(BrowserHistory, _History); - - function BrowserHistory(linkHandler) { - - - var _this2 = _possibleConstructorReturn(this, _History.call(this)); - - _this2._isActive = false; - _this2._checkUrlCallback = _this2._checkUrl.bind(_this2); - - _this2.location = PLATFORM.location; - _this2.history = PLATFORM.history; - _this2.linkHandler = linkHandler; - return _this2; - } - - BrowserHistory.prototype.activate = function activate(options) { - if (this._isActive) { - throw new Error('History has already been activated.'); - } - - var wantsPushState = !!options.pushState; - - this._isActive = true; - this.options = Object.assign({}, { root: '/' }, this.options, options); - - this.root = ('/' + this.options.root + '/').replace(rootStripper, '/'); - - this._wantsHashChange = this.options.hashChange !== false; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - - var eventName = void 0; - if (this._hasPushState) { - eventName = 'popstate'; - } else if (this._wantsHashChange) { - eventName = 'hashchange'; - } - - PLATFORM.addEventListener(eventName, this._checkUrlCallback); - - if (this._wantsHashChange && wantsPushState) { - var loc = this.location; - var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; - - if (!this._hasPushState && !atRoot) { - this.fragment = this._getFragment(null, true); - this.location.replace(this.root + this.location.search + '#' + this.fragment); - - return true; - } else if (this._hasPushState && atRoot && loc.hash) { - this.fragment = this._getHash().replace(routeStripper, ''); - this.history.replaceState({}, DOM.title, this.root + this.fragment + loc.search); - } - } - - if (!this.fragment) { - this.fragment = this._getFragment(); - } - - this.linkHandler.activate(this); - - if (!this.options.silent) { - return this._loadUrl(); - } - }; - - BrowserHistory.prototype.deactivate = function deactivate() { - PLATFORM.removeEventListener('popstate', this._checkUrlCallback); - PLATFORM.removeEventListener('hashchange', this._checkUrlCallback); - this._isActive = false; - this.linkHandler.deactivate(); - }; - - BrowserHistory.prototype.getAbsoluteRoot = function getAbsoluteRoot() { - var origin = createOrigin(this.location.protocol, this.location.hostname, this.location.port); - return '' + origin + this.root; - }; - - BrowserHistory.prototype.navigate = function navigate(fragment) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$trigger = _ref.trigger, - trigger = _ref$trigger === undefined ? true : _ref$trigger, - _ref$replace = _ref.replace, - replace = _ref$replace === undefined ? false : _ref$replace; - - if (fragment && absoluteUrl.test(fragment)) { - this.location.href = fragment; - return true; - } - - if (!this._isActive) { - return false; - } - - fragment = this._getFragment(fragment || ''); - - if (this.fragment === fragment && !replace) { - return false; - } - - this.fragment = fragment; - - var url = this.root + fragment; - - if (fragment === '' && url !== '/') { - url = url.slice(0, -1); - } - - if (this._hasPushState) { - url = url.replace('//', '/'); - this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); - } else if (this._wantsHashChange) { - updateHash(this.location, fragment, replace); - } else { - this.location.assign(url); - } - - if (trigger) { - return this._loadUrl(fragment); - } - - return true; - }; - - BrowserHistory.prototype.navigateBack = function navigateBack() { - this.history.back(); - }; - - BrowserHistory.prototype.setTitle = function setTitle(title) { - DOM.title = title; - }; - - BrowserHistory.prototype.setState = function setState(key, value) { - var state = Object.assign({}, this.history.state); - var _location = this.location, - pathname = _location.pathname, - search = _location.search, - hash = _location.hash; - - state[key] = value; - this.history.replaceState(state, null, '' + pathname + search + hash); - }; - - BrowserHistory.prototype.getState = function getState(key) { - var state = Object.assign({}, this.history.state); - return state[key]; - }; - - BrowserHistory.prototype.getHistoryIndex = function getHistoryIndex() { - var historyIndex = this.getState('HistoryIndex'); - if (historyIndex === undefined) { - historyIndex = this.history.length - 1; - this.setState('HistoryIndex', historyIndex); - } - return historyIndex; - }; - - BrowserHistory.prototype.go = function go(movement) { - this.history.go(movement); - }; - - BrowserHistory.prototype._getHash = function _getHash() { - return this.location.hash.substr(1); - }; - - BrowserHistory.prototype._getFragment = function _getFragment(fragment, forcePushState) { - var root = void 0; - - if (!fragment) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname + this.location.search; - root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) { - fragment = fragment.substr(root.length); - } - } else { - fragment = this._getHash(); - } - } - - return '/' + fragment.replace(routeStripper, ''); - }; - - BrowserHistory.prototype._checkUrl = function _checkUrl() { - var current = this._getFragment(); - if (current !== this.fragment) { - this._loadUrl(); - } - }; - - BrowserHistory.prototype._loadUrl = function _loadUrl(fragmentOverride) { - var fragment = this.fragment = this._getFragment(fragmentOverride); - - return this.options.routeHandler ? this.options.routeHandler(fragment) : false; - }; - - return BrowserHistory; -}(History), _class.inject = [LinkHandler], _temp); - -var routeStripper = /^#?\/*|\s+$/g; - -var rootStripper = /^\/+|\/+$/g; - -var trailingSlash = /\/$/; - -var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; +var LinkHandler = (function () { + function LinkHandler() { + } + LinkHandler.prototype.activate = function (history) { }; + LinkHandler.prototype.deactivate = function () { }; + return LinkHandler; +}()); +var DefaultLinkHandler = (function (_super) { + __extends(DefaultLinkHandler, _super); + function DefaultLinkHandler() { + var _this = _super.call(this) || this; + _this.handler = function (e) { + var _a = DefaultLinkHandler.getEventInfo(e), shouldHandleEvent = _a.shouldHandleEvent, href = _a.href; + if (shouldHandleEvent) { + e.preventDefault(); + _this.history.navigate(href); + } + }; + return _this; + } + DefaultLinkHandler.prototype.activate = function (history) { + if (history._hasPushState) { + this.history = history; + DOM.addEventListener('click', this.handler, true); + } + }; + DefaultLinkHandler.prototype.deactivate = function () { + DOM.removeEventListener('click', this.handler, true); + }; + DefaultLinkHandler.getEventInfo = function (event) { + var $event = event; + var info = { + shouldHandleEvent: false, + href: null, + anchor: null + }; + var target = DefaultLinkHandler.findClosestAnchor($event.target); + if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { + return info; + } + if (hasAttribute(target, 'download') + || hasAttribute(target, 'router-ignore') + || hasAttribute(target, 'data-router-ignore')) { + return info; + } + if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) { + return info; + } + var href = target.getAttribute('href'); + info.anchor = target; + info.href = href; + var leftButtonClicked = $event.which === 1; + var isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); + info.shouldHandleEvent = leftButtonClicked && isRelative; + return info; + }; + DefaultLinkHandler.findClosestAnchor = function (el) { + while (el) { + if (el.tagName === 'A') { + return el; + } + el = el.parentNode; + } + }; + DefaultLinkHandler.targetIsThisWindow = function (target) { + var targetWindow = target.getAttribute('target'); + var win = PLATFORM.global; + return !targetWindow || + targetWindow === win.name || + targetWindow === '_self'; + }; + return DefaultLinkHandler; +}(LinkHandler)); +var hasAttribute = function (el, attr) { return el.hasAttribute(attr); }; + +var BrowserHistory = (function (_super) { + __extends(BrowserHistory, _super); + function BrowserHistory(linkHandler) { + var _this = _super.call(this) || this; + _this._isActive = false; + _this._checkUrlCallback = _this._checkUrl.bind(_this); + _this.location = PLATFORM.location; + _this.history = PLATFORM.history; + _this.linkHandler = linkHandler; + return _this; + } + BrowserHistory.prototype.activate = function (options) { + if (this._isActive) { + throw new Error('History has already been activated.'); + } + var $history = this.history; + var wantsPushState = !!options.pushState; + this._isActive = true; + var normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options); + var rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/'); + var wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false; + var hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState); + var eventName; + if (hasPushState) { + eventName = 'popstate'; + } + else if (wantsHashChange) { + eventName = 'hashchange'; + } + PLATFORM.addEventListener(eventName, this._checkUrlCallback); + if (wantsHashChange && wantsPushState) { + var $location = this.location; + var atRoot = $location.pathname.replace(/[^\/]$/, '$&/') === rootUrl; + if (!hasPushState && !atRoot) { + var fragment = this.fragment = this._getFragment(null, true); + $location.replace(rootUrl + $location.search + '#' + fragment); + return true; + } + else if (hasPushState && atRoot && $location.hash) { + var fragment = this.fragment = this._getHash().replace(routeStripper, ''); + $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search); + } + } + if (!this.fragment) { + this.fragment = this._getFragment(''); + } + this.linkHandler.activate(this); + if (!normalizedOptions.silent) { + return this._loadUrl(''); + } + }; + BrowserHistory.prototype.deactivate = function () { + var handler = this._checkUrlCallback; + PLATFORM.removeEventListener('popstate', handler); + PLATFORM.removeEventListener('hashchange', handler); + this._isActive = false; + this.linkHandler.deactivate(); + }; + BrowserHistory.prototype.getAbsoluteRoot = function () { + var $location = this.location; + var origin = createOrigin($location.protocol, $location.hostname, $location.port); + return "" + origin + this.root; + }; + BrowserHistory.prototype.navigate = function (fragment, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b.trigger, trigger = _c === void 0 ? true : _c, _d = _b.replace, replace = _d === void 0 ? false : _d; + var location = this.location; + if (fragment && absoluteUrl.test(fragment)) { + location.href = fragment; + return true; + } + if (!this._isActive) { + return false; + } + fragment = this._getFragment(fragment || ''); + if (this.fragment === fragment && !replace) { + return false; + } + this.fragment = fragment; + var url = this.root + fragment; + if (fragment === '' && url !== '/') { + url = url.slice(0, -1); + } + if (this._hasPushState) { + url = url.replace('//', '/'); + this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); + } + else if (this._wantsHashChange) { + updateHash(location, fragment, replace); + } + else { + location.assign(url); + } + if (trigger) { + return this._loadUrl(fragment); + } + return true; + }; + BrowserHistory.prototype.navigateBack = function () { + this.history.back(); + }; + BrowserHistory.prototype.setTitle = function (title) { + DOM.title = title; + }; + BrowserHistory.prototype.setState = function (key, value) { + var $history = this.history; + var state = Object.assign({}, $history.state); + var _a = this.location, pathname = _a.pathname, search = _a.search, hash = _a.hash; + state[key] = value; + $history.replaceState(state, null, "" + pathname + search + hash); + }; + BrowserHistory.prototype.getState = function (key) { + var state = Object.assign({}, this.history.state); + return state[key]; + }; + BrowserHistory.prototype.getHistoryIndex = function () { + var historyIndex = this.getState('HistoryIndex'); + if (historyIndex === undefined) { + historyIndex = this.history.length - 1; + this.setState('HistoryIndex', historyIndex); + } + return historyIndex; + }; + BrowserHistory.prototype.go = function (movement) { + this.history.go(movement); + }; + BrowserHistory.prototype._getHash = function () { + return this.location.hash.substr(1); + }; + BrowserHistory.prototype._getFragment = function (fragment, forcePushState) { + var rootUrl; + if (!fragment) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + var location_1 = this.location; + fragment = location_1.pathname + location_1.search; + rootUrl = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(rootUrl)) { + fragment = fragment.substr(rootUrl.length); + } + } + else { + fragment = this._getHash(); + } + } + return '/' + fragment.replace(routeStripper, ''); + }; + BrowserHistory.prototype._checkUrl = function () { + var current = this._getFragment(''); + if (current !== this.fragment) { + this._loadUrl(''); + } + }; + BrowserHistory.prototype._loadUrl = function (fragmentOverride) { + var fragment = this.fragment = this._getFragment(fragmentOverride); + return this.options.routeHandler ? + this.options.routeHandler(fragment) : + false; + }; + BrowserHistory.inject = [LinkHandler]; + return BrowserHistory; +}(History)); +var routeStripper = /^#?\/*|\s+$/g; +var rootStripper = /^\/+|\/+$/g; +var trailingSlash = /\/$/; +var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; +function updateHash($location, fragment, replace) { + if (replace) { + var href = $location.href.replace(/(javascript:|#).*$/, ''); + $location.replace(href + '#' + fragment); + } + else { + $location.hash = '#' + fragment; + } +} +function createOrigin(protocol, hostname, port) { + return protocol + "//" + hostname + (port ? ':' + port : ''); +} -function updateHash(location, fragment, replace) { - if (replace) { - var _href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(_href + '#' + fragment); - } else { - location.hash = '#' + fragment; - } +function configure(config) { + var $config = config; + $config.singleton(History, BrowserHistory); + $config.transient(LinkHandler, DefaultLinkHandler); } -function createOrigin(protocol, hostname, port) { - return protocol + '//' + hostname + (port ? ':' + port : ''); -} \ No newline at end of file +export { BrowserHistory, DefaultLinkHandler, LinkHandler, configure }; +//# sourceMappingURL=aurelia-history-browser.js.map diff --git a/dist/native-modules/aurelia-history-browser.js.map b/dist/native-modules/aurelia-history-browser.js.map new file mode 100644 index 0000000..323112a --- /dev/null +++ b/dist/native-modules/aurelia-history-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"aurelia-history-browser.js","sources":["../../src/link-handler.ts","../../src/browser-history.ts","../../src/aurelia-history-browser.ts"],"sourcesContent":["import { DOM, PLATFORM } from 'aurelia-pal';\nimport { BrowserHistory } from './browser-history';\nimport { AnchorEventInfo } from './interfaces';\n\n/**\n * Class responsible for handling interactions that should trigger browser history navigations.\n */\nexport class LinkHandler {\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {/**/}\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {/**/}\n}\n\n/**\n * The default LinkHandler implementation. Navigations are triggered by click events on\n * anchor elements with relative hrefs when the history instance is using pushstate.\n */\nexport class DefaultLinkHandler extends LinkHandler {\n\n /**@internal */\n handler: (e: Event) => void;\n\n /**@internal */\n history: BrowserHistory;\n /**\n * Creates an instance of DefaultLinkHandler.\n */\n constructor() {\n super();\n\n this.handler = (e) => {\n let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e);\n\n if (shouldHandleEvent) {\n e.preventDefault();\n this.history.navigate(href);\n }\n };\n }\n\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {\n if (history._hasPushState) {\n this.history = history;\n DOM.addEventListener('click', this.handler, true);\n }\n }\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {\n DOM.removeEventListener('click', this.handler, true);\n }\n\n /**\n * Gets the href and a \"should handle\" recommendation, given an Event.\n *\n * @param event The Event to inspect for target anchor and href.\n */\n static getEventInfo(event: Event): AnchorEventInfo {\n let $event = event as MouseEvent;\n let info = {\n shouldHandleEvent: false,\n href: null,\n anchor: null\n };\n\n let target = DefaultLinkHandler.findClosestAnchor($event.target as Element);\n if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) {\n return info;\n }\n\n if (hasAttribute(target, 'download')\n || hasAttribute(target, 'router-ignore')\n || hasAttribute(target, 'data-router-ignore')\n ) {\n return info;\n }\n\n if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) {\n return info;\n }\n\n let href = target.getAttribute('href');\n info.anchor = target;\n info.href = href;\n\n let leftButtonClicked = $event.which === 1;\n let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href));\n\n info.shouldHandleEvent = leftButtonClicked && isRelative;\n return info;\n }\n\n /**\n * Finds the closest ancestor that's an anchor element.\n *\n * @param el The element to search upward from.\n * @returns The link element that is the closest ancestor.\n */\n static findClosestAnchor(el: Element): Element {\n while (el) {\n if (el.tagName === 'A') {\n return el;\n }\n\n el = el.parentNode as Element;\n }\n }\n\n /**\n * Gets a value indicating whether or not an anchor targets the current window.\n *\n * @param target The anchor element whose target should be inspected.\n * @returns True if the target of the link element is this window; false otherwise.\n */\n static targetIsThisWindow(target: Element): boolean {\n let targetWindow = target.getAttribute('target');\n let win = PLATFORM.global;\n\n return !targetWindow ||\n targetWindow === win.name ||\n targetWindow === '_self';\n }\n}\n\nconst hasAttribute = (el: Element, attr: string) => el.hasAttribute(attr);\n","import { DOM, PLATFORM } from 'aurelia-pal';\nimport { LinkHandler } from './link-handler';\nimport { History } from 'aurelia-history';\n\n/**\n * An implementation of the basic history API.\n */\nexport class BrowserHistory extends History {\n /**@internal */\n static inject = [LinkHandler];\n\n /**@internal */\n _isActive: boolean;\n\n /**@internal*/\n _checkUrlCallback: any;\n /**@internal*/\n location: Location;\n /**@internal*/\n history: typeof PLATFORM['history'];\n /**@internal*/\n linkHandler: LinkHandler;\n /**@internal*/\n options: any;\n /**@internal*/\n root: string;\n /**@internal*/\n _wantsHashChange: boolean;\n /**@internal*/\n _hasPushState: boolean;\n /**@internal*/\n fragment: string;\n\n /**\n * Creates an instance of BrowserHistory\n * @param linkHandler An instance of LinkHandler.\n */\n constructor(linkHandler: LinkHandler) {\n super();\n\n this._isActive = false;\n this._checkUrlCallback = this._checkUrl.bind(this);\n\n this.location = PLATFORM.location;\n this.history = PLATFORM.history;\n this.linkHandler = linkHandler;\n }\n\n /**\n * Activates the history object.\n * @param options The set of options to activate history with.\n * @returns Whether or not activation occurred.\n */\n activate(options?: Object): boolean {\n if (this._isActive) {\n throw new Error('History has already been activated.');\n }\n\n let $history = this.history;\n let wantsPushState = !!(options as any).pushState;\n\n this._isActive = true;\n let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options);\n\n // Normalize root to always include a leading and trailing slash.\n let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/');\n\n let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false;\n let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState);\n\n // Determine how we check the URL state.\n let eventName: string;\n if (hasPushState) {\n eventName = 'popstate';\n } else if (wantsHashChange) {\n eventName = 'hashchange';\n }\n\n PLATFORM.addEventListener(eventName, this._checkUrlCallback);\n\n // Determine if we need to change the base url, for a pushState link\n // opened by a non-pushState browser.\n if (wantsHashChange && wantsPushState) {\n // Transition from hashChange to pushState or vice versa if both are requested.\n let $location = this.location;\n let atRoot = $location.pathname.replace(/[^\\/]$/, '$&/') === rootUrl;\n\n // If we've started off with a route from a `pushState`-enabled\n // browser, but we're currently in a browser that doesn't support it...\n if (!hasPushState && !atRoot) {\n let fragment = this.fragment = this._getFragment(null, true);\n $location.replace(rootUrl + $location.search + '#' + fragment);\n // Return immediately as browser will do redirect to new url\n return true;\n\n // Or if we've started out with a hash-based route, but we're currently\n // in a browser where it could be `pushState`-based instead...\n } else if (hasPushState && atRoot && $location.hash) {\n let fragment = this.fragment = this._getHash().replace(routeStripper, '');\n $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search);\n }\n }\n\n if (!this.fragment) {\n this.fragment = this._getFragment('');\n }\n\n this.linkHandler.activate(this);\n\n if (!normalizedOptions.silent) {\n return this._loadUrl('');\n }\n }\n\n /**\n * Deactivates the history object.\n */\n deactivate(): void {\n const handler = this._checkUrlCallback;\n PLATFORM.removeEventListener('popstate', handler);\n PLATFORM.removeEventListener('hashchange', handler);\n this._isActive = false;\n this.linkHandler.deactivate();\n }\n\n /**\n * Returns the fully-qualified root of the current history object.\n * @returns The absolute root of the application.\n */\n getAbsoluteRoot(): string {\n let $location = this.location;\n let origin = createOrigin($location.protocol, $location.hostname, $location.port);\n return `${origin}${this.root}`;\n }\n\n /**\n * Causes a history navigation to occur.\n *\n * @param fragment The history fragment to navigate to.\n * @param options The set of options that specify how the navigation should occur.\n * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred.\n */\n navigate(fragment?: string, {trigger = true, replace = false} = {}): boolean {\n let location = this.location;\n if (fragment && absoluteUrl.test(fragment)) {\n location.href = fragment;\n return true;\n }\n\n if (!this._isActive) {\n return false;\n }\n\n fragment = this._getFragment(fragment || '');\n\n if (this.fragment === fragment && !replace) {\n return false;\n }\n\n this.fragment = fragment;\n\n let url = this.root + fragment;\n\n // Don't include a trailing slash on the root.\n if (fragment === '' && url !== '/') {\n url = url.slice(0, -1);\n }\n\n // If pushState is available, we use it to set the fragment as a real URL.\n if (this._hasPushState) {\n url = url.replace('//', '/');\n this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url);\n } else if (this._wantsHashChange) {\n // If hash changes haven't been explicitly disabled, update the hash\n // fragment to store history.\n updateHash(location, fragment, replace);\n } else {\n // If you've told us that you explicitly don't want fallback hashchange-\n // based history, then `navigate` becomes a page refresh.\n location.assign(url);\n }\n\n if (trigger) {\n return this._loadUrl(fragment);\n }\n\n return true;\n }\n\n /**\n * Causes the history state to navigate back.\n */\n navigateBack(): void {\n this.history.back();\n }\n\n /**\n * Sets the document title.\n */\n setTitle(title: string): void {\n DOM.title = title;\n }\n\n /**\n * Sets a key in the history page state.\n * @param key The key for the value.\n * @param value The value to set.\n */\n setState(key: string, value: any): void {\n let $history = this.history;\n let state = Object.assign({}, $history.state);\n let { pathname, search, hash } = this.location;\n state[key] = value;\n $history.replaceState(state, null, `${pathname}${search}${hash}`);\n }\n\n /**\n * Gets a key in the history page state.\n * @param key The key for the value.\n * @return The value for the key.\n */\n getState(key: string): any {\n let state = Object.assign({}, this.history.state);\n return state[key];\n }\n\n /**\n * Returns the current index in the navigation history.\n * @returns The current index.\n */\n getHistoryIndex(): number {\n let historyIndex = this.getState('HistoryIndex');\n if (historyIndex === undefined) {\n historyIndex = this.history.length - 1;\n this.setState('HistoryIndex', historyIndex);\n }\n return historyIndex;\n }\n\n /**\n * Move to a specific position in the navigation history.\n * @param movement The amount of steps, positive or negative, to move.\n */\n go(movement: number): void {\n this.history.go(movement);\n }\n\n /**\n * @internal\n */\n _getHash(): string {\n return this.location.hash.substr(1);\n }\n\n /**\n * @internal\n */\n _getFragment(fragment: string, forcePushState?: boolean): string {\n let rootUrl: string;\n\n if (!fragment) {\n if (this._hasPushState || !this._wantsHashChange || forcePushState) {\n let location = this.location;\n fragment = location.pathname + location.search;\n rootUrl = this.root.replace(trailingSlash, '');\n if (!fragment.indexOf(rootUrl)) {\n fragment = fragment.substr(rootUrl.length);\n }\n } else {\n fragment = this._getHash();\n }\n }\n\n return '/' + fragment.replace(routeStripper, '');\n }\n\n /**\n * Url change handler.\n * Invoked when current fragment is different with previous fragment\n * @internal\n */\n _checkUrl(): void {\n let current = this._getFragment('');\n if (current !== this.fragment) {\n this._loadUrl('');\n }\n }\n\n /**\n * invoke routeHandler\n * @internal\n */\n _loadUrl(fragmentOverride: string): boolean {\n let fragment = this.fragment = this._getFragment(fragmentOverride);\n\n return this.options.routeHandler ?\n this.options.routeHandler(fragment) :\n false;\n }\n}\n\n// Cached regex for stripping a leading hash/slash and trailing space.\nconst routeStripper = /^#?\\/*|\\s+$/g;\n\n// Cached regex for stripping leading and trailing slashes.\nconst rootStripper = /^\\/+|\\/+$/g;\n\n// Cached regex for removing a trailing slash.\nconst trailingSlash = /\\/$/;\n\n// Cached regex for detecting if a URL is absolute,\n// i.e., starts with a scheme or is scheme-relative.\n// See http://www.ietf.org/rfc/rfc2396.txt section 3.1 for valid scheme format\nconst absoluteUrl = /^([a-z][a-z0-9+\\-.]*:)?\\/\\//i;\n\n// Update the hash location, either replacing the current entry, or adding\n// a new one to the browser history.\nfunction updateHash($location: Location, fragment: string, replace: boolean) {\n if (replace) {\n let href = $location.href.replace(/(javascript:|#).*$/, '');\n $location.replace(href + '#' + fragment);\n } else {\n // Some browsers require that `hash` contains a leading #.\n $location.hash = '#' + fragment;\n }\n}\n\nfunction createOrigin(protocol: string, hostname: string, port: string) {\n return `${protocol}//${hostname}${port ? ':' + port : ''}`;\n}\n","import {History} from 'aurelia-history';\nimport {LinkHandler, DefaultLinkHandler} from './link-handler';\nimport { BrowserHistory } from './browser-history';\n\n/**\n * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container.\n * @param config The FrameworkConfiguration object provided by Aurelia.\n */\nexport function configure(config: Object): void {\n // work around for converting to TS without breaking compat\n const $config = config as any;\n $config.singleton(History, BrowserHistory);\n $config.transient(LinkHandler, DefaultLinkHandler);\n}\n\nexport {\n LinkHandler,\n DefaultLinkHandler,\n BrowserHistory\n};\n"],"names":["tslib_1.__extends"],"mappings":"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"} \ No newline at end of file diff --git a/dist/native-modules/index.js b/dist/native-modules/index.js deleted file mode 100644 index 4c74765..0000000 --- a/dist/native-modules/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './aurelia-history-browser'; \ No newline at end of file diff --git a/dist/system/aurelia-history-browser.js b/dist/system/aurelia-history-browser.js index b3e2386..a870334 100644 --- a/dist/system/aurelia-history-browser.js +++ b/dist/system/aurelia-history-browser.js @@ -1,368 +1,305 @@ -'use strict'; - -System.register(['aurelia-pal', 'aurelia-history'], function (_export, _context) { - "use strict"; - - var DOM, PLATFORM, History, _class, _temp, LinkHandler, DefaultLinkHandler, BrowserHistory, routeStripper, rootStripper, trailingSlash, absoluteUrl; - - function _possibleConstructorReturn(self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; - } - - function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - } - - - - function configure(config) { - config.singleton(History, BrowserHistory); - config.transient(LinkHandler, DefaultLinkHandler); - } - - _export('configure', configure); - - function updateHash(location, fragment, replace) { - if (replace) { - var _href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(_href + '#' + fragment); - } else { - location.hash = '#' + fragment; - } - } - - function createOrigin(protocol, hostname, port) { - return protocol + '//' + hostname + (port ? ':' + port : ''); - } - return { - setters: [function (_aureliaPal) { - DOM = _aureliaPal.DOM; - PLATFORM = _aureliaPal.PLATFORM; - }, function (_aureliaHistory) { - History = _aureliaHistory.History; - }], - execute: function () { - _export('LinkHandler', LinkHandler = function () { - function LinkHandler() { - - } - - LinkHandler.prototype.activate = function activate(history) {}; - - LinkHandler.prototype.deactivate = function deactivate() {}; - - return LinkHandler; - }()); - - _export('LinkHandler', LinkHandler); - - _export('DefaultLinkHandler', DefaultLinkHandler = function (_LinkHandler) { - _inherits(DefaultLinkHandler, _LinkHandler); - - function DefaultLinkHandler() { - - - var _this = _possibleConstructorReturn(this, _LinkHandler.call(this)); - - _this.handler = function (e) { - var _DefaultLinkHandler$g = DefaultLinkHandler.getEventInfo(e), - shouldHandleEvent = _DefaultLinkHandler$g.shouldHandleEvent, - href = _DefaultLinkHandler$g.href; - - if (shouldHandleEvent) { - e.preventDefault(); - _this.history.navigate(href); +System.register(['aurelia-history', 'aurelia-pal'], function (exports, module) { + 'use strict'; + var History, DOM, PLATFORM; + return { + setters: [function (module) { + History = module.History; + }, function (module) { + DOM = module.DOM; + PLATFORM = module.PLATFORM; + }], + execute: function () { + + exports('configure', configure); + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } - }; - return _this; - } - DefaultLinkHandler.prototype.activate = function activate(history) { - if (history._hasPushState) { - this.history = history; - DOM.addEventListener('click', this.handler, true); - } - }; - - DefaultLinkHandler.prototype.deactivate = function deactivate() { - DOM.removeEventListener('click', this.handler); - }; - - DefaultLinkHandler.getEventInfo = function getEventInfo(event) { - var info = { - shouldHandleEvent: false, - href: null, - anchor: null - }; - - var target = DefaultLinkHandler.findClosestAnchor(event.target); - if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { - return info; - } - - if (target.hasAttribute('download') || target.hasAttribute('router-ignore') || target.hasAttribute('data-router-ignore')) { - return info; - } - - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { - return info; - } - - var href = target.getAttribute('href'); - info.anchor = target; - info.href = href; - - var leftButtonClicked = event.which === 1; - var isRelative = href && !(href.charAt(0) === '#' || /^[a-z]+:/i.test(href)); - - info.shouldHandleEvent = leftButtonClicked && isRelative; - return info; - }; - - DefaultLinkHandler.findClosestAnchor = function findClosestAnchor(el) { - while (el) { - if (el.tagName === 'A') { - return el; + var LinkHandler = exports('LinkHandler', (function () { + function LinkHandler() { + } + LinkHandler.prototype.activate = function (history) { }; + LinkHandler.prototype.deactivate = function () { }; + return LinkHandler; + }())); + var DefaultLinkHandler = exports('DefaultLinkHandler', (function (_super) { + __extends(DefaultLinkHandler, _super); + function DefaultLinkHandler() { + var _this = _super.call(this) || this; + _this.handler = function (e) { + var _a = DefaultLinkHandler.getEventInfo(e), shouldHandleEvent = _a.shouldHandleEvent, href = _a.href; + if (shouldHandleEvent) { + e.preventDefault(); + _this.history.navigate(href); + } + }; + return _this; + } + DefaultLinkHandler.prototype.activate = function (history) { + if (history._hasPushState) { + this.history = history; + DOM.addEventListener('click', this.handler, true); + } + }; + DefaultLinkHandler.prototype.deactivate = function () { + DOM.removeEventListener('click', this.handler, true); + }; + DefaultLinkHandler.getEventInfo = function (event) { + var $event = event; + var info = { + shouldHandleEvent: false, + href: null, + anchor: null + }; + var target = DefaultLinkHandler.findClosestAnchor($event.target); + if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) { + return info; + } + if (hasAttribute(target, 'download') + || hasAttribute(target, 'router-ignore') + || hasAttribute(target, 'data-router-ignore')) { + return info; + } + if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) { + return info; + } + var href = target.getAttribute('href'); + info.anchor = target; + info.href = href; + var leftButtonClicked = $event.which === 1; + var isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href)); + info.shouldHandleEvent = leftButtonClicked && isRelative; + return info; + }; + DefaultLinkHandler.findClosestAnchor = function (el) { + while (el) { + if (el.tagName === 'A') { + return el; + } + el = el.parentNode; + } + }; + DefaultLinkHandler.targetIsThisWindow = function (target) { + var targetWindow = target.getAttribute('target'); + var win = PLATFORM.global; + return !targetWindow || + targetWindow === win.name || + targetWindow === '_self'; + }; + return DefaultLinkHandler; + }(LinkHandler))); + var hasAttribute = function (el, attr) { return el.hasAttribute(attr); }; + + var BrowserHistory = exports('BrowserHistory', (function (_super) { + __extends(BrowserHistory, _super); + function BrowserHistory(linkHandler) { + var _this = _super.call(this) || this; + _this._isActive = false; + _this._checkUrlCallback = _this._checkUrl.bind(_this); + _this.location = PLATFORM.location; + _this.history = PLATFORM.history; + _this.linkHandler = linkHandler; + return _this; + } + BrowserHistory.prototype.activate = function (options) { + if (this._isActive) { + throw new Error('History has already been activated.'); + } + var $history = this.history; + var wantsPushState = !!options.pushState; + this._isActive = true; + var normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options); + var rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/'); + var wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false; + var hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState); + var eventName; + if (hasPushState) { + eventName = 'popstate'; + } + else if (wantsHashChange) { + eventName = 'hashchange'; + } + PLATFORM.addEventListener(eventName, this._checkUrlCallback); + if (wantsHashChange && wantsPushState) { + var $location = this.location; + var atRoot = $location.pathname.replace(/[^\/]$/, '$&/') === rootUrl; + if (!hasPushState && !atRoot) { + var fragment = this.fragment = this._getFragment(null, true); + $location.replace(rootUrl + $location.search + '#' + fragment); + return true; + } + else if (hasPushState && atRoot && $location.hash) { + var fragment = this.fragment = this._getHash().replace(routeStripper, ''); + $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search); + } + } + if (!this.fragment) { + this.fragment = this._getFragment(''); + } + this.linkHandler.activate(this); + if (!normalizedOptions.silent) { + return this._loadUrl(''); + } + }; + BrowserHistory.prototype.deactivate = function () { + var handler = this._checkUrlCallback; + PLATFORM.removeEventListener('popstate', handler); + PLATFORM.removeEventListener('hashchange', handler); + this._isActive = false; + this.linkHandler.deactivate(); + }; + BrowserHistory.prototype.getAbsoluteRoot = function () { + var $location = this.location; + var origin = createOrigin($location.protocol, $location.hostname, $location.port); + return "" + origin + this.root; + }; + BrowserHistory.prototype.navigate = function (fragment, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b.trigger, trigger = _c === void 0 ? true : _c, _d = _b.replace, replace = _d === void 0 ? false : _d; + var location = this.location; + if (fragment && absoluteUrl.test(fragment)) { + location.href = fragment; + return true; + } + if (!this._isActive) { + return false; + } + fragment = this._getFragment(fragment || ''); + if (this.fragment === fragment && !replace) { + return false; + } + this.fragment = fragment; + var url = this.root + fragment; + if (fragment === '' && url !== '/') { + url = url.slice(0, -1); + } + if (this._hasPushState) { + url = url.replace('//', '/'); + this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); + } + else if (this._wantsHashChange) { + updateHash(location, fragment, replace); + } + else { + location.assign(url); + } + if (trigger) { + return this._loadUrl(fragment); + } + return true; + }; + BrowserHistory.prototype.navigateBack = function () { + this.history.back(); + }; + BrowserHistory.prototype.setTitle = function (title) { + DOM.title = title; + }; + BrowserHistory.prototype.setState = function (key, value) { + var $history = this.history; + var state = Object.assign({}, $history.state); + var _a = this.location, pathname = _a.pathname, search = _a.search, hash = _a.hash; + state[key] = value; + $history.replaceState(state, null, "" + pathname + search + hash); + }; + BrowserHistory.prototype.getState = function (key) { + var state = Object.assign({}, this.history.state); + return state[key]; + }; + BrowserHistory.prototype.getHistoryIndex = function () { + var historyIndex = this.getState('HistoryIndex'); + if (historyIndex === undefined) { + historyIndex = this.history.length - 1; + this.setState('HistoryIndex', historyIndex); + } + return historyIndex; + }; + BrowserHistory.prototype.go = function (movement) { + this.history.go(movement); + }; + BrowserHistory.prototype._getHash = function () { + return this.location.hash.substr(1); + }; + BrowserHistory.prototype._getFragment = function (fragment, forcePushState) { + var rootUrl; + if (!fragment) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + var location_1 = this.location; + fragment = location_1.pathname + location_1.search; + rootUrl = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(rootUrl)) { + fragment = fragment.substr(rootUrl.length); + } + } + else { + fragment = this._getHash(); + } + } + return '/' + fragment.replace(routeStripper, ''); + }; + BrowserHistory.prototype._checkUrl = function () { + var current = this._getFragment(''); + if (current !== this.fragment) { + this._loadUrl(''); + } + }; + BrowserHistory.prototype._loadUrl = function (fragmentOverride) { + var fragment = this.fragment = this._getFragment(fragmentOverride); + return this.options.routeHandler ? + this.options.routeHandler(fragment) : + false; + }; + BrowserHistory.inject = [LinkHandler]; + return BrowserHistory; + }(History))); + var routeStripper = /^#?\/*|\s+$/g; + var rootStripper = /^\/+|\/+$/g; + var trailingSlash = /\/$/; + var absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; + function updateHash($location, fragment, replace) { + if (replace) { + var href = $location.href.replace(/(javascript:|#).*$/, ''); + $location.replace(href + '#' + fragment); + } + else { + $location.hash = '#' + fragment; + } + } + function createOrigin(protocol, hostname, port) { + return protocol + "//" + hostname + (port ? ':' + port : ''); } - el = el.parentNode; - } - }; - - DefaultLinkHandler.targetIsThisWindow = function targetIsThisWindow(target) { - var targetWindow = target.getAttribute('target'); - var win = PLATFORM.global; - - return !targetWindow || targetWindow === win.name || targetWindow === '_self'; - }; - - return DefaultLinkHandler; - }(LinkHandler)); - - _export('DefaultLinkHandler', DefaultLinkHandler); - - _export('BrowserHistory', BrowserHistory = (_temp = _class = function (_History) { - _inherits(BrowserHistory, _History); - - function BrowserHistory(linkHandler) { - - - var _this2 = _possibleConstructorReturn(this, _History.call(this)); - - _this2._isActive = false; - _this2._checkUrlCallback = _this2._checkUrl.bind(_this2); - - _this2.location = PLATFORM.location; - _this2.history = PLATFORM.history; - _this2.linkHandler = linkHandler; - return _this2; - } - - BrowserHistory.prototype.activate = function activate(options) { - if (this._isActive) { - throw new Error('History has already been activated.'); - } - - var wantsPushState = !!options.pushState; - - this._isActive = true; - this.options = Object.assign({}, { root: '/' }, this.options, options); - - this.root = ('/' + this.options.root + '/').replace(rootStripper, '/'); - - this._wantsHashChange = this.options.hashChange !== false; - this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); - - var eventName = void 0; - if (this._hasPushState) { - eventName = 'popstate'; - } else if (this._wantsHashChange) { - eventName = 'hashchange'; - } - - PLATFORM.addEventListener(eventName, this._checkUrlCallback); - - if (this._wantsHashChange && wantsPushState) { - var loc = this.location; - var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; - - if (!this._hasPushState && !atRoot) { - this.fragment = this._getFragment(null, true); - this.location.replace(this.root + this.location.search + '#' + this.fragment); - - return true; - } else if (this._hasPushState && atRoot && loc.hash) { - this.fragment = this._getHash().replace(routeStripper, ''); - this.history.replaceState({}, DOM.title, this.root + this.fragment + loc.search); - } - } - - if (!this.fragment) { - this.fragment = this._getFragment(); - } - - this.linkHandler.activate(this); - - if (!this.options.silent) { - return this._loadUrl(); - } - }; - - BrowserHistory.prototype.deactivate = function deactivate() { - PLATFORM.removeEventListener('popstate', this._checkUrlCallback); - PLATFORM.removeEventListener('hashchange', this._checkUrlCallback); - this._isActive = false; - this.linkHandler.deactivate(); - }; - - BrowserHistory.prototype.getAbsoluteRoot = function getAbsoluteRoot() { - var origin = createOrigin(this.location.protocol, this.location.hostname, this.location.port); - return '' + origin + this.root; - }; - - BrowserHistory.prototype.navigate = function navigate(fragment) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$trigger = _ref.trigger, - trigger = _ref$trigger === undefined ? true : _ref$trigger, - _ref$replace = _ref.replace, - replace = _ref$replace === undefined ? false : _ref$replace; - - if (fragment && absoluteUrl.test(fragment)) { - this.location.href = fragment; - return true; - } - - if (!this._isActive) { - return false; - } - - fragment = this._getFragment(fragment || ''); - - if (this.fragment === fragment && !replace) { - return false; - } - - this.fragment = fragment; - - var url = this.root + fragment; - - if (fragment === '' && url !== '/') { - url = url.slice(0, -1); - } - - if (this._hasPushState) { - url = url.replace('//', '/'); - this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url); - } else if (this._wantsHashChange) { - updateHash(this.location, fragment, replace); - } else { - this.location.assign(url); - } - - if (trigger) { - return this._loadUrl(fragment); - } - - return true; - }; - - BrowserHistory.prototype.navigateBack = function navigateBack() { - this.history.back(); - }; - - BrowserHistory.prototype.setTitle = function setTitle(title) { - DOM.title = title; - }; - - BrowserHistory.prototype.setState = function setState(key, value) { - var state = Object.assign({}, this.history.state); - var _location = this.location, - pathname = _location.pathname, - search = _location.search, - hash = _location.hash; - - state[key] = value; - this.history.replaceState(state, null, '' + pathname + search + hash); - }; - - BrowserHistory.prototype.getState = function getState(key) { - var state = Object.assign({}, this.history.state); - return state[key]; - }; - - BrowserHistory.prototype.getHistoryIndex = function getHistoryIndex() { - var historyIndex = this.getState('HistoryIndex'); - if (historyIndex === undefined) { - historyIndex = this.history.length - 1; - this.setState('HistoryIndex', historyIndex); - } - return historyIndex; - }; - - BrowserHistory.prototype.go = function go(movement) { - this.history.go(movement); - }; - - BrowserHistory.prototype._getHash = function _getHash() { - return this.location.hash.substr(1); - }; - - BrowserHistory.prototype._getFragment = function _getFragment(fragment, forcePushState) { - var root = void 0; - - if (!fragment) { - if (this._hasPushState || !this._wantsHashChange || forcePushState) { - fragment = this.location.pathname + this.location.search; - root = this.root.replace(trailingSlash, ''); - if (!fragment.indexOf(root)) { - fragment = fragment.substr(root.length); - } - } else { - fragment = this._getHash(); + function configure(config) { + var $config = config; + $config.singleton(History, BrowserHistory); + $config.transient(LinkHandler, DefaultLinkHandler); } - } - - return '/' + fragment.replace(routeStripper, ''); - }; - - BrowserHistory.prototype._checkUrl = function _checkUrl() { - var current = this._getFragment(); - if (current !== this.fragment) { - this._loadUrl(); - } - }; - BrowserHistory.prototype._loadUrl = function _loadUrl(fragmentOverride) { - var fragment = this.fragment = this._getFragment(fragmentOverride); - - return this.options.routeHandler ? this.options.routeHandler(fragment) : false; - }; - - return BrowserHistory; - }(History), _class.inject = [LinkHandler], _temp)); - - _export('BrowserHistory', BrowserHistory); - - routeStripper = /^#?\/*|\s+$/g; - rootStripper = /^\/+|\/+$/g; - trailingSlash = /\/$/; - absoluteUrl = /^([a-z][a-z0-9+\-.]*:)?\/\//i; - } - }; -}); \ No newline at end of file + } + }; +}); +//# sourceMappingURL=aurelia-history-browser.js.map diff --git a/dist/system/aurelia-history-browser.js.map b/dist/system/aurelia-history-browser.js.map new file mode 100644 index 0000000..e743647 --- /dev/null +++ b/dist/system/aurelia-history-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"aurelia-history-browser.js","sources":["../../src/link-handler.ts","../../src/browser-history.ts","../../src/aurelia-history-browser.ts"],"sourcesContent":["import { DOM, PLATFORM } from 'aurelia-pal';\nimport { BrowserHistory } from './browser-history';\nimport { AnchorEventInfo } from './interfaces';\n\n/**\n * Class responsible for handling interactions that should trigger browser history navigations.\n */\nexport class LinkHandler {\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {/**/}\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {/**/}\n}\n\n/**\n * The default LinkHandler implementation. Navigations are triggered by click events on\n * anchor elements with relative hrefs when the history instance is using pushstate.\n */\nexport class DefaultLinkHandler extends LinkHandler {\n\n /**@internal */\n handler: (e: Event) => void;\n\n /**@internal */\n history: BrowserHistory;\n /**\n * Creates an instance of DefaultLinkHandler.\n */\n constructor() {\n super();\n\n this.handler = (e) => {\n let { shouldHandleEvent, href } = DefaultLinkHandler.getEventInfo(e);\n\n if (shouldHandleEvent) {\n e.preventDefault();\n this.history.navigate(href);\n }\n };\n }\n\n /**\n * Activate the instance.\n *\n * @param history The BrowserHistory instance that navigations should be dispatched to.\n */\n activate(history: BrowserHistory): void {\n if (history._hasPushState) {\n this.history = history;\n DOM.addEventListener('click', this.handler, true);\n }\n }\n\n /**\n * Deactivate the instance. Event handlers and other resources should be cleaned up here.\n */\n deactivate(): void {\n DOM.removeEventListener('click', this.handler, true);\n }\n\n /**\n * Gets the href and a \"should handle\" recommendation, given an Event.\n *\n * @param event The Event to inspect for target anchor and href.\n */\n static getEventInfo(event: Event): AnchorEventInfo {\n let $event = event as MouseEvent;\n let info = {\n shouldHandleEvent: false,\n href: null,\n anchor: null\n };\n\n let target = DefaultLinkHandler.findClosestAnchor($event.target as Element);\n if (!target || !DefaultLinkHandler.targetIsThisWindow(target)) {\n return info;\n }\n\n if (hasAttribute(target, 'download')\n || hasAttribute(target, 'router-ignore')\n || hasAttribute(target, 'data-router-ignore')\n ) {\n return info;\n }\n\n if ($event.altKey || $event.ctrlKey || $event.metaKey || $event.shiftKey) {\n return info;\n }\n\n let href = target.getAttribute('href');\n info.anchor = target;\n info.href = href;\n\n let leftButtonClicked = $event.which === 1;\n let isRelative = href && !(href.charAt(0) === '#' || (/^[a-z]+:/i).test(href));\n\n info.shouldHandleEvent = leftButtonClicked && isRelative;\n return info;\n }\n\n /**\n * Finds the closest ancestor that's an anchor element.\n *\n * @param el The element to search upward from.\n * @returns The link element that is the closest ancestor.\n */\n static findClosestAnchor(el: Element): Element {\n while (el) {\n if (el.tagName === 'A') {\n return el;\n }\n\n el = el.parentNode as Element;\n }\n }\n\n /**\n * Gets a value indicating whether or not an anchor targets the current window.\n *\n * @param target The anchor element whose target should be inspected.\n * @returns True if the target of the link element is this window; false otherwise.\n */\n static targetIsThisWindow(target: Element): boolean {\n let targetWindow = target.getAttribute('target');\n let win = PLATFORM.global;\n\n return !targetWindow ||\n targetWindow === win.name ||\n targetWindow === '_self';\n }\n}\n\nconst hasAttribute = (el: Element, attr: string) => el.hasAttribute(attr);\n","import { DOM, PLATFORM } from 'aurelia-pal';\nimport { LinkHandler } from './link-handler';\nimport { History } from 'aurelia-history';\n\n/**\n * An implementation of the basic history API.\n */\nexport class BrowserHistory extends History {\n /**@internal */\n static inject = [LinkHandler];\n\n /**@internal */\n _isActive: boolean;\n\n /**@internal*/\n _checkUrlCallback: any;\n /**@internal*/\n location: Location;\n /**@internal*/\n history: typeof PLATFORM['history'];\n /**@internal*/\n linkHandler: LinkHandler;\n /**@internal*/\n options: any;\n /**@internal*/\n root: string;\n /**@internal*/\n _wantsHashChange: boolean;\n /**@internal*/\n _hasPushState: boolean;\n /**@internal*/\n fragment: string;\n\n /**\n * Creates an instance of BrowserHistory\n * @param linkHandler An instance of LinkHandler.\n */\n constructor(linkHandler: LinkHandler) {\n super();\n\n this._isActive = false;\n this._checkUrlCallback = this._checkUrl.bind(this);\n\n this.location = PLATFORM.location;\n this.history = PLATFORM.history;\n this.linkHandler = linkHandler;\n }\n\n /**\n * Activates the history object.\n * @param options The set of options to activate history with.\n * @returns Whether or not activation occurred.\n */\n activate(options?: Object): boolean {\n if (this._isActive) {\n throw new Error('History has already been activated.');\n }\n\n let $history = this.history;\n let wantsPushState = !!(options as any).pushState;\n\n this._isActive = true;\n let normalizedOptions = this.options = Object.assign({}, { root: '/' }, this.options, options);\n\n // Normalize root to always include a leading and trailing slash.\n let rootUrl = this.root = ('/' + normalizedOptions.root + '/').replace(rootStripper, '/');\n\n let wantsHashChange = this._wantsHashChange = normalizedOptions.hashChange !== false;\n let hasPushState = this._hasPushState = !!(normalizedOptions.pushState && $history && $history.pushState);\n\n // Determine how we check the URL state.\n let eventName: string;\n if (hasPushState) {\n eventName = 'popstate';\n } else if (wantsHashChange) {\n eventName = 'hashchange';\n }\n\n PLATFORM.addEventListener(eventName, this._checkUrlCallback);\n\n // Determine if we need to change the base url, for a pushState link\n // opened by a non-pushState browser.\n if (wantsHashChange && wantsPushState) {\n // Transition from hashChange to pushState or vice versa if both are requested.\n let $location = this.location;\n let atRoot = $location.pathname.replace(/[^\\/]$/, '$&/') === rootUrl;\n\n // If we've started off with a route from a `pushState`-enabled\n // browser, but we're currently in a browser that doesn't support it...\n if (!hasPushState && !atRoot) {\n let fragment = this.fragment = this._getFragment(null, true);\n $location.replace(rootUrl + $location.search + '#' + fragment);\n // Return immediately as browser will do redirect to new url\n return true;\n\n // Or if we've started out with a hash-based route, but we're currently\n // in a browser where it could be `pushState`-based instead...\n } else if (hasPushState && atRoot && $location.hash) {\n let fragment = this.fragment = this._getHash().replace(routeStripper, '');\n $history.replaceState({}, DOM.title, rootUrl + fragment + $location.search);\n }\n }\n\n if (!this.fragment) {\n this.fragment = this._getFragment('');\n }\n\n this.linkHandler.activate(this);\n\n if (!normalizedOptions.silent) {\n return this._loadUrl('');\n }\n }\n\n /**\n * Deactivates the history object.\n */\n deactivate(): void {\n const handler = this._checkUrlCallback;\n PLATFORM.removeEventListener('popstate', handler);\n PLATFORM.removeEventListener('hashchange', handler);\n this._isActive = false;\n this.linkHandler.deactivate();\n }\n\n /**\n * Returns the fully-qualified root of the current history object.\n * @returns The absolute root of the application.\n */\n getAbsoluteRoot(): string {\n let $location = this.location;\n let origin = createOrigin($location.protocol, $location.hostname, $location.port);\n return `${origin}${this.root}`;\n }\n\n /**\n * Causes a history navigation to occur.\n *\n * @param fragment The history fragment to navigate to.\n * @param options The set of options that specify how the navigation should occur.\n * @return Promise if triggering navigation, otherwise true/false indicating if navigation occurred.\n */\n navigate(fragment?: string, {trigger = true, replace = false} = {}): boolean {\n let location = this.location;\n if (fragment && absoluteUrl.test(fragment)) {\n location.href = fragment;\n return true;\n }\n\n if (!this._isActive) {\n return false;\n }\n\n fragment = this._getFragment(fragment || '');\n\n if (this.fragment === fragment && !replace) {\n return false;\n }\n\n this.fragment = fragment;\n\n let url = this.root + fragment;\n\n // Don't include a trailing slash on the root.\n if (fragment === '' && url !== '/') {\n url = url.slice(0, -1);\n }\n\n // If pushState is available, we use it to set the fragment as a real URL.\n if (this._hasPushState) {\n url = url.replace('//', '/');\n this.history[replace ? 'replaceState' : 'pushState']({}, DOM.title, url);\n } else if (this._wantsHashChange) {\n // If hash changes haven't been explicitly disabled, update the hash\n // fragment to store history.\n updateHash(location, fragment, replace);\n } else {\n // If you've told us that you explicitly don't want fallback hashchange-\n // based history, then `navigate` becomes a page refresh.\n location.assign(url);\n }\n\n if (trigger) {\n return this._loadUrl(fragment);\n }\n\n return true;\n }\n\n /**\n * Causes the history state to navigate back.\n */\n navigateBack(): void {\n this.history.back();\n }\n\n /**\n * Sets the document title.\n */\n setTitle(title: string): void {\n DOM.title = title;\n }\n\n /**\n * Sets a key in the history page state.\n * @param key The key for the value.\n * @param value The value to set.\n */\n setState(key: string, value: any): void {\n let $history = this.history;\n let state = Object.assign({}, $history.state);\n let { pathname, search, hash } = this.location;\n state[key] = value;\n $history.replaceState(state, null, `${pathname}${search}${hash}`);\n }\n\n /**\n * Gets a key in the history page state.\n * @param key The key for the value.\n * @return The value for the key.\n */\n getState(key: string): any {\n let state = Object.assign({}, this.history.state);\n return state[key];\n }\n\n /**\n * Returns the current index in the navigation history.\n * @returns The current index.\n */\n getHistoryIndex(): number {\n let historyIndex = this.getState('HistoryIndex');\n if (historyIndex === undefined) {\n historyIndex = this.history.length - 1;\n this.setState('HistoryIndex', historyIndex);\n }\n return historyIndex;\n }\n\n /**\n * Move to a specific position in the navigation history.\n * @param movement The amount of steps, positive or negative, to move.\n */\n go(movement: number): void {\n this.history.go(movement);\n }\n\n /**\n * @internal\n */\n _getHash(): string {\n return this.location.hash.substr(1);\n }\n\n /**\n * @internal\n */\n _getFragment(fragment: string, forcePushState?: boolean): string {\n let rootUrl: string;\n\n if (!fragment) {\n if (this._hasPushState || !this._wantsHashChange || forcePushState) {\n let location = this.location;\n fragment = location.pathname + location.search;\n rootUrl = this.root.replace(trailingSlash, '');\n if (!fragment.indexOf(rootUrl)) {\n fragment = fragment.substr(rootUrl.length);\n }\n } else {\n fragment = this._getHash();\n }\n }\n\n return '/' + fragment.replace(routeStripper, '');\n }\n\n /**\n * Url change handler.\n * Invoked when current fragment is different with previous fragment\n * @internal\n */\n _checkUrl(): void {\n let current = this._getFragment('');\n if (current !== this.fragment) {\n this._loadUrl('');\n }\n }\n\n /**\n * invoke routeHandler\n * @internal\n */\n _loadUrl(fragmentOverride: string): boolean {\n let fragment = this.fragment = this._getFragment(fragmentOverride);\n\n return this.options.routeHandler ?\n this.options.routeHandler(fragment) :\n false;\n }\n}\n\n// Cached regex for stripping a leading hash/slash and trailing space.\nconst routeStripper = /^#?\\/*|\\s+$/g;\n\n// Cached regex for stripping leading and trailing slashes.\nconst rootStripper = /^\\/+|\\/+$/g;\n\n// Cached regex for removing a trailing slash.\nconst trailingSlash = /\\/$/;\n\n// Cached regex for detecting if a URL is absolute,\n// i.e., starts with a scheme or is scheme-relative.\n// See http://www.ietf.org/rfc/rfc2396.txt section 3.1 for valid scheme format\nconst absoluteUrl = /^([a-z][a-z0-9+\\-.]*:)?\\/\\//i;\n\n// Update the hash location, either replacing the current entry, or adding\n// a new one to the browser history.\nfunction updateHash($location: Location, fragment: string, replace: boolean) {\n if (replace) {\n let href = $location.href.replace(/(javascript:|#).*$/, '');\n $location.replace(href + '#' + fragment);\n } else {\n // Some browsers require that `hash` contains a leading #.\n $location.hash = '#' + fragment;\n }\n}\n\nfunction createOrigin(protocol: string, hostname: string, port: string) {\n return `${protocol}//${hostname}${port ? ':' + port : ''}`;\n}\n","import {History} from 'aurelia-history';\nimport {LinkHandler, DefaultLinkHandler} from './link-handler';\nimport { BrowserHistory } from './browser-history';\n\n/**\n * Configures the plugin by registering BrowserHistory as the implementation of History in the DI container.\n * @param config The FrameworkConfiguration object provided by Aurelia.\n */\nexport function configure(config: Object): void {\n // work around for converting to TS without breaking compat\n const $config = config as any;\n $config.singleton(History, BrowserHistory);\n $config.transient(LinkHandler, DefaultLinkHandler);\n}\n\nexport {\n LinkHandler,\n DefaultLinkHandler,\n BrowserHistory\n};\n"],"names":["tslib_1.__extends"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAOA;iBAYC;gBANC,8BAAQ,GAAR,UAAS,OAAuB,KAAc;gBAK9C,gCAAU,GAAV,eAAyB;gBAC3B,kBAAC;YAAD,CAAC,KAAA;;gBAMuCA,sCAAW;gBAUjD;oBAAA,YACE,iBAAO,SAUR;oBARC,KAAI,CAAC,OAAO,GAAG,UAAC,CAAC;wBACX,IAAA,uCAAgE,EAA9D,wCAAiB,EAAE,cAA2C,CAAC;wBAErE,IAAI,iBAAiB,EAAE;4BACrB,CAAC,CAAC,cAAc,EAAE,CAAC;4BACnB,KAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;yBAC7B;qBACF,CAAC;;iBACH;gBAOD,qCAAQ,GAAR,UAAS,OAAuB;oBAC9B,IAAI,OAAO,CAAC,aAAa,EAAE;wBACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;wBACvB,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;qBACnD;iBACF;gBAKD,uCAAU,GAAV;oBACE,GAAG,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;iBACtD;gBAOM,+BAAY,GAAnB,UAAoB,KAAY;oBAC9B,IAAI,MAAM,GAAG,KAAmB,CAAC;oBACjC,IAAI,IAAI,GAAG;wBACT,iBAAiB,EAAE,KAAK;wBACxB,IAAI,EAAE,IAAI;wBACV,MAAM,EAAE,IAAI;qBACb,CAAC;oBAEF,IAAI,MAAM,GAAG,kBAAkB,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAiB,CAAC,CAAC;oBAC5E,IAAI,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE;wBAC7D,OAAO,IAAI,CAAC;qBACb;oBAED,IAAI,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC;2BAC/B,YAAY,CAAC,MAAM,EAAE,eAAe,CAAC;2BACrC,YAAY,CAAC,MAAM,EAAE,oBAAoB,CAAC,EAC7C;wBACA,OAAO,IAAI,CAAC;qBACb;oBAED,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE;wBACxE,OAAO,IAAI,CAAC;qBACb;oBAED,IAAI,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;oBACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;oBACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;oBAEjB,IAAI,iBAAiB,GAAG,MAAM,CAAC,KAAK,KAAK,CAAC,CAAC;oBAC3C,IAAI,UAAU,GAAG,IAAI,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBAE/E,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,IAAI,UAAU,CAAC;oBACzD,OAAO,IAAI,CAAC;iBACb;gBAQM,oCAAiB,GAAxB,UAAyB,EAAW;oBAClC,OAAO,EAAE,EAAE;wBACT,IAAI,EAAE,CAAC,OAAO,KAAK,GAAG,EAAE;4BACtB,OAAO,EAAE,CAAC;yBACX;wBAED,EAAE,GAAG,EAAE,CAAC,UAAqB,CAAC;qBAC/B;iBACF;gBAQM,qCAAkB,GAAzB,UAA0B,MAAe;oBACvC,IAAI,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;oBACjD,IAAI,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC;oBAE1B,OAAO,CAAC,YAAY;wBAClB,YAAY,KAAK,GAAG,CAAC,IAAI;wBACzB,YAAY,KAAK,OAAO,CAAC;iBAC5B;gBACH,yBAAC;YAAD,CAhHA,CAAwC,WAAW,IAgHlD;YAED,IAAM,YAAY,GAAG,UAAC,EAAW,EAAE,IAAY,IAAK,OAAA,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,GAAA,CAAC;;;gBCpItCA,kCAAO;gBA8BzC,wBAAY,WAAwB;oBAApC,YACE,iBAAO,SAQR;oBANC,KAAI,CAAC,SAAS,GAAG,KAAK,CAAC;oBACvB,KAAI,CAAC,iBAAiB,GAAG,KAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAI,CAAC,CAAC;oBAEnD,KAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;oBAClC,KAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;oBAChC,KAAI,CAAC,WAAW,GAAG,WAAW,CAAC;;iBAChC;gBAOD,iCAAQ,GAAR,UAAS,OAAgB;oBACvB,IAAI,IAAI,CAAC,SAAS,EAAE;wBAClB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;qBACxD;oBAED,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC5B,IAAI,cAAc,GAAG,CAAC,CAAE,OAAe,CAAC,SAAS,CAAC;oBAElD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;oBACtB,IAAI,iBAAiB,GAAG,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBAG/F,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,iBAAiB,CAAC,IAAI,GAAG,GAAG,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;oBAE1F,IAAI,eAAe,GAAG,IAAI,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,UAAU,KAAK,KAAK,CAAC;oBACrF,IAAI,YAAY,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,iBAAiB,CAAC,SAAS,IAAI,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC;oBAG1G,IAAI,SAAiB,CAAC;oBACtB,IAAI,YAAY,EAAE;wBAChB,SAAS,GAAG,UAAU,CAAC;qBACxB;yBAAM,IAAI,eAAe,EAAE;wBAC1B,SAAS,GAAG,YAAY,CAAC;qBAC1B;oBAED,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;oBAI7D,IAAI,eAAe,IAAI,cAAc,EAAE;wBAErC,IAAI,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;wBAC9B,IAAI,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC;wBAIrE,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE;4BAC5B,IAAI,QAAQ,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;4BAC9D,SAAS,CAAC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC;4BAE/D,OAAO,IAAI,CAAC;yBAIb;6BAAM,IAAI,YAAY,IAAI,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE;4BACnD,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;4BAC1E,QAAQ,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;yBAC7E;qBACF;oBAED,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;wBAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;qBACvC;oBAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAEhC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE;wBAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;qBAC1B;iBACF;gBAKD,mCAAU,GAAV;oBACE,IAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC;oBACvC,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBAClD,QAAQ,CAAC,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;oBACpD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;oBACvB,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;iBAC/B;gBAMD,wCAAe,GAAf;oBACE,IAAI,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;oBAC9B,IAAI,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;oBAClF,OAAO,KAAG,MAAM,GAAG,IAAI,CAAC,IAAM,CAAC;iBAChC;gBASD,iCAAQ,GAAR,UAAS,QAAiB,EAAE,EAAsC;wBAAtC,4BAAsC,EAArC,eAAc,EAAd,mCAAc,EAAE,eAAe,EAAf,oCAAe;oBAC1D,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;oBAC7B,IAAI,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;wBAC1C,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC;wBACzB,OAAO,IAAI,CAAC;qBACb;oBAED,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;wBACnB,OAAO,KAAK,CAAC;qBACd;oBAED,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;oBAE7C,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,EAAE;wBAC1C,OAAO,KAAK,CAAC;qBACd;oBAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;oBAEzB,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;oBAG/B,IAAI,QAAQ,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE;wBAClC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;qBACxB;oBAGD,IAAI,IAAI,CAAC,aAAa,EAAE;wBACtB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;wBAC7B,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,cAAc,GAAG,WAAW,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;qBAC1E;yBAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE;wBAGhC,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;qBACzC;yBAAM;wBAGL,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;qBACtB;oBAED,IAAI,OAAO,EAAE;wBACX,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;qBAChC;oBAED,OAAO,IAAI,CAAC;iBACb;gBAKD,qCAAY,GAAZ;oBACE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;iBACrB;gBAKD,iCAAQ,GAAR,UAAS,KAAa;oBACpB,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;iBACnB;gBAOD,iCAAQ,GAAR,UAAS,GAAW,EAAE,KAAU;oBAC9B,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC5B,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;oBAC1C,IAAA,kBAA0C,EAAxC,sBAAQ,EAAE,kBAAM,EAAE,cAAsB,CAAC;oBAC/C,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;oBACnB,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,KAAG,QAAQ,GAAG,MAAM,GAAG,IAAM,CAAC,CAAC;iBACnE;gBAOD,iCAAQ,GAAR,UAAS,GAAW;oBAClB,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBAClD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;iBACnB;gBAMD,wCAAe,GAAf;oBACE,IAAI,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;oBACjD,IAAI,YAAY,KAAK,SAAS,EAAE;wBAC9B,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;wBACvC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;qBAC7C;oBACD,OAAO,YAAY,CAAC;iBACrB;gBAMD,2BAAE,GAAF,UAAG,QAAgB;oBACjB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;iBAC3B;gBAKD,iCAAQ,GAAR;oBACE,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;iBACrC;gBAKD,qCAAY,GAAZ,UAAa,QAAgB,EAAE,cAAwB;oBACrD,IAAI,OAAe,CAAC;oBAEpB,IAAI,CAAC,QAAQ,EAAE;wBACb,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,cAAc,EAAE;4BAClE,IAAI,UAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;4BAC7B,QAAQ,GAAG,UAAQ,CAAC,QAAQ,GAAG,UAAQ,CAAC,MAAM,CAAC;4BAC/C,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;4BAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gCAC9B,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;6BAC5C;yBACF;6BAAM;4BACL,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;yBAC5B;qBACF;oBAED,OAAO,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;iBAClD;gBAOD,kCAAS,GAAT;oBACE,IAAI,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;oBACpC,IAAI,OAAO,KAAK,IAAI,CAAC,QAAQ,EAAE;wBAC7B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;qBACnB;iBACF;gBAMD,iCAAQ,GAAR,UAAS,gBAAwB;oBAC/B,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;oBAEnE,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY;wBAC9B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC;wBACnC,KAAK,CAAC;iBACT;gBAjSM,qBAAM,GAAG,CAAC,WAAW,CAAC,CAAC;gBAkShC,qBAAC;aAAA,CApSmC,OAAO,IAoS1C;YAGD,IAAM,aAAa,GAAG,cAAc,CAAC;YAGrC,IAAM,YAAY,GAAG,YAAY,CAAC;YAGlC,IAAM,aAAa,GAAG,KAAK,CAAC;YAK5B,IAAM,WAAW,GAAG,8BAA8B,CAAC;YAInD,SAAS,UAAU,CAAC,SAAmB,EAAE,QAAgB,EAAE,OAAgB;gBACzE,IAAI,OAAO,EAAE;oBACX,IAAI,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;oBAC5D,SAAS,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC;iBAC1C;qBAAM;oBAEL,SAAS,CAAC,IAAI,GAAG,GAAG,GAAG,QAAQ,CAAC;iBACjC;YACH,CAAC;YAED,SAAS,YAAY,CAAC,QAAgB,EAAE,QAAgB,EAAE,IAAY;gBACpE,OAAU,QAAQ,UAAK,QAAQ,IAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE,CAAE,CAAC;YAC7D,CAAC;;qBCjUe,SAAS,CAAC,MAAc;gBAEtC,IAAM,OAAO,GAAG,MAAa,CAAC;gBAC9B,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;gBAC3C,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;YACrD,CAAC;;;;;;"} \ No newline at end of file diff --git a/dist/system/index.js b/dist/system/index.js deleted file mode 100644 index f3974ce..0000000 --- a/dist/system/index.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -System.register(['./aurelia-history-browser'], function (_export, _context) { - "use strict"; - - return { - setters: [function (_aureliaHistoryBrowser) { - var _exportObj = {}; - - for (var _key in _aureliaHistoryBrowser) { - if (_key !== "default" && _key !== "__esModule") _exportObj[_key] = _aureliaHistoryBrowser[_key]; - } - - _export(_exportObj); - }], - execute: function () {} - }; -}); \ No newline at end of file diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index f952b35..c9aecbb 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.3.2](https://github.com/aurelia/history-browser/compare/1.3.1...1.3.2) (2019-04-20) + + + ## [1.3.2](https://github.com/aurelia/history-browser/compare/1.3.0...1.3.2) (2019-03-27) diff --git a/src/browser-history.ts b/src/browser-history.ts index a265b7e..ddc3e68 100644 --- a/src/browser-history.ts +++ b/src/browser-history.ts @@ -12,8 +12,6 @@ export class BrowserHistory extends History { /**@internal */ _isActive: boolean; - /**@internal*/ - _checkUrlCallback: any; /**@internal*/ location: Location; /**@internal*/ @@ -39,7 +37,7 @@ export class BrowserHistory extends History { super(); this._isActive = false; - this._checkUrlCallback = this._checkUrl.bind(this); + this._checkUrl = this._checkUrl.bind(this); this.location = PLATFORM.location; this.history = PLATFORM.history; @@ -76,7 +74,7 @@ export class BrowserHistory extends History { eventName = 'hashchange'; } - PLATFORM.addEventListener(eventName, this._checkUrlCallback); + PLATFORM.addEventListener(eventName, this._checkUrl); // Determine if we need to change the base url, for a pushState link // opened by a non-pushState browser. @@ -116,7 +114,7 @@ export class BrowserHistory extends History { * Deactivates the history object. */ deactivate(): void { - const handler = this._checkUrlCallback; + const handler = this._checkUrl; PLATFORM.removeEventListener('popstate', handler); PLATFORM.removeEventListener('hashchange', handler); this._isActive = false; @@ -157,6 +155,8 @@ export class BrowserHistory extends History { return false; } + // caching fragment value to prevent triggering load same URL twice + // as this could potentially trigger hashchange or pushstate this.fragment = fragment; let url = this.root + fragment; @@ -271,7 +271,9 @@ export class BrowserHistory extends History { } } - return '/' + fragment.replace(routeStripper, ''); + // without decoding the fragment + // _loadUrl will be trigger twice if there are special character in the URL + return decodeURIComponent('/' + fragment.replace(routeStripper, '')); } /** @@ -281,6 +283,8 @@ export class BrowserHistory extends History { */ _checkUrl(): void { let current = this._getFragment(''); + // a guard to prevent triggering load same URL twice + // typically happens when calling navigate from router if (current !== this.fragment) { this._loadUrl(''); } diff --git a/test/history.spec.ts b/test/history.spec.ts index b69c011..b44990e 100644 --- a/test/history.spec.ts +++ b/test/history.spec.ts @@ -34,6 +34,34 @@ describe('browser history', () => { expect(bh._getFragment('#/admin/user/123 ')).toBe(expected); expect(bh._getFragment('#///admin/user/123')).toBe(expected); }); + + const testCases = [ + [encodeURIComponent('admin user 123'), '/admin user 123'], + [encodeURIComponent('ad"min user'), '/ad"min user'], + [encodeURIComponent('ad{min '), '/ad{min '], + ...['@', '!', '$', '%', '&', '^', '*', '(', ')', '[', ']', '\\', '|', '{', '}', ':', ';', '\'', ' ', ' ', ' ', '"', '<', '>', '~', '`', + ...[ + '( ͡° ͜ʖ ͡°)', + 'ʕ•ᴥ•ʔ', + '༼ つ ◕_◕ ༽つ', + '(ಥ﹏ಥ)', + 'ლ(ಠ益ಠლ)', + '◉_◉', + 'ಠ⌣ಠ', + 'ಠ~ಠ' + ] + ] + .map(specialChar => { + return [encodeURIComponent(`ad${specialChar}min/ad${specialChar}min`), `/ad${specialChar}min/ad${specialChar}min`]; + }) + ]; + + testCases.forEach(([input, output]) => { + it(`should decode fragment "${input}" correctly`, async () => { + let bh = new BrowserHistory(null); + expect(bh._getFragment(input)).toBe(output); + }); + }); }); describe('getAbsoluteRoot', () => {