PageSourceSearch

https://maavoimat.fi/o/frontend-js-aui-web/aui/event-custom-complex/event-custom-complex.js

js maavoimat.fi collected 2026-10-02 03:56:55 UTC 16,808 bytes, 670 lines download raw bytes

1YUI.add('event-custom-complex', function (Y, NAME) {
2
3
4/**
5 * Adds event facades, preventable default behavior, and bubbling.
6 * events.
7 * @module event-custom
8 * @submodule event-custom-complex
9 */
10
11var FACADE,
12    FACADE_KEYS,
13    YObject = Y.Object,
14    key,
15    EMPTY = {},
16    CEProto = Y.CustomEvent.prototype,
17    ETProto = Y.EventTarget.prototype,
18
19    mixFacadeProps = function(facade, payload) {
20        var p;
21
22        for (p in payload) {
23            if (!(FACADE_KEYS.hasOwnProperty(p))) {
24                facade[p] = payload[p];
25            }
26        }
27    };
28
29/**
30 * Wraps and protects a custom event for use when emitFacade is set to true.
31 * Requires the event-custom-complex module
32 * @class EventFacade
33 * @param e {Event} the custom event
34 * @param currentTarget {HTMLElement} the element the listener was attached to
35 */
36
37Y.EventFacade = function(e, currentTarget) {
38
39    if (!e) {
40        e = EMPTY;
41    }
42
43    this._event = e;
44
45    /**
46     * The arguments passed to fire
47     * @property details
48     * @type Array
49     */
50    this.details = e.details;
51
52    /**
53     * The event type, this can be overridden by the fire() payload
54     * @property type
55     * @type string
56     */
57    this.type = e.type;
58
59    /**
60     * The real event type
61     * @property _type
62     * @type string
63     * @private
64     */
65    this._type = e.type;
66
67    //////////////////////////////////////////////////////
68
69    /**
70     * Node reference for the targeted eventtarget
71     * @property target
72     * @type Node
73     */
74    this.target = e.target;
75
76    /**
77     * Node reference for the element that the listener was attached to.
78     * @property currentTarget
79     * @type Node
80     */
81    this.currentTarget = currentTarget;
82
83    /**
84     * Node reference to the relatedTarget
85     * @property relatedTarget
86     * @type Node
87     */
88    this.relatedTarget = e.relatedTarget;
89
90};
91
92Y.mix(Y.EventFacade.prototype, {
93
94    /**
95     * Stops the propagation to the next bubble target
96     * @method stopPropagation
97     */
98    stopPropagation: function() {
99        this._event.stopPropagation();
100        this.stopped = 1;
101    },
102
103    /**
104     * Stops the propagation to the next bubble target and
105     * prevents any additional listeners from being exectued
106     * on the current target.
107     * @method stopImmediatePropagation
108     */
109    stopImmediatePropagation: function() {
110        this._event.stopImmediatePropagation();
111        this.stopped = 2;
112    },
113
114    /**
115     * Prevents the event's default behavior
116     * @method preventDefault
117     */
118    preventDefault: function() {
119        this._event.preventDefault();
120        this.prevented = 1;
121    },
122
123    /**
124     * Stops the event propagation and prevents the default
125     * event behavior.
126     * @method halt
127     * @param immediate {boolean} if true additional listeners
128     * on the current target will not be executed
129     */
130    halt: function(immediate) {
131        this._event.halt(immediate);
132        this.prevented = 1;
133        this.stopped = (immediate) ? 2 : 1;
134    }
135
136});
137
138CEProto.fireComplex = function(args) {
139
140    var es,
141        ef,
142        q,
143        queue,
144        ce,
145        ret = true,
146        events,
147        subs,
148        ons,
149        afters,
150        afterQueue,
151        postponed,
152        prevented,
153        preventedFn,
154        defaultFn,
155        self = this,
156        host = self.host || self,
157        next,
158        oldbubble,
159        stack = self.stack,
160        yuievt = host._yuievt,
161        hasPotentialSubscribers;
162
163    if (stack) {
164
165        // queue this event if the current item in the queue bubbles
166        if (self.queuable && self.type !== stack.next.type) {
167
168            if (!stack.queue) {
169                stack.queue = [];
170            }
171            stack.queue.push([self, args]);
172
173            return true;
174        }
175    }
176
177    hasPotentialSubscribers = self.hasSubs() || yuievt.hasTargets || self.broadcast;
178
179    self.target = self.target || host;
180    self.currentTarget = host;
181
182    self.details = args.concat();
183
184    if (hasPotentialSubscribers) {
185
186        es = stack || {
187
188           id: self.id, // id of the first event in the stack
189           next: self,
190           silent: self.silent,
191           stopped: 0,
192           prevented: 0,
193           bubbling: null,
194           type: self.type,
195           // defaultFnQueue: new Y.Queue(),
196           defaultTargetOnly: self.defaultTargetOnly
197
198        };
199
200        subs = self.getSubs();
201        ons = subs[0];
202        afters = subs[1];
203
204        self.stopped = (self.type !== es.type) ? 0 : es.stopped;
205        self.prevented = (self.type !== es.type) ? 0 : es.prevented;
206
207        if (self.stoppedFn) {
208            // PERF TODO: Can we replace with callback, like preventedFn. Look into history
209            events = new Y.EventTarget({
210                fireOnce: true,
211                context: host
212            });
213            self.events = events;
214            events.on('stopped', self.stoppedFn);
215        }
216
217
218        self._facade = null; // kill facade to eliminate stale properties
219
220        ef = self._createFacade(args);
221
222        if (ons) {
223            self._procSubs(ons, args, ef);
224        }
225
226        // bubble if this is hosted in an event target and propagation has not been stopped
227        if (self.bubbles && host.bubble && !self.stopped) {
228            oldbubble = es.bubbling;
229
230            es.bubbling = self.type;
231
232            if (es.type !== self.type) {
233                es.stopped = 0;
234                es.prevented = 0;
235            }
236
237            ret = host.bubble(self, args, null, es);
238
239            self.stopped = Math.max(self.stopped, es.stopped);
240            self.prevented = Math.max(self.prevented, es.prevented);
241
242            es.bubbling = oldbubble;
243        }
244
245        prevented = self.prevented;
246
247        if (prevented) {
248            preventedFn = self.preventedFn;
249            if (preventedFn) {
250                preventedFn.apply(host, args);
251            }
252        } else {
253            defaultFn = self.defaultFn;
254
255            if (defaultFn && ((!self.defaultTargetOnly && !es.defaultTargetOnly) || host === ef.target)) {
256                defaultFn.apply(host, args);
257            }
258        }
259
260        // broadcast listeners are fired as discreet events on the
261        // YUI instance and potentially the YUI global.
262        if (self.broadcast) {
263            self._broadcast(args);
264        }
265
266        if (afters && !self.prevented && self.stopped < 2) {
267
268            // Queue the after
269            afterQueue = es.afterQueue;
270
271            if (es.id === self.id || self.type !== yuievt.bubbling) {
272
273                self._procSubs(afters, args, ef);
274
275                if (afterQueue) {
276                    while ((next = afterQueue.last())) {
277                        next();
278                    }
279                }
280            } else {
281                postponed = afters;
282
283                if (es.execDefaultCnt) {
284                    postponed = Y.merge(postponed);
285
286                    Y.each(postponed, function(s) {
287                        s.postponed = true;
288                    });
289                }
290
291                if (!afterQueue) {
292                    es.afterQueue = new Y.Queue();
293                }
294
295                es.afterQueue.add(function() {
296                    self._procSubs(postponed, args, ef);
297                });
298            }
299
300        }
301
302        self.target = null;
303
304        if (es.id === self.id) {
305
306            queue = es.queue;
307
308            if (queue) {
309                while (queue.length) {
310                    q = queue.pop();
311                    ce = q[0];
312                    // set up stack to allow the next item to be processed
313                    es.next = ce;
314                    ce._fire(q[1]);
315                }
316            }
317
318            self.stack = null;
319        }
320
321        ret = !(self.stopped);
322
323        if (self.type !== yuievt.bubbling) {
324            es.stopped = 0;
325            es.prevented = 0;
326            self.stopped = 0;
327            self.prevented = 0;
328        }
329
330    } else {
331        defaultFn = self.defaultFn;
332
333        if(defaultFn) {
334            ef = self._createFacade(args);
335
336            if ((!self.defaultTargetOnly) || (host === ef.target)) {
337                defaultFn.apply(host, args);
338            }
339        }
340    }
341
342    // Kill the cached facade to free up memory.
343    // Otherwise we have the facade from the last fire, sitting around forever.
344    self._facade = null;
345
346    return ret;
347};
348
349/**
350 * @method _hasPotentialSubscribers
351 * @for CustomEvent
352 * @private
353 * @return {boolean} Whether the event has potential subscribers or not
354 */
355CEProto._hasPotentialSubscribers = function() {
356    return this.hasSubs() || this.host._yuievt.hasTargets || this.broadcast;
357};
358
359/**
360 * Internal utility method to create a new facade instance and
361 * insert it into the fire argument list, accounting for any payload
362 * merging which needs to happen.
363 *
364 * This used to be called `_getFacade`, but the name seemed inappropriate
365 * when it was used without a need for the return value.
366 *
367 * @method _createFacade
368 * @private
369 * @param fireArgs {Array} The arguments passed to "fire", which need to be
370 * shifted (and potentially merged) when the facade is added.
371 * @return {EventFacade} The event facade created.
372 */
373
374// TODO: Remove (private) _getFacade alias, once synthetic.js is updated.
375CEProto._createFacade = CEProto._getFacade = function(fireArgs) {
376
377    var userArgs = this.details,
378        firstArg = userArgs && userArgs[0],
379        firstArgIsObj = (firstArg && (typeof firstArg === "object")),
380        ef = this._facade;
381
382    if (!ef) {
383        ef = new Y.EventFacade(this, this.currentTarget);
384    }
385
386    if (firstArgIsObj) {
387        // protect the event facade properties
388        mixFacadeProps(ef, firstArg);
389
390        // Allow the event type to be faked http://yuilibrary.com/projects/yui3/ticket/2528376
391        if (firstArg.type) {
392            ef.type = firstArg.type;
393        }
394
395        if (fireArgs) {
396            fireArgs[0] = ef;
397        }
398    } else {
399        if (fireArgs) {
400            fireArgs.unshift(ef);
401        }
402    }
403
404    // update the details field with the arguments
405    ef.details = this.details;
406
407    // use the original target when the event bubbled to this target
408    ef.target = this.originalTarget || this.target;
409
410    ef.currentTarget = this.currentTarget;
411    ef.stopped = 0;
412    ef.prevented = 0;
413
414    this._facade = ef;
415
416    return this._facade;
417};
418
419/**
420 * Utility method to manipulate the args array passed in, to add the event facade,
421 * if it's not already the first arg.
422 *
423 * @method _addFacadeToArgs
424 * @private
425 * @param {Array} The arguments to manipulate
426 */
427CEProto._addFacadeToArgs = function(args) {
428    var e = args[0];
429
430    // Trying not to use instanceof, just to avoid potential cross Y edge case issues.
431    if (!(e && e.halt && e.stopImmediatePropagation && e.stopPropagation && e._event)) {
432        this._createFacade(args);
433    }
434};
435
436/**
437 * Stop propagation to bubble targets
438 * @for CustomEvent
439 * @method stopPropagation
440 */
441CEProto.stopPropagation = function() {
442    this.stopped = 1;
443    if (this.stack) {
444        this.stack.stopped = 1;
445    }
446    if (this.events) {
447        this.events.fire('stopped', this);
448    }
449};
450
451/**
452 * Stops propagation to bubble targets, and prevents any remaining
453 * subscribers on the current target from executing.
454 * @method stopImmediatePropagation
455 */
456CEProto.stopImmediatePropagation = function() {
457    this.stopped = 2;
458    if (this.stack) {
459        this.stack.stopped = 2;
460    }
461    if (this.events) {
462        this.events.fire('stopped', this);
463    }
464};
465
466/**
467 * Prevents the execution of this event's defaultFn
468 * @method preventDefault
469 */
470CEProto.preventDefault = function() {
471    if (this.preventable) {
472        this.prevented = 1;
473        if (this.stack) {
474            this.stack.prevented = 1;
475        }
476    }
477};
478
479/**
480 * Stops the event propagation and prevents the default
481 * event behavior.
482 * @method halt
483 * @param immediate {boolean} if true additional listeners
484 * on the current target will not be executed
485 */
486CEProto.halt = function(immediate) {
487    if (immediate) {
488        this.stopImmediatePropagation();
489    } else {
490        this.stopPropagation();
491    }
492    this.preventDefault();
493};
494
495/**
496 * Registers another EventTarget as a bubble target.  Bubble order
497 * is determined by the order registered.  Multiple targets can
498 * be specified.
499 *
500 * Events can only bubble if emitFacade is true.
501 *
502 * Included in the event-custom-complex submodule.
503 *
504 * @method addTarget
505 * @chainable
506 * @param o {EventTarget} the target to add
507 * @for EventTarget
508 */
509ETProto.addTarget = function(o) {
510    var etState = this._yuievt;
511
512    if (!etState.targets) {
513        etState.targets = {};
514    }
515
516    etState.targets[Y.stamp(o)] = o;
517    etState.hasTargets = true;
518
519    return this;
520};
521
522/**
523 * Returns an array of bubble targets for this object.
524 * @method getTargets
525 * @return EventTarget[]
526 */
527ETProto.getTargets = function() {
528    var targets = this._yuievt.targets;
529    return targets ? YObject.values(targets) : [];
530};
531
532/**
533 * Removes a bubble target
534 * @method removeTarget
535 * @chainable
536 * @param o {EventTarget} the target to remove
537 * @for EventTarget
538 */
539ETProto.removeTarget = function(o) {
540    var targets = this._yuievt.targets;
541
542    if (targets) {
543        delete targets[Y.stamp(o, true)];
544
545        if (YObject.size(targets) === 0) {
546            this._yuievt.hasTargets = false;
547        }
548    }
549
550    return this;
551};
552
553/**
554 * Propagate an event.  Requires the event-custom-complex module.
555 * @method bubble
556 * @param evt {CustomEvent} the custom event to propagate
557 * @return {boolean} the aggregated return value from Event.Custom.fire
558 * @for EventTarget
559 */
560ETProto.bubble = function(evt, args, target, es) {
561
562    var targs = this._yuievt.targets,
563        ret = true,
564        t,
565        ce,
566        i,
567        bc,
568        ce2,
569        type = evt && evt.type,
570        originalTarget = target || (evt && evt.target) || this,
571        oldbubble;
572
573    if (!evt || ((!evt.stopped) && targs)) {
574
575        for (i in targs) {
576            if (targs.hasOwnProperty(i)) {
577
578                t = targs[i];
579
580                ce = t._yuievt.events[type];
581
582                if (t._hasSiblings) {
583                    ce2 = t.getSibling(type, ce);
584                }
585
586                if (ce2 && !ce) {
587                    ce = t.publish(type);
588                }
589
590                oldbubble = t._yuievt.bubbling;
591                t._yuievt.bubbling = type;
592
593                // if this event was not published on the bubble target,
594                // continue propagating the event.
595                if (!ce) {
596                    if (t._yuievt.hasTargets) {
597                        t.bubble(evt, args, originalTarget, es);
598                    }
599                } else {
600
601                    if (ce2) {
602                        ce.sibling = ce2;
603                    }
604
605                    // set the original target to that the target payload on the facade is correct.
606                    ce.target = originalTarget;
607                    ce.originalTarget = originalTarget;
608                    ce.currentTarget = t;
609                    bc = ce.broadcast;
610                    ce.broadcast = false;
611
612                    // default publish may not have emitFacade true -- that
613                    // shouldn't be what the implementer meant to do
614                    ce.emitFacade = true;
615
616                    ce.stack = es;
617
618                    // TODO: See what's getting in the way of changing this to use
619                    // the more performant ce._fire(args || evt.details || []).
620
621                    // Something in Widget Parent/Child tests is not happy if we
622                    // change it - maybe evt.details related?
623                    ret = ret && ce.fire.apply(ce, args || evt.details || []);
624
625                    ce.broadcast = bc;
626                    ce.originalTarget = null;
627
628                    // stopPropagation() was called
629                    if (ce.stopped) {
630                        break;
631                    }
632                }
633
634                t._yuievt.bubbling = oldbubble;
635            }
636        }
637    }
638
639    return ret;
640};
641
642/**
643 * @method _hasPotentialSubscribers
644 * @for EventTarget
645 * @private
646 * @param {String} fullType The fully prefixed type name
647 * @return {boolean} Whether the event has potential subscribers or not
648 */
649ETProto._hasPotentialSubscribers = function(fullType) {
650
651    var etState = this._yuievt,
652        e = etState.events[fullType];
653
654    if (e) {
655        return e.hasSubs() || etState.hasTargets  || e.broadcast;
656    } else {
657        return false;
658    }
659};
660
661FACADE = new Y.EventFacade();
662FACADE_KEYS = {};
663
664// Flatten whitelist
665for (key in FACADE) {
666    FACADE_KEYS[key] = true;
667}
668
669
670}, 'patched-v3.18.7', {"requires": ["event-custom-base"]});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.