UNPKG

react-crossroads

Version:

Client side router for web applications built with React and utilizing the Flux architecture. The backing routing engine is CrossroadsJs.

203 lines (173 loc) 6.58 kB
var BLOCKED, EventEmitter, LocationStore, Logger, RouterConstants, UNBLOCKED, _, _isExpectedEvent, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; RouterConstants = require('../constants/RouterConstants'); Logger = require('../utils/logger'); EventEmitter = require('events').EventEmitter; _ = require('lodash'); BLOCKED = true; UNBLOCKED = false; _isExpectedEvent = function(action, path) { if (action.actionType === RouterConstants.LOCATION_GOBACK) { return true; } else { return path === action.path; } }; LocationStore = (function(_super) { __extends(LocationStore, _super); function LocationStore(dispatcher, context) { this.context = context; this._locationChanged = __bind(this._locationChanged, this); this.handler = __bind(this.handler, this); this.dispatchToken = dispatcher.register(this.handler); this._become(UNBLOCKED); this._currentLocationChanged = this._locationChangedDefault; this._queue = []; this._changing = false; this._blockedIds = {}; } LocationStore.prototype.isBlocked = function() { return _.any(_.values(this._blockedIds)); }; LocationStore.prototype.isIdBlocked = function(id) { return this._blockedIds[id] || false; }; LocationStore.prototype.getCurrentPath = function() { return this._location.getCurrentPath(); }; LocationStore.prototype.pathToHref = function(path) { return this._location.pathToHref(path); }; LocationStore.prototype.handler = function(payload) { var action; if (payload.source !== RouterConstants.ROUTER_ACTION) { return; } action = payload.action; this._queue.push(action); if (!this._changing) { return this._processQueue(); } }; LocationStore.prototype._blockedHandler = function(action) { switch (action.actionType) { case RouterConstants.LOCATION_BLOCK: Logger.development.warn('Location store is already blocked'); break; case RouterConstants.LOCATION_UNBLOCK: if (this._blockedIds[action.blockId] != null) { delete this._blockedIds[action.blockId]; } if (!this.isBlocked()) { this._become(UNBLOCKED); } this._emitChange(); break; case RouterConstants.LOCATION_CHANGE: case RouterConstants.LOCATION_REPLACE: case RouterConstants.LOCATION_GOBACK: Logger.development.warn("Location store is blocked: " + (JSON.stringify(action))); } return true; }; LocationStore.prototype._unblockedHandler = function(action) { switch (action.actionType) { case RouterConstants.LOCATION_BLOCK: if (this._blockedIds[action.blockId]) { console.error("Router has already been blocked for id `" + action.blockId + "`"); } this._blockedIds[action.blockId] = true; this._become(BLOCKED); this._emitChange(); return true; case RouterConstants.LOCATION_UNBLOCK: Logger.development.warn('Location store is already unblocked'); return true; case RouterConstants.LOCATION_CHANGE: if (action.fromLocationEvent) { this._emitChange(); return true; } else { this._changeLocation((function(_this) { return function() { return _this._location.push(action.path); }; })(this)); return false; } break; case RouterConstants.LOCATION_REPLACE: this._changeLocation((function(_this) { return function() { return _this._location.replace(action.path); }; })(this)); return false; case RouterConstants.LOCATION_GOBACK: this._changeLocation((function(_this) { return function() { return _this._location.pop(); }; })(this)); return false; case RouterConstants.LOCATION_ATTEMPT: throw new Error('Location store is not blocked!'); } }; LocationStore.prototype._processQueue = function() { var action, queueTail, _ref; _ref = this._queue, action = _ref[0], queueTail = 2 <= _ref.length ? __slice.call(_ref, 1) : []; if (action && this._currentHandler(action)) { this._queue = queueTail; return this._processQueue(); } }; LocationStore.prototype._changeLocation = function(func) { this._changing = true; this._currentLocationChanged = this._locationChangedExpected; return func(); }; LocationStore.prototype._become = function(blocked) { return this._currentHandler = blocked ? this._blockedHandler : this._unblockedHandler; }; LocationStore.prototype._emitChange = function() { return this.emit(RouterConstants.CHANGE_EVENT); }; LocationStore.prototype._locationChanged = function() { return this._currentLocationChanged(this._location.getCurrentPath()); }; LocationStore.prototype._locationChangedExpected = function(path) { if (!_isExpectedEvent(this._queue[0], path)) { return this._locationChangedDefault(path); } else { Logger.debug.log("Location changed by react-crossroads [path: " + path + "]"); this._changing = false; this._emitChange(); this._queue.shift(); this._currentLocationChanged = this._locationChangedDefault; return this._processQueue(); } }; LocationStore.prototype._locationChangedDefault = function(path) { Logger.debug.log("Location changed by user [path: " + path + "]"); return this.context.actions.updateLocation(path); }; LocationStore.prototype.setup = function(location, initialPath) { if (this._location != null) { Location.development.warn('Location has already been setup'); } this._location = location; return this._location.setup(this._locationChanged, initialPath); }; LocationStore.prototype.addChangeListener = function(listener) { return this.on(RouterConstants.CHANGE_EVENT, listener); }; LocationStore.prototype.removeChangeListener = function(listener) { return this.removeListener(RouterConstants.CHANGE_EVENT, listener); }; return LocationStore; })(EventEmitter); module.exports = LocationStore;