-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
/
HashLocation.js
121 lines (94 loc) · 2.63 KB
/
HashLocation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
var LocationActions = require('../actions/LocationActions');
var History = require('../History');
/**
* Returns the current URL path from the `hash` portion of the URL, including
* query string.
*/
function getHashPath() {
return decodeURI(
// We can't use window.location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
window.location.href.split('#')[1] || ''
);
}
var _actionType;
function ensureSlash() {
var path = getHashPath();
if (path.charAt(0) === '/')
return true;
HashLocation.replace('/' + path);
return false;
}
var _changeListeners = [];
function notifyChange(type) {
if (type === LocationActions.PUSH)
History.length += 1;
var change = {
path: getHashPath(),
type: type
};
_changeListeners.forEach(function (listener) {
listener(change);
});
}
var _isListening = false;
function onHashChange() {
if (ensureSlash()) {
// 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
// manipulation. So just guess 'pop'.
notifyChange(_actionType || LocationActions.POP);
_actionType = null;
}
}
/**
* A Location that uses `window.location.hash`.
*/
var HashLocation = {
addChangeListener: function (listener) {
_changeListeners.push(listener);
// Do this BEFORE listening for hashchange.
ensureSlash();
if (!_isListening) {
if (window.addEventListener) {
window.addEventListener('hashchange', onHashChange, false);
} else {
window.attachEvent('onhashchange', onHashChange);
}
_isListening = true;
}
},
removeChangeListener: function(listener) {
_changeListeners = _changeListeners.filter(function (l) {
return l !== listener;
});
if (_changeListeners.length === 0) {
if (window.removeEventListener) {
window.removeEventListener('hashchange', onHashChange, false);
} else {
window.removeEvent('onhashchange', onHashChange);
}
_isListening = false;
}
},
push: function (path) {
_actionType = LocationActions.PUSH;
window.location.hash = encodeURI(path);
},
replace: function (path) {
_actionType = LocationActions.REPLACE;
window.location.replace(
window.location.pathname + window.location.search + '#' + encodeURI(path)
);
},
pop: function () {
_actionType = LocationActions.POP;
History.back();
},
getCurrentPath: getHashPath,
toString: function () {
return '<HashLocation>';
}
};
module.exports = HashLocation;