-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhashrouter.class.js
152 lines (138 loc) · 4.35 KB
/
hashrouter.class.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
* Simple access to the Hashbang with listeners, filters and query string
* deconstruction.
*/
class HashRouter {
constructor() {
if (HashRouter.instance) {
return HashRouter.instance;
}
this.currentHash = HashRouter.toObject(window.location.hash);
this.filterID = -1;
this.filters = [];
this.hook();
HashRouter.instance = this;
}
/**
* Changes the hashbang.
* @param {String|Object} to The new value to change to. If string,
* replaces whole hash!
* @param {Function} cb If provided, calls on complete.
*/
change(to, cb) {
let key;
if (typeof to == 'string') {
window.location.hash = to;
this.currentHash = HashRouter.toObject(to);
console.warn('HashRouter: Hash overwritten', to);
} else if (typeof to == 'object') {
for (key in to) {
this.currentHash[key] = to[key];
}
if (Object.keys(this.currentHash).length > 0) {
window.location.hash = $.param(this.currentHash);
}
}
}
/**
* Clears filter by ID or clears all filters if no filterID provided.
* @param {String?} filterID ID to clear.
*/
clear(filterID) {
if (this.filters.hasOwnProperty(filterID)) {
delete this.filters[filterID];
} else if (!filterID) {
this.filters = {};
console.warn('HashRouter: Clearing all filters');
}
}
/**
* Checks a filter against the current hashbang. If filter is string,
* checks against whole hashbang. If function, passes hashbang into that
* function. If Object, checks each key against filter. If Object key
* value is function, passes hashbang key value as parameter into that
* function.
* @param {String|Object|Function} filter The filter to check against the
* URL hash.
* @return {Boolean} True if the hash passes the filters.
*/
check(filter) {
let key;
if (typeof filter == 'string') {
return window.location.href.substr(1) == filter;
} else if (typeof filter == 'function') {
return filter(window.location.href.substr(1));
} else {
for (key in filter) {
if (this.currentHash[key] != filter[key]) {
return false;
}
}
}
return true;
}
/**
* Hooks a listsner to 'hashchange' event.
*/
hook() {
let fn = (e) => {
let filterID;
if (window.location.hash) {
this.currentHash = HashRouter.toObject(window.location.hash);
}
for (filterID in this.filters) {
if (this.check(this.filters[filterID][0])) {
this.filters[filterID][1](this.currentHash);
}
}
}
window.addEventListener('hashchange', fn);
window.addEventListener('load', fn);
}
/**
* Creates a filter with a callback. Returns the filter ID.
* @param {String|Object|Function} filter The filter to add.
* @param {Function} cb Function called when filter passes.
* @return {String} Filter ID, used for clearing filter.
*/
on(filter, cb) {
this.filters[++this.filterID] = [filter, cb];
return this.filterID;
}
/**
* Helper function converts hash into Object.
* @param {String?} A string that defaults to the hash.
* @return {Object} A map of the hash.
*/
static toObject(str) {
return (str.length == 0) ? {} : (str || window.location.hash)
.replace(/(^\#)/,'').split("&")
.map(function(n){return n = n.split("="),this[n[0]] = n[1],this}
.bind({}))[0];
}
}
// fallback
(function(window) {
// exit if the browser implements that event
if ( "onhashchange" in window.document.body ) { return; }
var location = window.location,
oldURL = location.href,
oldHash = location.hash;
// check the location hash on a 100ms interval
setInterval(function() {
var newURL = location.href,
newHash = location.hash;
// if the hash has changed and a handler has been bound...
if ( newHash != oldHash && typeof window.onhashchange === "function" ) {
// execute the handler
window.onhashchange({
type: "hashchange",
oldURL: oldURL,
newURL: newURL
});
oldURL = newURL;
oldHash = newHash;
}
}, 100);
})(window);
var $hashRouter = new HashRouter();