@lumjs/core 1.10.0 → 1.11.0
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/lib/observable.js +92 -47
- package/package.json +1 -1
package/lib/observable.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
const {B,F,S,def,isObj,isComplex,TYPES,console} = require('./types');
|
|
3
|
+
const {duplicateAll: clone} = require('./obj/copyall');
|
|
4
|
+
const lock = Object.freeze;
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Make an object support the *Observable* API.
|
|
@@ -11,29 +13,57 @@ const {B,F,S,def,isObj,isComplex,TYPES,console} = require('./types');
|
|
|
11
13
|
* @param {string} [opts.wildcard='*'] The event name used as a wildcard.
|
|
12
14
|
* @param {boolean} [opts.wrapthis=false] If `true`, `this` will be a wrapper.
|
|
13
15
|
*
|
|
14
|
-
* If
|
|
15
|
-
* the
|
|
16
|
+
* If `wrapthis` is `true`, the function will be called with a wrapper object
|
|
17
|
+
* as the `this` variable instead of the target object. The wrapper will be:
|
|
16
18
|
*
|
|
17
19
|
* ```js
|
|
18
20
|
* {
|
|
21
|
+
* isObservable:
|
|
22
|
+
* {
|
|
23
|
+
* event: true, // This is an event data object.
|
|
24
|
+
* target: false, // This is not the target object.
|
|
25
|
+
* },
|
|
19
26
|
* self: el, // The target object.
|
|
20
27
|
* name: event, // The event name that was triggered.
|
|
21
28
|
* wildcard: bool, // Will be true if this was a wildcard event handler.
|
|
22
29
|
* func: function, // The function being called.
|
|
30
|
+
* args: array, // The arguments passed to trigger.
|
|
23
31
|
* }
|
|
24
32
|
* ```
|
|
25
33
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
34
|
+
* The object will be frozen so its values cannot be modified.
|
|
35
|
+
*
|
|
36
|
+
* @param {boolean} [opts.wrapargs=false] If `true`, the functions will be
|
|
37
|
+
* passed a single object as the sole argument. The object will be the same
|
|
38
|
+
* as the one from `opts.wrapthis`.
|
|
39
|
+
*
|
|
40
|
+
* @param {boolean} [opts.addname] If `true` callbacks with
|
|
41
|
+
* multiple events will have the name of the triggered event added as
|
|
42
|
+
* the first parameter.
|
|
43
|
+
*
|
|
44
|
+
* If either `wrapthis` or `wrapargs` are `true`, then this will default
|
|
45
|
+
* to `false`, otherwise it will default to `true`.
|
|
46
|
+
*
|
|
47
|
+
* @param {boolean} [opts.addis] If `true` add a read-only, frozen
|
|
48
|
+
* object property named `isObservable` with the value:
|
|
49
|
+
*
|
|
50
|
+
* ```js
|
|
51
|
+
* {
|
|
52
|
+
* event: false, // This is not an event data object.
|
|
53
|
+
* target: true, // This is the target object.
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* If either `wrapthis` or `wrapargs` are `true`, then this will default
|
|
58
|
+
* to `true`, otherwise it will default to `false`.
|
|
29
59
|
*
|
|
30
|
-
* @param {boolean} [opts.addis=opts.wrapthis] If `true` add immutable
|
|
31
|
-
* property named `isObservable` which will have a value of `true`.
|
|
32
60
|
* @param {string} [opts.addme] If set, add a method with this name
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
61
|
+
* to the `el` object, which is a version of `observable()` with the
|
|
62
|
+
* default options being the same as the current `opts`.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} [opts.addre] If set, add a method with this name
|
|
65
|
+
* to the `el` object, which is a function that can re-build the
|
|
66
|
+
* observable API methods with new `opts` replacing the old ones.
|
|
37
67
|
*
|
|
38
68
|
* @returns {object} el
|
|
39
69
|
*
|
|
@@ -69,30 +99,46 @@ function observable (el={}, opts={})
|
|
|
69
99
|
? opts.wildcard
|
|
70
100
|
: '*';
|
|
71
101
|
|
|
72
|
-
const wrapthis = (typeof opts.wrapthis ===
|
|
102
|
+
const wrapthis = (typeof opts.wrapthis === B)
|
|
73
103
|
? opts.wrapthis
|
|
74
104
|
: false;
|
|
75
105
|
|
|
76
|
-
const
|
|
106
|
+
const wrapargs = (typeof opts.wrapargs === B)
|
|
107
|
+
? opts.wrapargs
|
|
108
|
+
: false;
|
|
109
|
+
|
|
110
|
+
const wrapped = (wrapthis || wrapargs);
|
|
111
|
+
|
|
112
|
+
const addname = (typeof opts.addname === B)
|
|
77
113
|
? opts.addname
|
|
78
|
-
: !
|
|
114
|
+
: !wrapped;
|
|
79
115
|
|
|
80
|
-
const addis = (typeof opts.addis ===
|
|
116
|
+
const addis = (typeof opts.addis === B)
|
|
81
117
|
? opts.addis
|
|
82
|
-
:
|
|
118
|
+
: wrapped;
|
|
83
119
|
|
|
84
120
|
const validIdent = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
|
|
85
121
|
|
|
86
|
-
const addme = (typeof opts.addme ===
|
|
122
|
+
const addme = (typeof opts.addme === S
|
|
87
123
|
&& validIdent.test(opts.addme))
|
|
88
124
|
? opts.addme
|
|
89
|
-
:
|
|
125
|
+
: null;
|
|
126
|
+
|
|
127
|
+
const addre = (typeof opts.addre === S
|
|
128
|
+
&& validIdent.test(opts.addre))
|
|
129
|
+
? opts.addre
|
|
130
|
+
: null;
|
|
90
131
|
|
|
91
132
|
const slice = Array.prototype.slice;
|
|
92
133
|
|
|
93
134
|
function onEachEvent (e, fn)
|
|
94
135
|
{
|
|
95
|
-
e.
|
|
136
|
+
const es = e.split(/\s+/);
|
|
137
|
+
const me = es.length > 1;
|
|
138
|
+
for (e of es)
|
|
139
|
+
{
|
|
140
|
+
fn(e, me);
|
|
141
|
+
}
|
|
96
142
|
}
|
|
97
143
|
|
|
98
144
|
const add = def(el);
|
|
@@ -102,29 +148,28 @@ function observable (el={}, opts={})
|
|
|
102
148
|
if (fn.busy) return;
|
|
103
149
|
fn.busy = 1;
|
|
104
150
|
|
|
105
|
-
let
|
|
151
|
+
let fobj;
|
|
106
152
|
|
|
107
|
-
if (wrapthis)
|
|
108
|
-
{
|
|
153
|
+
if (wrapthis || wrapargs)
|
|
154
|
+
{ // Something is going to use our wrapper object.
|
|
109
155
|
const isWild = (name === wildcard);
|
|
110
156
|
const fname = isWild ? (addname ? args[0] : args.shift()) : name;
|
|
111
|
-
|
|
112
|
-
{
|
|
157
|
+
fobj =
|
|
158
|
+
lock({
|
|
159
|
+
isObservable: lock({event: true, target: false}),
|
|
113
160
|
self: el,
|
|
114
161
|
name: fname,
|
|
115
162
|
func: fn,
|
|
116
163
|
wildcard: isWild,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
else
|
|
120
|
-
{
|
|
121
|
-
fthis = el;
|
|
164
|
+
args,
|
|
165
|
+
});
|
|
122
166
|
}
|
|
123
167
|
|
|
124
|
-
|
|
125
|
-
|
|
168
|
+
const fthis = wrapthis ? fobj : el;
|
|
169
|
+
const fargs = wrapargs ? [fobj]
|
|
170
|
+
: ((fn.typed && addname) ? [name].concat(args) : args);
|
|
171
|
+
|
|
126
172
|
fn.apply(fthis, fargs);
|
|
127
|
-
|
|
128
173
|
fn.busy = 0;
|
|
129
174
|
}
|
|
130
175
|
|
|
@@ -147,10 +192,10 @@ function observable (el={}, opts={})
|
|
|
147
192
|
return el;
|
|
148
193
|
}
|
|
149
194
|
|
|
150
|
-
onEachEvent(events, function(name,
|
|
195
|
+
onEachEvent(events, function(name, typed)
|
|
151
196
|
{
|
|
152
197
|
(callbacks[name] = callbacks[name] || []).push(fn);
|
|
153
|
-
fn.typed =
|
|
198
|
+
fn.typed = typed;
|
|
154
199
|
});
|
|
155
200
|
|
|
156
201
|
return el;
|
|
@@ -244,28 +289,28 @@ function observable (el={}, opts={})
|
|
|
244
289
|
|
|
245
290
|
if (addis)
|
|
246
291
|
{
|
|
247
|
-
add('isObservable', true);
|
|
292
|
+
add('isObservable', lock({event: false, target: true}));
|
|
248
293
|
}
|
|
249
294
|
|
|
250
295
|
if (addme)
|
|
251
296
|
{ // Add a wrapper for observable() that sets new default options.
|
|
252
|
-
const ourProps = Object.keys(opts);
|
|
253
297
|
add(addme, function (obj=null, mopts={})
|
|
254
298
|
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
return observable(obj, mopts);
|
|
299
|
+
return observable(obj, clone(opts, mopts));
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (addre)
|
|
304
|
+
{ // Add a method to change the observable options.
|
|
305
|
+
add(addre, function(opts={})
|
|
306
|
+
{
|
|
307
|
+
return observable(el, opts);
|
|
266
308
|
});
|
|
267
309
|
}
|
|
268
310
|
|
|
311
|
+
// Metadata
|
|
312
|
+
add('$$observable$$', lock({opts, observable}));
|
|
313
|
+
|
|
269
314
|
return el
|
|
270
315
|
|
|
271
316
|
} // observable()
|