From d57f830cd2e54778d5378baa5de91eb6fb5ea86a Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 7 Oct 2014 17:43:32 -0700 Subject: [PATCH] [changed] Public interface for Location objects Also, removed the Flux dispatcher. Fixes #363 --- modules/actions/LocationActions.js | 5 --- modules/dispatchers/LocationDispatcher.js | 18 -------- modules/locations/HashLocation.js | 31 ++++---------- modules/locations/HistoryLocation.js | 34 ++++----------- modules/locations/RefreshLocation.js | 18 +------- modules/mixins/LocationContext.js | 5 ++- modules/stores/PathStore.js | 51 ++++++++++++++--------- package.json | 1 - 8 files changed, 53 insertions(+), 110 deletions(-) delete mode 100644 modules/dispatchers/LocationDispatcher.js diff --git a/modules/actions/LocationActions.js b/modules/actions/LocationActions.js index 46a1be6634..68e512f769 100644 --- a/modules/actions/LocationActions.js +++ b/modules/actions/LocationActions.js @@ -3,11 +3,6 @@ */ var LocationActions = { - /** - * Indicates a location is being setup for the first time. - */ - SETUP: 'setup', - /** * Indicates a new location is being pushed to the history stack. */ diff --git a/modules/dispatchers/LocationDispatcher.js b/modules/dispatchers/LocationDispatcher.js deleted file mode 100644 index de4a9c62d5..0000000000 --- a/modules/dispatchers/LocationDispatcher.js +++ /dev/null @@ -1,18 +0,0 @@ -var copyProperties = require('react/lib/copyProperties'); -var Dispatcher = require('flux').Dispatcher; - -/** - * Dispatches actions that modify the URL. - */ -var LocationDispatcher = copyProperties(new Dispatcher, { - - handleViewAction: function (action) { - this.dispatch({ - source: 'VIEW_ACTION', - action: action - }); - } - -}); - -module.exports = LocationDispatcher; diff --git a/modules/locations/HashLocation.js b/modules/locations/HashLocation.js index a783f58c44..7321fc36b7 100644 --- a/modules/locations/HashLocation.js +++ b/modules/locations/HashLocation.js @@ -1,7 +1,4 @@ -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; var LocationActions = require('../actions/LocationActions'); -var LocationDispatcher = require('../dispatchers/LocationDispatcher'); var getWindowPath = require('../utils/getWindowPath'); function getHashPath() { @@ -21,11 +18,13 @@ function ensureSlash() { return false; } +var _onChange; + function onHashChange() { if (ensureSlash()) { var path = getHashPath(); - LocationDispatcher.handleViewAction({ + _onChange({ // If we don't have an _actionType then all we know is the hash // changed. It was probably caused by the user clicking the Back // button, but may have also been the Forward button or manual @@ -38,36 +37,22 @@ function onHashChange() { } } -var _isSetup = false; - /** * A Location that uses `window.location.hash`. */ var HashLocation = { - setup: function () { - if (_isSetup) - return; - - invariant( - canUseDOM, - 'You cannot use HashLocation in an environment with no DOM' - ); + setup: function (onChange) { + _onChange = onChange; + // Do this BEFORE listening for hashchange. ensureSlash(); - LocationDispatcher.handleViewAction({ - type: LocationActions.SETUP, - path: getHashPath() - }); - if (window.addEventListener) { window.addEventListener('hashchange', onHashChange, false); } else { window.attachEvent('onhashchange', onHashChange); } - - _isSetup = true; }, teardown: function () { @@ -76,8 +61,6 @@ var HashLocation = { } else { window.detachEvent('onhashchange', onHashChange); } - - _isSetup = false; }, push: function (path) { @@ -95,6 +78,8 @@ var HashLocation = { window.history.back(); }, + getCurrentPath: getHashPath, + toString: function () { return ''; } diff --git a/modules/locations/HistoryLocation.js b/modules/locations/HistoryLocation.js index 7e4b5fbe0a..eabf97bd6d 100644 --- a/modules/locations/HistoryLocation.js +++ b/modules/locations/HistoryLocation.js @@ -1,44 +1,28 @@ -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; var LocationActions = require('../actions/LocationActions'); -var LocationDispatcher = require('../dispatchers/LocationDispatcher'); var getWindowPath = require('../utils/getWindowPath'); +var _onChange; + function onPopState() { - LocationDispatcher.handleViewAction({ + _onChange({ type: LocationActions.POP, path: getWindowPath() }); } -var _isSetup = false; - /** * A Location that uses HTML5 history. */ var HistoryLocation = { - setup: function () { - if (_isSetup) - return; - - invariant( - canUseDOM, - 'You cannot use HistoryLocation in an environment with no DOM' - ); - - LocationDispatcher.handleViewAction({ - type: LocationActions.SETUP, - path: getWindowPath() - }); + setup: function (onChange) { + _onChange = onChange; if (window.addEventListener) { window.addEventListener('popstate', onPopState, false); } else { window.attachEvent('popstate', onPopState); } - - _isSetup = true; }, teardown: function () { @@ -47,14 +31,12 @@ var HistoryLocation = { } else { window.detachEvent('popstate', onPopState); } - - _isSetup = false; }, push: function (path) { window.history.pushState({ path: path }, '', path); - LocationDispatcher.handleViewAction({ + _onChange({ type: LocationActions.PUSH, path: getWindowPath() }); @@ -63,7 +45,7 @@ var HistoryLocation = { replace: function (path) { window.history.replaceState({ path: path }, '', path); - LocationDispatcher.handleViewAction({ + _onChange({ type: LocationActions.REPLACE, path: getWindowPath() }); @@ -73,6 +55,8 @@ var HistoryLocation = { window.history.back(); }, + getCurrentPath: getWindowPath, + toString: function () { return ''; } diff --git a/modules/locations/RefreshLocation.js b/modules/locations/RefreshLocation.js index 6e806639c0..ece68917b6 100644 --- a/modules/locations/RefreshLocation.js +++ b/modules/locations/RefreshLocation.js @@ -1,7 +1,3 @@ -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; -var LocationActions = require('../actions/LocationActions'); -var LocationDispatcher = require('../dispatchers/LocationDispatcher'); var getWindowPath = require('../utils/getWindowPath'); /** @@ -11,18 +7,6 @@ var getWindowPath = require('../utils/getWindowPath'); */ var RefreshLocation = { - setup: function () { - invariant( - canUseDOM, - 'You cannot use RefreshLocation in an environment with no DOM' - ); - - LocationDispatcher.handleViewAction({ - type: LocationActions.SETUP, - path: getWindowPath() - }); - }, - push: function (path) { window.location = path; }, @@ -35,6 +19,8 @@ var RefreshLocation = { window.history.back(); }, + getCurrentPath: getWindowPath, + toString: function () { return ''; } diff --git a/modules/mixins/LocationContext.js b/modules/mixins/LocationContext.js index 847f2bc281..81c93ec43a 100644 --- a/modules/mixins/LocationContext.js +++ b/modules/mixins/LocationContext.js @@ -4,6 +4,7 @@ var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; var HashLocation = require('../locations/HashLocation'); var HistoryLocation = require('../locations/HistoryLocation'); var RefreshLocation = require('../locations/RefreshLocation'); +var PathStore = require('../stores/PathStore'); var supportsHistory = require('../utils/supportsHistory'); /** @@ -60,8 +61,8 @@ var LocationContext = { 'Cannot use location without a DOM' ); - if (location && location.setup) - location.setup(); + if (location) + PathStore.useLocation(location); }, /** diff --git a/modules/stores/PathStore.js b/modules/stores/PathStore.js index 5bce5baa4e..489ca0baa7 100644 --- a/modules/stores/PathStore.js +++ b/modules/stores/PathStore.js @@ -1,6 +1,6 @@ +var invariant = require('react/lib/invariant'); var EventEmitter = require('events').EventEmitter; var LocationActions = require('../actions/LocationActions'); -var LocationDispatcher = require('../dispatchers/LocationDispatcher'); var CHANGE_EVENT = 'change'; var _events = new EventEmitter; @@ -9,7 +9,15 @@ function notifyChange() { _events.emit(CHANGE_EVENT); } -var _currentPath, _currentActionType; +var _currentLocation, _currentPath, _currentActionType; + +function handleLocationChangeAction(action) { + if (_currentPath !== action.path) { + _currentPath = action.path; + _currentActionType = action.type; + notifyChange(); + } +} /** * The PathStore keeps track of the current URL path. @@ -28,6 +36,26 @@ var PathStore = { _events.removeAllListeners(CHANGE_EVENT); }, + /** + * Setup the PathStore to use the given location. + */ + useLocation: function (location) { + invariant( + _currentLocation == null || _currentLocation === location, + 'You cannot use %s and %s on the same page', + _currentLocation, location + ); + + if (_currentLocation !== location) { + if (location.setup) + location.setup(handleLocationChangeAction); + + _currentPath = location.getCurrentPath(); + } + + _currentLocation = location; + }, + /** * Returns the current URL path. */ @@ -40,24 +68,7 @@ var PathStore = { */ getCurrentActionType: function () { return _currentActionType; - }, - - dispatchToken: LocationDispatcher.register(function (payload) { - var action = payload.action; - - switch (action.type) { - case LocationActions.SETUP: - case LocationActions.PUSH: - case LocationActions.REPLACE: - case LocationActions.POP: - if (_currentPath !== action.path) { - _currentPath = action.path; - _currentActionType = action.type; - notifyChange(); - } - break; - } - }) + } }; diff --git a/package.json b/package.json index cf8c9ea37f..dbf8a31b66 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ }, "dependencies": { "events": "1.0.1", - "flux": "2.0.1", "qs": "2.2.2", "when": "3.4.6" },