@next2d/events 1.14.20

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.
@@ -0,0 +1,622 @@
1
+ import { Event } from "./Event";
2
+ import { EventPhase } from "./EventPhase";
3
+ import { $setCurrentLoaderInfo, $currentPlayer } from "@next2d/util";
4
+ import { $getMap, $poolMap, $getArray, $poolArray } from "@next2d/share";
5
+ /**
6
+ * EventDispatcher クラスは、イベントを送出するすべてのクラスの基本クラスです。
7
+ *
8
+ * The EventDispatcher class is the base class for all classes that dispatch events.
9
+ *
10
+ * @example <caption>Example usage of EventDispatcher.</caption>
11
+ * // new ColorTransform
12
+ * const {EventDispatcher} = next2d.events;
13
+ * const eventDispatcher = new EventDispatcher();
14
+ * eventDispatcher.addEventListener(Event.ENTER_FRAME, function (event)
15
+ * {
16
+ * // more...
17
+ * });
18
+ *
19
+ * @class
20
+ * @memberOf next2d.events
21
+ */
22
+ export class EventDispatcher {
23
+ /**
24
+ * @constructor
25
+ * @public
26
+ */
27
+ constructor() {
28
+ /**
29
+ * @type {Map}
30
+ * @default null
31
+ * @private
32
+ */
33
+ this._$events = null;
34
+ }
35
+ /**
36
+ * 指定されたクラスのストリングを返します。
37
+ * Returns the string representation of the specified class.
38
+ *
39
+ * @return {string}
40
+ * @default [class EventDispatcher]
41
+ * @method
42
+ * @static
43
+ */
44
+ static toString() {
45
+ return "[class EventDispatcher]";
46
+ }
47
+ /**
48
+ * @description 指定されたクラスの空間名を返します。
49
+ * Returns the space name of the specified class.
50
+ *
51
+ * @member {string}
52
+ * @default next2d.events.EventDispatcher
53
+ * @const
54
+ * @static
55
+ */
56
+ static get namespace() {
57
+ return "next2d.events.EventDispatcher";
58
+ }
59
+ /**
60
+ * @description 指定されたオブジェクトのストリングを返します。
61
+ * Returns the string representation of the specified object.
62
+ *
63
+ * @return {string}
64
+ * @method
65
+ * @public
66
+ */
67
+ toString() {
68
+ return "[object EventDispatcher]";
69
+ }
70
+ /**
71
+ * @description 指定されたオブジェクトの空間名を返します。
72
+ * Returns the space name of the specified object.
73
+ *
74
+ * @member {string}
75
+ * @default next2d.events.EventDispatcher
76
+ * @const
77
+ * @public
78
+ */
79
+ get namespace() {
80
+ return "next2d.events.EventDispatcher";
81
+ }
82
+ /**
83
+ * @description イベントリスナーオブジェクトを EventDispatcher オブジェクトに登録し、
84
+ * リスナーがイベントの通知を受け取るようにします。
85
+ * Registers an event listener object with an EventDispatcher object
86
+ * so that the listener receives notification of an event.
87
+ *
88
+ * @param {string} type
89
+ * @param {function} listener
90
+ * @param {boolean} [use_capture=false]
91
+ * @param {number} [priority=0]
92
+ * @return {void}
93
+ * @method
94
+ * @public
95
+ */
96
+ addEventListener(type, listener, use_capture = false, priority = 0) {
97
+ const player = $currentPlayer();
98
+ let events;
99
+ let isBroadcast = false;
100
+ type = `${type}`;
101
+ switch (type) {
102
+ // broadcast event
103
+ case Event.ENTER_FRAME:
104
+ case Event.EXIT_FRAME:
105
+ case Event.FRAME_CONSTRUCTED:
106
+ case Event.RENDER:
107
+ case Event.ACTIVATE:
108
+ case Event.DEACTIVATE:
109
+ case "keyDown":
110
+ case "keyUp":
111
+ if (!player.broadcastEvents.size
112
+ || !player.broadcastEvents.has(type)) {
113
+ player.broadcastEvents.set(type, $getArray());
114
+ }
115
+ events = player.broadcastEvents.get(type) || $getArray();
116
+ isBroadcast = true;
117
+ break;
118
+ // normal event
119
+ default:
120
+ // init
121
+ if (!this._$events) {
122
+ this._$events = $getMap();
123
+ }
124
+ if (!this._$events.size || !this._$events.has(type)) {
125
+ this._$events.set(type, $getArray());
126
+ }
127
+ events = this._$events.get(type) || $getArray();
128
+ break;
129
+ }
130
+ // duplicate check
131
+ let length = events.length;
132
+ for (let idx = 0; idx < length; ++idx) {
133
+ const event = events[idx];
134
+ if (use_capture !== event.useCapture) {
135
+ continue;
136
+ }
137
+ if (event.target !== this) {
138
+ continue;
139
+ }
140
+ if (event.listener === listener) {
141
+ length = idx;
142
+ }
143
+ }
144
+ // add or overwrite
145
+ events[length] = {
146
+ "listener": listener,
147
+ "priority": priority,
148
+ "useCapture": use_capture,
149
+ "target": this
150
+ };
151
+ if (events.length > 1) {
152
+ // sort(DESC)
153
+ events.sort(function (a, b) {
154
+ switch (true) {
155
+ case a.priority > b.priority:
156
+ return -1;
157
+ case a.priority < b.priority:
158
+ return 1;
159
+ default:
160
+ return 0;
161
+ }
162
+ });
163
+ }
164
+ // set new event
165
+ if (isBroadcast) {
166
+ player.broadcastEvents.set(type, events);
167
+ }
168
+ else {
169
+ if (!this._$events) {
170
+ this._$events = $getMap();
171
+ }
172
+ this._$events.set(type, events);
173
+ }
174
+ }
175
+ /**
176
+ * @description イベントをイベントフローに送出します。
177
+ * Dispatches an event into the event flow.
178
+ *
179
+ * @param {Event} event
180
+ * @return {boolean}
181
+ * @method
182
+ * @public
183
+ */
184
+ dispatchEvent(event) {
185
+ switch (event.type) {
186
+ case Event.ENTER_FRAME:
187
+ case Event.EXIT_FRAME:
188
+ case Event.FRAME_CONSTRUCTED:
189
+ case Event.RENDER:
190
+ case Event.ACTIVATE:
191
+ case Event.DEACTIVATE:
192
+ case "keyDown":
193
+ case "keyUp":
194
+ {
195
+ const player = $currentPlayer();
196
+ if (player && player.broadcastEvents.size
197
+ && player.broadcastEvents.has(event.type)) {
198
+ const events = player.broadcastEvents.get(event.type);
199
+ for (let idx = 0; idx < events.length; ++idx) {
200
+ const obj = events[idx];
201
+ if (obj.target !== this) {
202
+ continue;
203
+ }
204
+ // start target
205
+ event.eventPhase = EventPhase.AT_TARGET;
206
+ // event execute
207
+ event.currentTarget = obj.target;
208
+ try {
209
+ event.listener = obj.listener;
210
+ obj.listener.call(null, event);
211
+ }
212
+ catch (e) {
213
+ console.error(e);
214
+ return false;
215
+ }
216
+ }
217
+ return true;
218
+ }
219
+ }
220
+ break;
221
+ default:
222
+ {
223
+ let events = null;
224
+ if (this._$events
225
+ && this._$events.size
226
+ && this._$events.has(event.type)) {
227
+ events = this._$events.get(event.type);
228
+ if (events) {
229
+ events = events.slice(0);
230
+ }
231
+ }
232
+ if (!events) {
233
+ events = $getArray();
234
+ }
235
+ // parent
236
+ const parentEvents = $getArray();
237
+ if ("parent" in this) {
238
+ let parent = this.parent;
239
+ while (parent) {
240
+ if (parent.hasEventListener(event.type)) {
241
+ const events = parent._$events
242
+ ? parent._$events.get(event.type)
243
+ : undefined;
244
+ if (events) {
245
+ parentEvents.push(events);
246
+ }
247
+ }
248
+ parent = parent.parent;
249
+ }
250
+ }
251
+ event.target = this;
252
+ if (events.length || parentEvents.length) {
253
+ // start capture
254
+ event.eventPhase = EventPhase.CAPTURING_PHASE;
255
+ // stage => parent... end
256
+ if (parentEvents.length) {
257
+ switch (true) {
258
+ case event._$stopImmediatePropagation:
259
+ case event._$stopPropagation:
260
+ break;
261
+ default:
262
+ parentEvents.reverse();
263
+ for (let idx = 0; idx < parentEvents.length; ++idx) {
264
+ const targets = parentEvents[idx];
265
+ for (let idx = 0; idx < targets.length; ++idx) {
266
+ const obj = targets[idx];
267
+ if (!obj.useCapture) {
268
+ continue;
269
+ }
270
+ // event execute
271
+ event.currentTarget = obj.target;
272
+ $setCurrentLoaderInfo(obj.target.loaderInfo);
273
+ try {
274
+ event.listener = obj.listener;
275
+ obj.listener.call(null, event);
276
+ }
277
+ catch (e) {
278
+ console.error(e);
279
+ return false;
280
+ }
281
+ if (event._$stopImmediatePropagation) {
282
+ break;
283
+ }
284
+ }
285
+ if (event._$stopImmediatePropagation) {
286
+ break;
287
+ }
288
+ }
289
+ parentEvents.reverse();
290
+ break;
291
+ }
292
+ }
293
+ // start target
294
+ event.eventPhase = EventPhase.AT_TARGET;
295
+ if (!event._$stopImmediatePropagation
296
+ && !event._$stopPropagation) {
297
+ const length = events.length;
298
+ for (let idx = 0; idx < length; ++idx) {
299
+ const obj = events[idx];
300
+ if (obj.useCapture) {
301
+ continue;
302
+ }
303
+ // event execute
304
+ event.currentTarget = obj.target;
305
+ $setCurrentLoaderInfo(obj.target.loaderInfo);
306
+ try {
307
+ event.listener = obj.listener;
308
+ obj.listener.call(null, event);
309
+ }
310
+ catch (e) {
311
+ console.error(e);
312
+ return false;
313
+ }
314
+ if (event._$stopImmediatePropagation) {
315
+ break;
316
+ }
317
+ }
318
+ }
319
+ // start bubbling
320
+ event.eventPhase = EventPhase.BUBBLING_PHASE;
321
+ switch (true) {
322
+ case event._$stopImmediatePropagation:
323
+ case event._$stopPropagation:
324
+ case !event.bubbles:
325
+ break;
326
+ default:
327
+ // this => parent... => stage end
328
+ for (let idx = 0; idx < parentEvents.length; ++idx) {
329
+ const targets = parentEvents[idx];
330
+ for (let idx = 0; idx < targets.length; ++idx) {
331
+ const obj = targets[idx];
332
+ if (obj.useCapture) {
333
+ continue;
334
+ }
335
+ // event execute
336
+ event.currentTarget = obj.target;
337
+ $setCurrentLoaderInfo(obj.target.loaderInfo);
338
+ try {
339
+ event.listener = obj.listener;
340
+ obj.listener.call(null, event);
341
+ }
342
+ catch (e) {
343
+ console.error(e);
344
+ return false;
345
+ }
346
+ if (event._$stopImmediatePropagation) {
347
+ break;
348
+ }
349
+ }
350
+ if (event._$stopImmediatePropagation) {
351
+ break;
352
+ }
353
+ }
354
+ break;
355
+ }
356
+ $poolArray(events);
357
+ $poolArray(parentEvents);
358
+ return true;
359
+ }
360
+ $poolArray(events);
361
+ $poolArray(parentEvents);
362
+ }
363
+ break;
364
+ }
365
+ return false;
366
+ }
367
+ /**
368
+ * @description EventDispatcher オブジェクトに、特定のイベントタイプに対して登録されたリスナーがあるかどうかを確認します。
369
+ * Checks whether the EventDispatcher object has any listeners registered for a specific type of event.
370
+ *
371
+ * @param {string} type
372
+ * @return {boolean}
373
+ * @method
374
+ * @public
375
+ */
376
+ hasEventListener(type) {
377
+ type = `${type}`;
378
+ switch (type) {
379
+ case Event.ENTER_FRAME:
380
+ case Event.EXIT_FRAME:
381
+ case Event.FRAME_CONSTRUCTED:
382
+ case Event.RENDER:
383
+ case Event.ACTIVATE:
384
+ case Event.DEACTIVATE:
385
+ case "keyDown":
386
+ case "keyUp":
387
+ {
388
+ const player = $currentPlayer();
389
+ if (player
390
+ && player.broadcastEvents.size
391
+ && player.broadcastEvents.has(type)) {
392
+ const events = player.broadcastEvents.get(type) || $getArray();
393
+ for (let idx = 0; idx < events.length; idx++) {
394
+ if (events[idx].target === this) {
395
+ return true;
396
+ }
397
+ }
398
+ }
399
+ return false;
400
+ }
401
+ default:
402
+ return !!(this._$events
403
+ && this._$events.size
404
+ && this._$events.has(type));
405
+ }
406
+ }
407
+ /**
408
+ * @description EventDispatcher オブジェクトからリスナーを削除します。
409
+ * Removes a listener from the EventDispatcher object.
410
+ *
411
+ * @param {string} type
412
+ * @param {function} [listener = null]
413
+ * @param {boolean} [use_capture = false]
414
+ * @return {void}
415
+ * @method
416
+ * @public
417
+ */
418
+ removeEventListener(type, listener, use_capture = false) {
419
+ if (!listener) {
420
+ return;
421
+ }
422
+ type = `${type}`;
423
+ if (!this.hasEventListener(type)) {
424
+ return;
425
+ }
426
+ const player = $currentPlayer();
427
+ let events = null;
428
+ let isBroadcast = false;
429
+ switch (type) {
430
+ case Event.ENTER_FRAME:
431
+ case Event.EXIT_FRAME:
432
+ case Event.FRAME_CONSTRUCTED:
433
+ case Event.RENDER:
434
+ case Event.ACTIVATE:
435
+ case Event.DEACTIVATE:
436
+ case "keyDown":
437
+ case "keyUp":
438
+ isBroadcast = true;
439
+ if (player) {
440
+ events = player.broadcastEvents.get(type) || $getArray();
441
+ }
442
+ break;
443
+ default:
444
+ if (this._$events
445
+ && this._$events.size
446
+ && this._$events.has(type)) {
447
+ events = this._$events.get(type) || $getArray();
448
+ }
449
+ break;
450
+ }
451
+ if (!events) {
452
+ return;
453
+ }
454
+ // remove listener
455
+ for (let idx = 0; idx < events.length; ++idx) {
456
+ // event object
457
+ const obj = events[idx];
458
+ if (use_capture === obj.useCapture
459
+ && obj.listener === listener) {
460
+ events.splice(idx, 1);
461
+ break;
462
+ }
463
+ }
464
+ if (!events.length) {
465
+ if (isBroadcast) {
466
+ player.broadcastEvents.delete(type);
467
+ }
468
+ else {
469
+ if (!this._$events) {
470
+ return;
471
+ }
472
+ this._$events.delete(type);
473
+ if (!this._$events.size) {
474
+ $poolMap(this._$events);
475
+ this._$events = null;
476
+ }
477
+ }
478
+ return;
479
+ }
480
+ if (events.length > 1) {
481
+ // event sort(DESC)
482
+ events.sort(function (a, b) {
483
+ switch (true) {
484
+ case a.priority > b.priority:
485
+ return -1;
486
+ case a.priority < b.priority:
487
+ return 1;
488
+ default:
489
+ return 0;
490
+ }
491
+ });
492
+ }
493
+ if (isBroadcast) {
494
+ player.broadcastEvents.set(type, events);
495
+ }
496
+ else {
497
+ if (!this._$events) {
498
+ this._$events = $getMap();
499
+ }
500
+ this._$events.set(type, events);
501
+ }
502
+ }
503
+ /**
504
+ * @description EventDispatcherオブジェクトから指定したタイプのリスナーを全て削除します。
505
+ * Removes all listeners of the specified type from the EventDispatcher object.
506
+ *
507
+ * @param {string} type
508
+ * @param {boolean} [use_capture=false]
509
+ * @return {void}
510
+ * @method
511
+ * @public
512
+ */
513
+ removeAllEventListener(type, use_capture = false) {
514
+ type = `${type}`;
515
+ if (!this.hasEventListener(type)) {
516
+ return;
517
+ }
518
+ const player = $currentPlayer();
519
+ let events = null;
520
+ let isBroadcast = false;
521
+ switch (type) {
522
+ case Event.ENTER_FRAME:
523
+ case Event.EXIT_FRAME:
524
+ case Event.FRAME_CONSTRUCTED:
525
+ case Event.RENDER:
526
+ case Event.ACTIVATE:
527
+ case Event.DEACTIVATE:
528
+ case "keyDown":
529
+ case "keyUp":
530
+ isBroadcast = true;
531
+ if (player) {
532
+ events = player.broadcastEvents.get(type) || $getArray();
533
+ }
534
+ break;
535
+ default:
536
+ if (this._$events
537
+ && this._$events.size
538
+ && this._$events.has(type)) {
539
+ events = this._$events.get(type) || $getArray();
540
+ }
541
+ break;
542
+ }
543
+ if (!events) {
544
+ return;
545
+ }
546
+ // remove listener
547
+ const results = $getArray();
548
+ for (let idx = 0; idx < events.length; ++idx) {
549
+ // event object
550
+ const obj = events[idx];
551
+ if (use_capture !== obj.useCapture) {
552
+ results.push(obj);
553
+ }
554
+ }
555
+ if (!results.length) {
556
+ if (isBroadcast) {
557
+ player.broadcastEvents.delete(type);
558
+ }
559
+ else {
560
+ if (!this._$events) {
561
+ return;
562
+ }
563
+ this._$events.delete(type);
564
+ if (!this._$events.size) {
565
+ $poolMap(this._$events);
566
+ this._$events = null;
567
+ }
568
+ }
569
+ return;
570
+ }
571
+ if (results.length > 1) {
572
+ // event sort (DESC)
573
+ results.sort(function (a, b) {
574
+ switch (true) {
575
+ case a.priority > b.priority:
576
+ return -1;
577
+ case a.priority < b.priority:
578
+ return 1;
579
+ default:
580
+ return 0;
581
+ }
582
+ });
583
+ }
584
+ if (isBroadcast) {
585
+ player.broadcastEvents.set(type, results);
586
+ }
587
+ else {
588
+ if (!this._$events) {
589
+ this._$events = $getMap();
590
+ }
591
+ this._$events.set(type, results);
592
+ }
593
+ }
594
+ /**
595
+ * @description 指定されたイベントタイプについて、
596
+ * この EventDispatcher オブジェクトまたはその祖先にイベントリスナーが
597
+ * 登録されているかどうかを確認します。
598
+ * Checks whether an event listener is registered
599
+ * with this EventDispatcher object or
600
+ * any of its ancestors for the specified event type.
601
+ *
602
+ * @param {string} type
603
+ * @return {boolean}
604
+ * @method
605
+ * @public
606
+ */
607
+ willTrigger(type) {
608
+ if (this.hasEventListener(type)) {
609
+ return true;
610
+ }
611
+ if ("parent" in this) {
612
+ let parent = this.parent;
613
+ while (parent) {
614
+ if (parent.hasEventListener(type)) {
615
+ return true;
616
+ }
617
+ parent = parent.parent;
618
+ }
619
+ }
620
+ return false;
621
+ }
622
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * EventPhase クラスは、Event クラスの eventPhase プロパティの値を提供します。
3
+ *
4
+ * The EventPhase class provides values for the eventPhase property of the Event class.
5
+ *
6
+ * @class
7
+ * @memberOf next2d.events
8
+ */
9
+ export declare class EventPhase {
10
+ /**
11
+ * 指定されたクラスのストリングを返します。
12
+ * Returns the string representation of the specified class.
13
+ *
14
+ * @return {string}
15
+ * @default [class EventPhase]
16
+ * @method
17
+ * @static
18
+ */
19
+ static toString(): string;
20
+ /**
21
+ * @description 指定されたクラスの空間名を返します。
22
+ * Returns the space name of the specified class.
23
+ *
24
+ * @member {string}
25
+ * @default next2d.events.EventPhase
26
+ * @const
27
+ * @static
28
+ */
29
+ static get namespace(): string;
30
+ /**
31
+ * @description 指定されたオブジェクトのストリングを返します。
32
+ * Returns the string representation of the specified object.
33
+ *
34
+ * @return {string}
35
+ * @default [object EventPhase]
36
+ * @method
37
+ * @public
38
+ */
39
+ toString(): string;
40
+ /**
41
+ * @description 指定されたオブジェクトの空間名を返します。
42
+ * Returns the space name of the specified object.
43
+ *
44
+ * @member {string}
45
+ * @default next2d.events.EventPhase
46
+ * @const
47
+ * @public
48
+ */
49
+ get namespace(): string;
50
+ /**
51
+ * @description ターゲット段階(イベントフローの 2 番目の段階)です。
52
+ * The target phase, which is the second phase of the event flow.
53
+ *
54
+ * @return {number}
55
+ * @default 2
56
+ * @const
57
+ * @static
58
+ */
59
+ static get AT_TARGET(): number;
60
+ /**
61
+ * @description ターゲット段階(イベントフローの 2 番目の段階)です。
62
+ * The target phase, which is the second phase of the event flow.
63
+ *
64
+ * @return {number}
65
+ * @default 3
66
+ * @const
67
+ * @static
68
+ */
69
+ static get BUBBLING_PHASE(): number;
70
+ /**
71
+ * @description キャプチャ段階(イベントフローの最初の段階)です。
72
+ * The capturing phase, which is the first phase of the event flow.
73
+ *
74
+ * @return {number}
75
+ * @default 1
76
+ * @const
77
+ * @static
78
+ */
79
+ static get CAPTURING_PHASE(): number;
80
+ }