UNPKG

react-router

Version:

A complete routing library for React.js

209 lines (158 loc) • 8.11 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 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) subClass.__proto__ = superClass; } var _warning = require('warning'); var _warning2 = _interopRequireDefault(_warning); var _DOMHistory2 = require('./DOMHistory'); var _DOMHistory3 = _interopRequireDefault(_DOMHistory2); var _NavigationTypes = require('./NavigationTypes'); var _NavigationTypes2 = _interopRequireDefault(_NavigationTypes); var _DOMUtils = require('./DOMUtils'); var _URLUtils = require('./URLUtils'); var DefaultQueryKey = '_qk'; function ensureSlash() { var path = (0, _DOMUtils.getHashPath)(); if ((0, _URLUtils.isAbsolutePath)(path)) return true; (0, _DOMUtils.replaceHashPath)('/' + path); return false; } function addQueryStringValueToPath(path, key, value) { return path + (path.indexOf('?') === -1 ? '?' : '&') + ('' + key + '=' + value); } function getQueryStringValueFromPath(path, key) { var match = path.match(new RegExp('\\?.*?\\b' + key + '=(.+?)\\b')); return match && match[1]; } function saveState(path, queryKey, state) { window.sessionStorage.setItem(state.key, JSON.stringify(state)); return addQueryStringValueToPath(path, queryKey, state.key); } function readState(path, queryKey) { var sessionKey = getQueryStringValueFromPath(path, queryKey); var json = sessionKey && window.sessionStorage.getItem(sessionKey); if (json) { try { return JSON.parse(json); } catch (error) {} } return null; } function updateCurrentState(queryKey, extraState) { var path = (0, _DOMUtils.getHashPath)(); var state = readState(path, queryKey); if (state) saveState(path, queryKey, _extends(state, extraState)); } /** * A history implementation for DOM environments that uses window.location.hash * to store the current path. This is essentially a hack for older browsers that * do not support the HTML5 history API (IE <= 9). * * Support for persistence of state across page refreshes is provided using a * combination of a URL query string parameter and DOM storage. However, this * support is not enabled by default. In order to use it, create your own * HashHistory, like this: * * import { HashHistory } from 'react-router/lib/HashHistory'; * var StatefulHashHistory = new HashHistory({ queryKey: '_key' }); * React.render(<Router history={StatefulHashHistory} .../>, ...); */ var HashHistory = (function (_DOMHistory) { function HashHistory() { var options = arguments[0] === undefined ? {} : arguments[0]; _classCallCheck(this, HashHistory); _get(Object.getPrototypeOf(HashHistory.prototype), 'constructor', this).call(this, options); this.handleHashChange = this.handleHashChange.bind(this); this.queryKey = options.queryKey; if (typeof this.queryKey !== 'string') this.queryKey = this.queryKey ? DefaultQueryKey : null; } _inherits(HashHistory, _DOMHistory); _createClass(HashHistory, [{ key: '_updateLocation', value: function _updateLocation(navigationType) { var path = (0, _DOMUtils.getHashPath)(); var state = this.queryKey ? readState(path, this.queryKey) : null; this.location = this.createLocation(path, state, navigationType); } }, { key: 'setup', value: function setup() { if (this.location == null) { ensureSlash(); this._updateLocation(); } } }, { key: 'handleHashChange', value: function handleHashChange() { if (!ensureSlash()) return; if (this._ignoreNextHashChange) { this._ignoreNextHashChange = false; } else { this._updateLocation(_NavigationTypes2['default'].POP); this._notifyChange(); } } }, { key: 'addChangeListener', value: function addChangeListener(listener) { _get(Object.getPrototypeOf(HashHistory.prototype), 'addChangeListener', this).call(this, listener); if (this.changeListeners.length === 1) { if (window.addEventListener) { window.addEventListener('hashchange', this.handleHashChange, false); } else { window.attachEvent('onhashchange', this.handleHashChange); } } } }, { key: 'removeChangeListener', value: function removeChangeListener(listener) { _get(Object.getPrototypeOf(HashHistory.prototype), 'removeChangeListener', this).call(this, listener); if (this.changeListeners.length === 0) { if (window.removeEventListener) { window.removeEventListener('hashchange', this.handleHashChange, false); } else { window.removeEvent('onhashchange', this.handleHashChange); } } } }, { key: 'pushState', value: function pushState(state, path) { (0, _warning2['default'])(this.queryKey || state == null, 'HashHistory needs a queryKey in order to persist state'); if (this.queryKey) updateCurrentState(this.queryKey, this.getScrollPosition()); state = this._createState(state); if (this.queryKey) path = saveState(path, this.queryKey, state); this._ignoreNextHashChange = true; window.location.hash = path; this.location = this.createLocation(path, state, _NavigationTypes2['default'].PUSH); this._notifyChange(); } }, { key: 'replaceState', value: function replaceState(state, path) { state = this._createState(state); if (this.queryKey) path = saveState(path, this.queryKey, state); this._ignoreNextHashChange = true; (0, _DOMUtils.replaceHashPath)(path); this.location = this.createLocation(path, state, _NavigationTypes2['default'].REPLACE); this._notifyChange(); } }, { key: 'makeHref', value: function makeHref(pathname, query) { return '#' + _get(Object.getPrototypeOf(HashHistory.prototype), 'makeHref', this).call(this, pathname, query); } }]); return HashHistory; })(_DOMHistory3['default']); exports.HashHistory = HashHistory; exports['default'] = new HashHistory(); // Ignore invalid JSON in session storage.