@ouroboros/browser 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/hash.d.ts +4 -16
- package/hash.js +74 -69
- package/hash.ts +98 -83
- package/package.json +1 -1
package/hash.d.ts
CHANGED
|
@@ -7,18 +7,7 @@
|
|
|
7
7
|
* @copyright Ouroboros Coding Inc.
|
|
8
8
|
* @created 2018-12-09
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Init
|
|
13
|
-
*
|
|
14
|
-
* Initialises the internal hash by fetching and parsing the current
|
|
15
|
-
* location hash
|
|
16
|
-
*
|
|
17
|
-
* @name init
|
|
18
|
-
* @access public
|
|
19
|
-
* @return {void}
|
|
20
|
-
*/
|
|
21
|
-
declare function init(): void;
|
|
10
|
+
import { SubscribeCallback, SubscribeReturn } from '@ouroboros/subscribe';
|
|
22
11
|
/**
|
|
23
12
|
* Get
|
|
24
13
|
*
|
|
@@ -55,11 +44,11 @@ declare function set(name: string | object, value?: string): void;
|
|
|
55
44
|
* @param {function} callback The function to call when the value changes
|
|
56
45
|
* @return {void}
|
|
57
46
|
*/
|
|
58
|
-
declare function subscribe(name: string, callback:
|
|
47
|
+
declare function subscribe(name: string, callback: SubscribeCallback): SubscribeReturn;
|
|
59
48
|
/**
|
|
60
49
|
* Unsubscribe
|
|
61
50
|
*
|
|
62
|
-
* Removes a callback from the
|
|
51
|
+
* Removes a callback from the oSubscribe
|
|
63
52
|
*
|
|
64
53
|
* @name unsubscribe
|
|
65
54
|
* @access public
|
|
@@ -67,9 +56,8 @@ declare function subscribe(name: string, callback: Callback): void;
|
|
|
67
56
|
* @param {function} callback The callback to remove
|
|
68
57
|
* @return {void}
|
|
69
58
|
*/
|
|
70
|
-
declare function unsubscribe(name: string, callback:
|
|
59
|
+
declare function unsubscribe(name: string, callback: SubscribeCallback): void;
|
|
71
60
|
declare const hash: {
|
|
72
|
-
init: typeof init;
|
|
73
61
|
get: typeof get;
|
|
74
62
|
set: typeof set;
|
|
75
63
|
subscribe: typeof subscribe;
|
package/hash.js
CHANGED
|
@@ -7,63 +7,56 @@
|
|
|
7
7
|
* @copyright Ouroboros Coding Inc.
|
|
8
8
|
* @created 2018-12-09
|
|
9
9
|
*/
|
|
10
|
-
//
|
|
11
|
-
import
|
|
10
|
+
// Ouroboros modules
|
|
11
|
+
import Subscribe from '@ouroboros/subscribe';
|
|
12
12
|
import { empty, isObject, parseQuery } from '@ouroboros/tools';
|
|
13
13
|
// name regex
|
|
14
14
|
const nameRE = /^[a-zA-Z_]+$/;
|
|
15
|
-
//
|
|
16
|
-
const
|
|
17
|
-
//
|
|
18
|
-
let dHash =
|
|
15
|
+
// Subscribers by name
|
|
16
|
+
const oSubscribe = {};
|
|
17
|
+
// Hash values by name (only null for init)
|
|
18
|
+
let dHash = null;
|
|
19
|
+
/**
|
|
20
|
+
* Init
|
|
21
|
+
*
|
|
22
|
+
* Only called once
|
|
23
|
+
*/
|
|
24
|
+
if (dHash === null) {
|
|
25
|
+
// Track changes
|
|
26
|
+
window.addEventListener("hashchange", hashChanged);
|
|
27
|
+
// Parse the current location hash
|
|
28
|
+
dHash = parseQuery(window.location.hash.substring(1));
|
|
29
|
+
}
|
|
19
30
|
/**
|
|
20
31
|
* Hash Changed
|
|
21
32
|
*
|
|
22
33
|
* Called when the location hash has been altered, notifies any watchers of
|
|
23
34
|
* hash values changing
|
|
24
35
|
*
|
|
25
|
-
* @name
|
|
36
|
+
* @name hashChanged
|
|
26
37
|
* @access private
|
|
27
38
|
* @return {void}
|
|
28
39
|
*/
|
|
29
|
-
function
|
|
40
|
+
function hashChanged() {
|
|
30
41
|
// Store the current hash
|
|
31
|
-
const old =
|
|
42
|
+
const old = { ...dHash };
|
|
32
43
|
// Re-parse the current location hash
|
|
33
44
|
dHash = parseQuery(window.location.hash.substring(1));
|
|
34
|
-
// If there are
|
|
35
|
-
if (!empty(
|
|
36
|
-
// Check each
|
|
37
|
-
for (const name
|
|
38
|
-
// If the value
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
f(dHash[name] || null);
|
|
46
|
-
}
|
|
45
|
+
// If there are oSubscribe
|
|
46
|
+
if (!empty(oSubscribe)) {
|
|
47
|
+
// Check each subscribe instance
|
|
48
|
+
for (const name of Object.keys(oSubscribe)) {
|
|
49
|
+
// If the value no longer exists, set it to null
|
|
50
|
+
if (name in old && !(name in dHash)) {
|
|
51
|
+
oSubscribe[name].set(null);
|
|
52
|
+
}
|
|
53
|
+
// Else, the value is new, or altered, so use the new value
|
|
54
|
+
else {
|
|
55
|
+
oSubscribe[name].set(dHash[name]);
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
58
|
}
|
|
50
59
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Init
|
|
53
|
-
*
|
|
54
|
-
* Initialises the internal hash by fetching and parsing the current
|
|
55
|
-
* location hash
|
|
56
|
-
*
|
|
57
|
-
* @name init
|
|
58
|
-
* @access public
|
|
59
|
-
* @return {void}
|
|
60
|
-
*/
|
|
61
|
-
function init() {
|
|
62
|
-
// Track changes
|
|
63
|
-
window.addEventListener("hashchange", _hashChanged);
|
|
64
|
-
// Parse the current location hash
|
|
65
|
-
dHash = parseQuery(window.location.hash.substring(1));
|
|
66
|
-
}
|
|
67
60
|
/**
|
|
68
61
|
* Get
|
|
69
62
|
*
|
|
@@ -90,6 +83,20 @@ function get(name, defaultReturn) {
|
|
|
90
83
|
return defaultReturn === undefined ? null : defaultReturn;
|
|
91
84
|
}
|
|
92
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Reset
|
|
88
|
+
*
|
|
89
|
+
* Notifies all existing subscriptions that all data went away
|
|
90
|
+
*
|
|
91
|
+
* @name reset
|
|
92
|
+
* @access private
|
|
93
|
+
*/
|
|
94
|
+
function reset() {
|
|
95
|
+
// Go through each subscribe instance
|
|
96
|
+
for (const name of Object.keys(oSubscribe)) {
|
|
97
|
+
oSubscribe[name].set(null);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
93
100
|
/**
|
|
94
101
|
* Set
|
|
95
102
|
*
|
|
@@ -111,7 +118,7 @@ function set(name, value) {
|
|
|
111
118
|
name = { [name]: value };
|
|
112
119
|
}
|
|
113
120
|
// Make a copy of the current hash
|
|
114
|
-
const copy =
|
|
121
|
+
const copy = { ...dHash };
|
|
115
122
|
// Go through each name
|
|
116
123
|
for (const n of Object.keys(name)) {
|
|
117
124
|
// If the name is invalid
|
|
@@ -131,10 +138,24 @@ function set(name, value) {
|
|
|
131
138
|
const temp = [];
|
|
132
139
|
// Go through each name
|
|
133
140
|
for (const k of Object.keys(copy)) {
|
|
134
|
-
temp.push(k + '=' + copy[k]);
|
|
141
|
+
temp.push(copy[k] === '' ? k : (k + '=' + copy[k]));
|
|
142
|
+
}
|
|
143
|
+
// If we have none
|
|
144
|
+
if (temp.length === 0) {
|
|
145
|
+
// If we can use pushState
|
|
146
|
+
if ('pushState' in history) {
|
|
147
|
+
history.pushState('', document.title, window.location.pathname + window.location.search);
|
|
148
|
+
reset();
|
|
149
|
+
}
|
|
150
|
+
// Else, we can't remove the '#', but clear the rest regardless
|
|
151
|
+
else {
|
|
152
|
+
window.location.hash = '';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Else, reset the window location hash
|
|
156
|
+
else {
|
|
157
|
+
window.location.hash = temp.join('&');
|
|
135
158
|
}
|
|
136
|
-
// Reset the window location hash
|
|
137
|
-
window.location.hash = temp.join('&');
|
|
138
159
|
}
|
|
139
160
|
/**
|
|
140
161
|
* Subscribe
|
|
@@ -149,27 +170,18 @@ function set(name, value) {
|
|
|
149
170
|
* @return {void}
|
|
150
171
|
*/
|
|
151
172
|
function subscribe(name, callback) {
|
|
152
|
-
// If we already have the name
|
|
153
|
-
if (name in
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
// If we already have the callback there's no need to store it
|
|
157
|
-
if (f === callback) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
173
|
+
// If we don't already have the name
|
|
174
|
+
if (!(name in oSubscribe)) {
|
|
175
|
+
// Create a new subscribe instance
|
|
176
|
+
oSubscribe[name] = new Subscribe(name in dHash ? dHash[name] : null);
|
|
161
177
|
}
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
dCallbacks[name] = [];
|
|
165
|
-
}
|
|
166
|
-
// Add the callback to the dCallbacks
|
|
167
|
-
dCallbacks[name].push(callback);
|
|
178
|
+
// Add the callback and return
|
|
179
|
+
return oSubscribe[name].subscribe(callback);
|
|
168
180
|
}
|
|
169
181
|
/**
|
|
170
182
|
* Unsubscribe
|
|
171
183
|
*
|
|
172
|
-
* Removes a callback from the
|
|
184
|
+
* Removes a callback from the oSubscribe
|
|
173
185
|
*
|
|
174
186
|
* @name unsubscribe
|
|
175
187
|
* @access public
|
|
@@ -179,18 +191,11 @@ function subscribe(name, callback) {
|
|
|
179
191
|
*/
|
|
180
192
|
function unsubscribe(name, callback) {
|
|
181
193
|
// If we have the name
|
|
182
|
-
if (name in
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
// If we find the callback
|
|
186
|
-
if (dCallbacks[name][i] === callback) {
|
|
187
|
-
// Remove it
|
|
188
|
-
dCallbacks[name].splice(i, 1);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
194
|
+
if (name in oSubscribe) {
|
|
195
|
+
// Attempt to unsubscribe
|
|
196
|
+
oSubscribe[name].unsubscribe(callback);
|
|
192
197
|
}
|
|
193
198
|
}
|
|
194
199
|
// Default export
|
|
195
|
-
const hash = {
|
|
200
|
+
const hash = { get, set, subscribe, unsubscribe };
|
|
196
201
|
export default hash;
|
package/hash.ts
CHANGED
|
@@ -8,21 +8,38 @@
|
|
|
8
8
|
* @created 2018-12-09
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
import
|
|
11
|
+
// Ouroboros modules
|
|
12
|
+
import Subscribe, {
|
|
13
|
+
SubscribeCallback,
|
|
14
|
+
SubscribeReturn
|
|
15
|
+
} from '@ouroboros/subscribe';
|
|
13
16
|
import { empty, isObject, parseQuery } from '@ouroboros/tools';
|
|
14
17
|
|
|
15
|
-
//
|
|
16
|
-
type
|
|
18
|
+
// Type
|
|
19
|
+
type HashType = Record<string, string>;
|
|
17
20
|
|
|
18
21
|
// name regex
|
|
19
22
|
const nameRE = /^[a-zA-Z_]+$/;
|
|
20
23
|
|
|
21
|
-
//
|
|
22
|
-
const
|
|
24
|
+
// Subscribers by name
|
|
25
|
+
const oSubscribe: Record<string, Subscribe> = {};
|
|
23
26
|
|
|
24
|
-
//
|
|
25
|
-
let dHash:
|
|
27
|
+
// Hash values by name (only null for init)
|
|
28
|
+
let dHash: HashType | null = null;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Init
|
|
32
|
+
*
|
|
33
|
+
* Only called once
|
|
34
|
+
*/
|
|
35
|
+
if(dHash === null) {
|
|
36
|
+
|
|
37
|
+
// Track changes
|
|
38
|
+
window.addEventListener("hashchange", hashChanged);
|
|
39
|
+
|
|
40
|
+
// Parse the current location hash
|
|
41
|
+
dHash = parseQuery(window.location.hash.substring(1));
|
|
42
|
+
}
|
|
26
43
|
|
|
27
44
|
/**
|
|
28
45
|
* Hash Changed
|
|
@@ -30,58 +47,37 @@ let dHash: Record<string, string> = {};
|
|
|
30
47
|
* Called when the location hash has been altered, notifies any watchers of
|
|
31
48
|
* hash values changing
|
|
32
49
|
*
|
|
33
|
-
* @name
|
|
50
|
+
* @name hashChanged
|
|
34
51
|
* @access private
|
|
35
52
|
* @return {void}
|
|
36
53
|
*/
|
|
37
|
-
function
|
|
54
|
+
function hashChanged(): void {
|
|
38
55
|
|
|
39
56
|
// Store the current hash
|
|
40
|
-
const old =
|
|
57
|
+
const old = { ...dHash };
|
|
41
58
|
|
|
42
59
|
// Re-parse the current location hash
|
|
43
60
|
dHash = parseQuery(window.location.hash.substring(1));
|
|
44
61
|
|
|
45
|
-
// If there are
|
|
46
|
-
if(!empty(
|
|
62
|
+
// If there are oSubscribe
|
|
63
|
+
if(!empty(oSubscribe)) {
|
|
47
64
|
|
|
48
|
-
// Check each
|
|
49
|
-
for(const name
|
|
65
|
+
// Check each subscribe instance
|
|
66
|
+
for(const name of Object.keys(oSubscribe)) {
|
|
50
67
|
|
|
51
|
-
// If the value
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
old[name] !== dHash[name]) {
|
|
68
|
+
// If the value no longer exists, set it to null
|
|
69
|
+
if(name in old && !(name in dHash)) {
|
|
70
|
+
oSubscribe[name].set(null);
|
|
71
|
+
}
|
|
56
72
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
73
|
+
// Else, the value is new, or altered, so use the new value
|
|
74
|
+
else {
|
|
75
|
+
oSubscribe[name].set(dHash[name]);
|
|
61
76
|
}
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
|
|
66
|
-
/**
|
|
67
|
-
* Init
|
|
68
|
-
*
|
|
69
|
-
* Initialises the internal hash by fetching and parsing the current
|
|
70
|
-
* location hash
|
|
71
|
-
*
|
|
72
|
-
* @name init
|
|
73
|
-
* @access public
|
|
74
|
-
* @return {void}
|
|
75
|
-
*/
|
|
76
|
-
function init(): void {
|
|
77
|
-
|
|
78
|
-
// Track changes
|
|
79
|
-
window.addEventListener("hashchange", _hashChanged);
|
|
80
|
-
|
|
81
|
-
// Parse the current location hash
|
|
82
|
-
dHash = parseQuery(window.location.hash.substring(1));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
81
|
/**
|
|
86
82
|
* Get
|
|
87
83
|
*
|
|
@@ -102,8 +98,8 @@ function get(name: string, defaultReturn?: string): string | null {
|
|
|
102
98
|
}
|
|
103
99
|
|
|
104
100
|
// If there is a value for the name
|
|
105
|
-
if(typeof dHash[name] !== 'undefined') {
|
|
106
|
-
return dHash[name];
|
|
101
|
+
if(typeof (dHash as HashType)[name] !== 'undefined') {
|
|
102
|
+
return (dHash as HashType)[name];
|
|
107
103
|
}
|
|
108
104
|
|
|
109
105
|
// Else, return the default
|
|
@@ -112,6 +108,22 @@ function get(name: string, defaultReturn?: string): string | null {
|
|
|
112
108
|
}
|
|
113
109
|
}
|
|
114
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Reset
|
|
113
|
+
*
|
|
114
|
+
* Notifies all existing subscriptions that all data went away
|
|
115
|
+
*
|
|
116
|
+
* @name reset
|
|
117
|
+
* @access private
|
|
118
|
+
*/
|
|
119
|
+
function reset(): void {
|
|
120
|
+
|
|
121
|
+
// Go through each subscribe instance
|
|
122
|
+
for(const name of Object.keys(oSubscribe)) {
|
|
123
|
+
oSubscribe[name].set(null);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
115
127
|
/**
|
|
116
128
|
* Set
|
|
117
129
|
*
|
|
@@ -137,7 +149,7 @@ function set(name: string | object, value?: string) {
|
|
|
137
149
|
}
|
|
138
150
|
|
|
139
151
|
// Make a copy of the current hash
|
|
140
|
-
const copy =
|
|
152
|
+
const copy = { ...dHash };
|
|
141
153
|
|
|
142
154
|
// Go through each name
|
|
143
155
|
for(const n of Object.keys(name)) {
|
|
@@ -162,11 +174,32 @@ function set(name: string | object, value?: string) {
|
|
|
162
174
|
|
|
163
175
|
// Go through each name
|
|
164
176
|
for(const k of Object.keys(copy)) {
|
|
165
|
-
temp.push(k + '=' + copy[k]);
|
|
177
|
+
temp.push(copy[k] === '' ? k : (k + '=' + copy[k]));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If we have none
|
|
181
|
+
if(temp.length === 0) {
|
|
182
|
+
|
|
183
|
+
// If we can use pushState
|
|
184
|
+
if('pushState' in history) {
|
|
185
|
+
history.pushState(
|
|
186
|
+
'',
|
|
187
|
+
document.title,
|
|
188
|
+
window.location.pathname + window.location.search
|
|
189
|
+
);
|
|
190
|
+
reset();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Else, we can't remove the '#', but clear the rest regardless
|
|
194
|
+
else {
|
|
195
|
+
window.location.hash = '';
|
|
196
|
+
}
|
|
166
197
|
}
|
|
167
198
|
|
|
168
|
-
//
|
|
169
|
-
|
|
199
|
+
// Else, reset the window location hash
|
|
200
|
+
else {
|
|
201
|
+
window.location.hash = temp.join('&');
|
|
202
|
+
}
|
|
170
203
|
}
|
|
171
204
|
|
|
172
205
|
/**
|
|
@@ -181,34 +214,25 @@ function set(name: string | object, value?: string) {
|
|
|
181
214
|
* @param {function} callback The function to call when the value changes
|
|
182
215
|
* @return {void}
|
|
183
216
|
*/
|
|
184
|
-
function subscribe(name: string, callback:
|
|
185
|
-
|
|
186
|
-
// If we already have the name
|
|
187
|
-
if(name in dCallbacks) {
|
|
217
|
+
function subscribe(name: string, callback: SubscribeCallback): SubscribeReturn {
|
|
188
218
|
|
|
189
|
-
|
|
190
|
-
|
|
219
|
+
// If we don't already have the name
|
|
220
|
+
if(!(name in oSubscribe)) {
|
|
191
221
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
222
|
+
// Create a new subscribe instance
|
|
223
|
+
oSubscribe[name] = new Subscribe(
|
|
224
|
+
name in (dHash as HashType) ? (dHash as HashType)[name] : null
|
|
225
|
+
);
|
|
197
226
|
}
|
|
198
227
|
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
dCallbacks[name] = [];
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Add the callback to the dCallbacks
|
|
205
|
-
dCallbacks[name].push(callback);
|
|
228
|
+
// Add the callback and return
|
|
229
|
+
return oSubscribe[name].subscribe(callback);
|
|
206
230
|
}
|
|
207
231
|
|
|
208
232
|
/**
|
|
209
233
|
* Unsubscribe
|
|
210
234
|
*
|
|
211
|
-
* Removes a callback from the
|
|
235
|
+
* Removes a callback from the oSubscribe
|
|
212
236
|
*
|
|
213
237
|
* @name unsubscribe
|
|
214
238
|
* @access public
|
|
@@ -216,25 +240,16 @@ function subscribe(name: string, callback: Callback): void {
|
|
|
216
240
|
* @param {function} callback The callback to remove
|
|
217
241
|
* @return {void}
|
|
218
242
|
*/
|
|
219
|
-
function unsubscribe(name: string, callback:
|
|
243
|
+
function unsubscribe(name: string, callback: SubscribeCallback): void {
|
|
220
244
|
|
|
221
245
|
// If we have the name
|
|
222
|
-
if(name in
|
|
223
|
-
|
|
224
|
-
// Go through the callbacks associated with the name
|
|
225
|
-
for(let i = 0; i < dCallbacks[name].length; ++i) {
|
|
246
|
+
if(name in oSubscribe) {
|
|
226
247
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
// Remove it
|
|
231
|
-
dCallbacks[name].splice(i, 1);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
248
|
+
// Attempt to unsubscribe
|
|
249
|
+
oSubscribe[name].unsubscribe(callback);
|
|
235
250
|
}
|
|
236
251
|
}
|
|
237
252
|
|
|
238
253
|
// Default export
|
|
239
|
-
const hash = {
|
|
240
|
-
export default hash;
|
|
254
|
+
const hash = { get, set, subscribe, unsubscribe };
|
|
255
|
+
export default hash;
|