@lumjs/core 1.26.0 → 1.31.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/README.md +15 -1
- package/jsdoc.js +13 -0
- package/lib/console.js +54 -0
- package/lib/enum.js +65 -15
- package/lib/events/event.js +85 -0
- package/lib/events/index.js +30 -0
- package/lib/events/listener.js +127 -0
- package/lib/events/registry.js +537 -0
- package/lib/index.js +34 -17
- package/lib/meta.js +71 -82
- package/lib/obj/clone.js +1 -1
- package/lib/obj/copyprops.js +2 -2
- package/lib/obj/cp.js +1375 -0
- package/lib/obj/flip.js +2 -0
- package/lib/obj/index.js +2 -1
- package/lib/obj/merge.js +1 -1
- package/lib/obj/ns.js +1 -1
- package/lib/objectid.js +41 -13
- package/lib/observable.js +1 -1
- package/lib/old/abstractclass.js +82 -0
- package/lib/opt/args.js +50 -0
- package/lib/opt/getpath.js +70 -0
- package/lib/opt/getval.js +61 -0
- package/lib/opt/index.js +21 -0
- package/lib/opt/val.js +63 -0
- package/lib/strings.js +1 -1
- package/lib/types/basics.js +35 -16
- package/lib/types/def.js +49 -36
- package/lib/types/dt.js +147 -18
- package/lib/types/index.js +32 -59
- package/lib/types/isa.js +4 -0
- package/lib/types/js.js +43 -7
- package/lib/types/lazy.js +3 -2
- package/lib/types/needs.js +0 -1
- package/lib/types/typelist.js +6 -4
- package/lum.build.js +40 -0
- package/package.json +24 -14
- package/TODO.md +0 -76
- package/jsdoc.json +0 -33
- package/lib/opt.js +0 -664
package/README.md
CHANGED
|
@@ -6,6 +6,16 @@ and work in CommonJS/Node.js and modern browsers without any modifications.
|
|
|
6
6
|
|
|
7
7
|
Used by all the rest of my *Lum.js* libraries.
|
|
8
8
|
|
|
9
|
+
## Notes
|
|
10
|
+
|
|
11
|
+
As of version `1.30.0` the `opt.Opts` class has been split into its the new
|
|
12
|
+
[@lumjs/opts] package, which itself depends on a new [@lumjs/errors] package.
|
|
13
|
+
|
|
14
|
+
Until the next major release (`2.0`), this package will have
|
|
15
|
+
a dependency on the split-away pacakages, so that it can have a deprecated
|
|
16
|
+
alias to the old class name available. As of `2.0` that alias will be
|
|
17
|
+
removed, and the dependencies will also be removed.
|
|
18
|
+
|
|
9
19
|
## Documentation
|
|
10
20
|
|
|
11
21
|
### [API Docs](https://supernovus.github.io/docs/js/@lumjs/core/)
|
|
@@ -16,7 +26,7 @@ You can compile the documentation using `npm run build-docs`
|
|
|
16
26
|
which will put the generated docs into the `./docs/api` folder.
|
|
17
27
|
|
|
18
28
|
### [Changelog](./docs/changelogs/1.x.md)
|
|
19
|
-
### [TODO](TODO.md)
|
|
29
|
+
### [TODO](./docs/TODO.md)
|
|
20
30
|
### [Homepage](https://supernovus.github.io/)
|
|
21
31
|
|
|
22
32
|
## Official URLs
|
|
@@ -34,3 +44,7 @@ Timothy Totten <2010@totten.ca>
|
|
|
34
44
|
|
|
35
45
|
[MIT](https://spdx.org/licenses/MIT.html)
|
|
36
46
|
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
[@lumjs/opts]: https://github.com/supernovus/lum.opts.js
|
|
50
|
+
[@lumjs/errors]: https://github.com/supernovus/lum.errors.js
|
package/jsdoc.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const docRules = require('@lumjs/build/jsdoc-rules');
|
|
4
|
+
const ourRules = docRules.docsReadme.srcDocs.clone();
|
|
5
|
+
module.exports = ourRules;
|
|
6
|
+
|
|
7
|
+
/*console.debug(
|
|
8
|
+
{
|
|
9
|
+
docRules,
|
|
10
|
+
ourRules,
|
|
11
|
+
incPath: ourRules?.source?.include,
|
|
12
|
+
});*/
|
|
13
|
+
|
package/lib/console.js
CHANGED
|
@@ -177,4 +177,58 @@ for (const method of DEFAULT_METHODS)
|
|
|
177
177
|
addMethod(method);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Export our wrapper to replace the real console
|
|
182
|
+
* in the global namespace.
|
|
183
|
+
*
|
|
184
|
+
* @param {*} [handler] Set a handler while we're exported.
|
|
185
|
+
*
|
|
186
|
+
* See the description of `handler` for possible values.
|
|
187
|
+
* Any existing handler value will be saved to the `preHandler`
|
|
188
|
+
* static property.
|
|
189
|
+
*
|
|
190
|
+
* @function module:@lumjs/core/console.export
|
|
191
|
+
*/
|
|
192
|
+
def(LC, 'export', function(handler)
|
|
193
|
+
{
|
|
194
|
+
if (handler !== undefined)
|
|
195
|
+
{ // Save the existing handler as 'preHandler'
|
|
196
|
+
LC.preHandler = LC.handler ?? null; // Prevent `undefined`
|
|
197
|
+
LC.handler = handler;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
globalThis.console = LC;
|
|
201
|
+
return LC;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Restore the real console.
|
|
206
|
+
*
|
|
207
|
+
* If a `handler` was passed to `export()`, then
|
|
208
|
+
* it will be removed, and the previous handler value
|
|
209
|
+
* will be restored.
|
|
210
|
+
*
|
|
211
|
+
* @function module:@lumjs/core/console.restore
|
|
212
|
+
*/
|
|
213
|
+
def(LC, 'restore', function()
|
|
214
|
+
{
|
|
215
|
+
if (LC.preHandler !== undefined)
|
|
216
|
+
{
|
|
217
|
+
LC.handler = LC.preHandler;
|
|
218
|
+
delete LC.preHandler;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
globalThis.console = LC.real;
|
|
222
|
+
return LC;
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* A shortcut for `LC.export(false)`
|
|
227
|
+
* @function module:@lumjs/core/console.mute
|
|
228
|
+
*/
|
|
229
|
+
def(LC, 'mute', function()
|
|
230
|
+
{
|
|
231
|
+
return LC.export(false);
|
|
232
|
+
});
|
|
233
|
+
|
|
180
234
|
module.exports = LC;
|
package/lib/enum.js
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
const {S,def,notNil,isObj,needObj,TYPES} = require('./types');
|
|
1
|
+
const {S,F,def,notNil,isObj,needObj,TYPES} = require('./types');
|
|
2
2
|
const {InternalObjectId} = require('./objectid');
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A pseudo-module describing everything associated with `core.Enum`
|
|
6
|
+
* @module @lumjs/core/enum
|
|
7
|
+
*/
|
|
8
|
+
|
|
4
9
|
// Internal id instances should never be exported.
|
|
5
|
-
const
|
|
10
|
+
const EID = '@lumjs/core/enum';
|
|
11
|
+
const ENUM_ID = new InternalObjectId({name: EID});
|
|
12
|
+
const isEnum = ENUM_ID.isFunction();
|
|
13
|
+
const EOPT = Symbol(EID+':opts');
|
|
6
14
|
|
|
7
15
|
/**
|
|
8
16
|
* A function to build magic Enum objects.
|
|
9
17
|
*
|
|
10
18
|
* Like the built-in `Symbol`, this is called as a function, not a constructor.
|
|
11
19
|
*
|
|
20
|
+
* This is the *actual* exported value from the `enum` pseudo-module.
|
|
21
|
+
*
|
|
12
22
|
* @param {(string[]|object)} spec - May be in one of two formats:
|
|
13
23
|
*
|
|
14
24
|
* - An `Array` of strings. Each string represents the name of an Enum
|
|
@@ -24,7 +34,13 @@ const ENUM_ID = new InternalObjectId({name: '$Enum'});
|
|
|
24
34
|
*
|
|
25
35
|
* @param {object} [opts] Options for creating the Enum
|
|
26
36
|
*
|
|
27
|
-
*
|
|
37
|
+
* If the `opts` is an _open_ `Enum` object, then
|
|
38
|
+
*
|
|
39
|
+
* @param {(bool|function)} [opts.symbols=false] Use `Symbol` property values.
|
|
40
|
+
*
|
|
41
|
+
* If this is a `function`, it will be passed the name that would be used as
|
|
42
|
+
* the symbol key, and must return the actual key string to use, or any
|
|
43
|
+
* non-string value to disable the use of symbols for that name.
|
|
28
44
|
*
|
|
29
45
|
* @param {bool} [opts.globals=false] Use `Symbol.for()` property values.
|
|
30
46
|
*
|
|
@@ -45,18 +61,24 @@ const ENUM_ID = new InternalObjectId({name: '$Enum'});
|
|
|
45
61
|
*
|
|
46
62
|
* The default value is `1` if `opts.flags` is `true` or `0` otherwise.
|
|
47
63
|
*
|
|
48
|
-
* @param {bool} [opts.open=false]
|
|
49
|
-
*
|
|
64
|
+
* @param {bool} [opts.open=false] Should the Enum be open to be extended?
|
|
65
|
+
*
|
|
66
|
+
* - If `true` the Enum object won't be locked, and the `opts` will be saved.
|
|
67
|
+
* - If `false` (default value) we use `Object.freeze()` to lock the object.
|
|
50
68
|
*
|
|
51
69
|
* @param {(bool|object|Array)} [opts.lock=null] If this is *not* `null`,
|
|
52
70
|
* use {@see module:@lumjs/core/obj.lock lock()} instead of `Object.freeze()`.
|
|
53
71
|
*
|
|
54
|
-
*
|
|
72
|
+
* If `opts.open` is `false`, the supported values are:
|
|
55
73
|
*
|
|
56
74
|
* - `Array`: The `[cloneable, cloneOpts, useSeal]` parameters for `clone()`.
|
|
57
75
|
* - `object`: The `cloneOpts` parameter for `clone()`.
|
|
58
76
|
* - `bool`: The `cloneable` parameter for `clone()`.
|
|
59
77
|
*
|
|
78
|
+
* If `opts.open` is `true`, this only supports an `object` which will be
|
|
79
|
+
* used as the `opts` for {@see module:@lumjs/core/obj.addLock addLock()},
|
|
80
|
+
* which will be called on the open Enum object.
|
|
81
|
+
*
|
|
60
82
|
* @param {bool} [opts.configurable=false] Enum properties are configurable?
|
|
61
83
|
*
|
|
62
84
|
* This option is ignored if `opts.open` is `false`.
|
|
@@ -65,29 +87,44 @@ const ENUM_ID = new InternalObjectId({name: '$Enum'});
|
|
|
65
87
|
*
|
|
66
88
|
* @returns {object} A magic Enum object.
|
|
67
89
|
* @throws {TypeError} If an invalid value was passed.
|
|
68
|
-
* @
|
|
90
|
+
* @alias module:@lumjs/core/enum.Enum
|
|
69
91
|
*/
|
|
70
92
|
function Enum (spec, opts={})
|
|
71
93
|
{
|
|
72
94
|
needObj(spec, "Enum spec must be an object")
|
|
73
95
|
needObj(opts, "Enum options must be an object")
|
|
74
96
|
|
|
75
|
-
const
|
|
97
|
+
const isExisting = isEnum(opts);
|
|
98
|
+
const anEnum = isExisting ? opts : ENUM_ID.tag({});
|
|
99
|
+
if (isExisting)
|
|
100
|
+
{
|
|
101
|
+
opts = anEnum[EOPT];
|
|
102
|
+
if (!isObj(opts))
|
|
103
|
+
{
|
|
104
|
+
throw new Error("existing Enum was not open for changes");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
76
107
|
|
|
77
108
|
const configurable = opts.configurable ?? false;
|
|
78
109
|
const enumerable = opts.enumerable ?? true;
|
|
79
110
|
|
|
111
|
+
const symKey
|
|
112
|
+
= (typeof opts.symbols === F)
|
|
113
|
+
? opts.symbols
|
|
114
|
+
: v => v;
|
|
115
|
+
|
|
80
116
|
function getVal (name, def)
|
|
81
117
|
{
|
|
82
118
|
if (opts.symbols)
|
|
83
119
|
{ // We want to use symbols.
|
|
120
|
+
const key = symKey(name);
|
|
84
121
|
if (opts.globals)
|
|
85
122
|
{
|
|
86
|
-
return Symbol.for(
|
|
123
|
+
return Symbol.for(key);
|
|
87
124
|
}
|
|
88
125
|
else
|
|
89
126
|
{
|
|
90
|
-
return Symbol(
|
|
127
|
+
return Symbol(key);
|
|
91
128
|
}
|
|
92
129
|
}
|
|
93
130
|
else
|
|
@@ -130,6 +167,10 @@ function Enum (spec, opts={})
|
|
|
130
167
|
counter++;
|
|
131
168
|
}
|
|
132
169
|
}
|
|
170
|
+
if (opts.open)
|
|
171
|
+
{ // Save the last counter value into the opts
|
|
172
|
+
opts.counter = counter;
|
|
173
|
+
}
|
|
133
174
|
}
|
|
134
175
|
else
|
|
135
176
|
{ // An object mapping of property name to value.
|
|
@@ -141,7 +182,18 @@ function Enum (spec, opts={})
|
|
|
141
182
|
}
|
|
142
183
|
}
|
|
143
184
|
|
|
144
|
-
if (
|
|
185
|
+
if (opts.open)
|
|
186
|
+
{
|
|
187
|
+
if (!isExisting)
|
|
188
|
+
{ // Save the options into a special Symbol property.
|
|
189
|
+
def(anEnum, EOPT, {value: opts});
|
|
190
|
+
if (isObj(opts.lock))
|
|
191
|
+
{ // Add lock() method.
|
|
192
|
+
addLock(anEnum, opts.lock);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else
|
|
145
197
|
{
|
|
146
198
|
if (notNil(opts.lock))
|
|
147
199
|
{ // Use lock() function.
|
|
@@ -180,13 +232,11 @@ function Enum (spec, opts={})
|
|
|
180
232
|
* @param {*} obj - The expected object/function to test.
|
|
181
233
|
* @returns {boolean}
|
|
182
234
|
*/
|
|
183
|
-
const isEnum = ENUM_ID.isFunction()
|
|
184
235
|
def(Enum, 'is', isEnum);
|
|
185
236
|
|
|
186
237
|
/**
|
|
187
238
|
* Is a value an *Enum* magic object?
|
|
188
|
-
* @
|
|
189
|
-
* @function
|
|
239
|
+
* @function module:@lumjs/core/types.isEnum
|
|
190
240
|
* @param {*} v - The value to test.
|
|
191
241
|
* @returns {boolean}
|
|
192
242
|
* @see module:@lumjs/core/enum.is
|
|
@@ -202,4 +252,4 @@ TYPES.add('ENUM', 'enum', isEnum, 'isEnum');
|
|
|
202
252
|
module.exports = Enum;
|
|
203
253
|
|
|
204
254
|
// Loading this at the end.
|
|
205
|
-
const {lock} = require('./obj/lock');
|
|
255
|
+
const {lock,addLock} = require('./obj/lock');
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {F,isObj} = require('../types');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* An Event object to emit to handler callbacks.
|
|
7
|
+
*
|
|
8
|
+
* @prop {module:@lumjs/core/events.Listener} eventListener
|
|
9
|
+
* The event Listener instance this event was emitted from.
|
|
10
|
+
* @prop {string} name - The event name that was triggered.
|
|
11
|
+
* @prop {object} target - Target object for this event.
|
|
12
|
+
* @prop {Array} args - Arguments passed to `emit()`
|
|
13
|
+
* @prop {object} options - Composes options from the
|
|
14
|
+
* Registry and the Listener. Listener options take priority.
|
|
15
|
+
* @prop {?object} data
|
|
16
|
+
* If `args[0]` is any kind of `object` other than another Event
|
|
17
|
+
* instance, it will be used as the `data` property.
|
|
18
|
+
* If `args[0]` is not an `object`, this property will be `null`.
|
|
19
|
+
* @prop {module:@lumjs/core/events.Event} origEvent
|
|
20
|
+
* Unless `this.prevEvent` is set, this should always be
|
|
21
|
+
* a reference to `this` instance itself.
|
|
22
|
+
* @prop {?module:@lumjs/core/events.Event} prevEvent
|
|
23
|
+
* If `args[0]` is another Event instance this property
|
|
24
|
+
* will be set with its value, as well as the following
|
|
25
|
+
* changes to the default behavior:
|
|
26
|
+
*
|
|
27
|
+
* - `this.data` will be set to `prevEvent.data`.
|
|
28
|
+
* - `this.origEvent` will be set to `prevEvent.origEvent`
|
|
29
|
+
*
|
|
30
|
+
* @prop {module:@lumjs/core/events~Status} emitStatus
|
|
31
|
+
*
|
|
32
|
+
* @alias module:@lumjs/core/events.Event
|
|
33
|
+
*/
|
|
34
|
+
class LumEvent
|
|
35
|
+
{
|
|
36
|
+
/**
|
|
37
|
+
* Create a new Event instance; should not be called directly.
|
|
38
|
+
* @protected
|
|
39
|
+
* @param {module:@lumjs/core/events.Listener} listener
|
|
40
|
+
* @param {object} target
|
|
41
|
+
* @param {string} name
|
|
42
|
+
* @param {Array} args
|
|
43
|
+
* @param {object} status
|
|
44
|
+
*/
|
|
45
|
+
constructor(listener, target, name, args, status)
|
|
46
|
+
{
|
|
47
|
+
const reg = listener.registry;
|
|
48
|
+
this.eventListener = listener;
|
|
49
|
+
this.args = args;
|
|
50
|
+
this.target = target;
|
|
51
|
+
this.name = name;
|
|
52
|
+
this.emitStatus = status;
|
|
53
|
+
this.options = Object.assign({},
|
|
54
|
+
reg.options,
|
|
55
|
+
listener.options,
|
|
56
|
+
status.options);
|
|
57
|
+
|
|
58
|
+
this.data = null;
|
|
59
|
+
this.prevEvent = null;
|
|
60
|
+
this.origEvent = this;
|
|
61
|
+
|
|
62
|
+
if (isObj(args[0]))
|
|
63
|
+
{ // The first argument is an object.
|
|
64
|
+
const ao = args[0];
|
|
65
|
+
if (ao instanceof LumEvent)
|
|
66
|
+
{ // A previous event.
|
|
67
|
+
this.prevEvent = ao;
|
|
68
|
+
this.origEvent = ao.origEvent;
|
|
69
|
+
this.data = ao.data;
|
|
70
|
+
}
|
|
71
|
+
else
|
|
72
|
+
{ // Use it as a data object.
|
|
73
|
+
this.data = ao;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (typeof this.options.setupEvent === F)
|
|
78
|
+
{
|
|
79
|
+
this.options.setupEvent.call(listener, this);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = LumEvent;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simplistic event registration and dispatch module.
|
|
3
|
+
*
|
|
4
|
+
* Designed to be a replacement for the `observable` API which started
|
|
5
|
+
* out simple enough (when I forked it from `riot.js`), but has since
|
|
6
|
+
* grown into a big mess with many unusual and unexpected behaviours.
|
|
7
|
+
*
|
|
8
|
+
* So this has been designed to work with a cleaner, more consistent,
|
|
9
|
+
* yet extremely flexible event model.
|
|
10
|
+
*
|
|
11
|
+
* @module @lumjs/core/events
|
|
12
|
+
*/
|
|
13
|
+
exports = module.exports =
|
|
14
|
+
{
|
|
15
|
+
Registry: require('./registry'),
|
|
16
|
+
Listener: require('./listener'),
|
|
17
|
+
Event: require('./event'),
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A shortcut function to create a new Registry instance.
|
|
21
|
+
* All arguments are passed to the Registry constructor.
|
|
22
|
+
* @param {(object|module:@lumjs/core/events~GetTargets)} targets
|
|
23
|
+
* @param {object} [opts]
|
|
24
|
+
* @returns {module:@lumjs/core/events.Registry}
|
|
25
|
+
*/
|
|
26
|
+
register()
|
|
27
|
+
{
|
|
28
|
+
return new exports.Registry(...arguments);
|
|
29
|
+
},
|
|
30
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {F,isObj} = require('../types');
|
|
4
|
+
const Event = require('./event');
|
|
5
|
+
|
|
6
|
+
const REMOVE_OPTS = ['listener','handler','eventNames'];
|
|
7
|
+
|
|
8
|
+
function makeOpts(spec)
|
|
9
|
+
{
|
|
10
|
+
const opts = Object.assign({}, spec, spec.options);
|
|
11
|
+
for (const rm of REMOVE_OPTS)
|
|
12
|
+
{
|
|
13
|
+
delete opts[rm];
|
|
14
|
+
}
|
|
15
|
+
return opts;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Is something a valid value for an event listener?
|
|
20
|
+
*
|
|
21
|
+
* Valid listener values are inspired by the `DOM.EventTarget` interface:
|
|
22
|
+
*
|
|
23
|
+
* - A `function`
|
|
24
|
+
* - An `object` with a `handleEvent()` method
|
|
25
|
+
*
|
|
26
|
+
* @param {*} v - Value we are testing
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
* @alias module:@lumjs/core/events.Listener.isListener
|
|
29
|
+
*/
|
|
30
|
+
function isListener(v)
|
|
31
|
+
{
|
|
32
|
+
return (typeof v === F || (isObj(v) && typeof v.handleEvent === F));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* An Event Listener instance used by a Registry
|
|
37
|
+
*
|
|
38
|
+
* Used internally by the Registry class, there's likely very few
|
|
39
|
+
* reasons you'd want to call any methods on this manually.
|
|
40
|
+
*
|
|
41
|
+
* @prop {module:@lumjs/core/events.Registry} registry
|
|
42
|
+
* The Registry instance this Listener belongs to.
|
|
43
|
+
* @prop {(function|object)} handler - Event handler callback
|
|
44
|
+
* @prop {Set} eventNames - A set of all event names handled by this
|
|
45
|
+
* @prop {object} options - Options specific to this listener.
|
|
46
|
+
*
|
|
47
|
+
* See {@link module:@lumjs/core/events.Registry#makeListener makeListener()}
|
|
48
|
+
* for details on what this may contain and how it is populated.
|
|
49
|
+
*
|
|
50
|
+
* @alias module:@lumjs/core/events.Listener
|
|
51
|
+
*/
|
|
52
|
+
class LumEventListener
|
|
53
|
+
{
|
|
54
|
+
/**
|
|
55
|
+
* Build a listener; called by Registry instance
|
|
56
|
+
* @private
|
|
57
|
+
* @param {module:@lumjs/core/events.Registry} registry
|
|
58
|
+
* @param {object} spec
|
|
59
|
+
*/
|
|
60
|
+
constructor(registry, spec)
|
|
61
|
+
{
|
|
62
|
+
if (isListener(spec.listener))
|
|
63
|
+
{
|
|
64
|
+
this.handler = spec.listener;
|
|
65
|
+
}
|
|
66
|
+
else if (isListener(spec.handler))
|
|
67
|
+
{
|
|
68
|
+
this.handler = spec.handler;
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
{
|
|
72
|
+
console.error({spec,registry});
|
|
73
|
+
throw new TypeError("Invalid listener/handler in spec");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Assign the rest here.
|
|
77
|
+
this.registry = registry;
|
|
78
|
+
this.options = makeOpts(spec);
|
|
79
|
+
this.eventNames = registry.getEventNames(spec.eventNames);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* See if there is at least one item in `this.eventNames`
|
|
84
|
+
* @type {boolean}
|
|
85
|
+
*/
|
|
86
|
+
get hasEvents()
|
|
87
|
+
{
|
|
88
|
+
return this.eventNames.size > 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Used by {@link module:@lumjs/core/events.Registry#emit emit()} to create
|
|
93
|
+
* and emit a new Event instance for a specified event name and target.
|
|
94
|
+
*
|
|
95
|
+
* This is a *protected method* and should not be called directly.
|
|
96
|
+
* @protected
|
|
97
|
+
* @param {string} eventName - A single event name that was triggered
|
|
98
|
+
* @param {object} target - A single target object
|
|
99
|
+
* @param {Array} args - Arguments passed to `emit()`
|
|
100
|
+
* @param {module:@lumjs/core/events~Status} status - Emit status info
|
|
101
|
+
* @returns {module:@lumjs/core/events.Event} The new Event that was emitted
|
|
102
|
+
*/
|
|
103
|
+
emitEvent(eventName, target, args, status)
|
|
104
|
+
{
|
|
105
|
+
const event = new Event(this, target, eventName, args, status);
|
|
106
|
+
|
|
107
|
+
if (typeof this.handler === F)
|
|
108
|
+
{ // The simplest is the good old function
|
|
109
|
+
this.handler.call(event.target, event);
|
|
110
|
+
}
|
|
111
|
+
else
|
|
112
|
+
{ // An object with a `handleEvent()` method
|
|
113
|
+
this.handler.handleEvent(event);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (event.options.once)
|
|
117
|
+
{ // This listener is to be removed
|
|
118
|
+
status.onceRemoved.add(this);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return event;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
LumEventListener.isListener = isListener;
|
|
127
|
+
module.exports = LumEventListener;
|