~lutostag/ubuntu/utopic/maas/1.5.2

« back to all changes in this revision

Viewing changes to src/maasserver/static/js/yui/3.4.1/event-synthetic/event-synthetic.js

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2012-03-15 18:14:08 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20120315181408-zgl94hzo0x4n99an
Tags: 0.1+bzr295+dfsg-0ubuntu2
* debian/patches:
  - 01-fix-database-settings.patch: Update to set PSERV_URL.
  - 02-pserv-config.patch: Set port to 8001.
* debian/maas.postinst: Run maas-import-isos on install.
* debian/control: Depends on rabbitmq-server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
YUI 3.4.1 (build 4118)
3
 
Copyright 2011 Yahoo! Inc. All rights reserved.
4
 
Licensed under the BSD License.
5
 
http://yuilibrary.com/license/
6
 
*/
7
 
YUI.add('event-synthetic', function(Y) {
8
 
 
9
 
/* Define new DOM events that can be subscribed to from Nodes.
10
 
 *
11
 
 * @module event
12
 
 * @submodule event-synthetic
13
 
 */
14
 
var DOMMap   = Y.Env.evt.dom_map,
15
 
    toArray  = Y.Array,
16
 
    YLang    = Y.Lang,
17
 
    isObject = YLang.isObject,
18
 
    isString = YLang.isString,
19
 
    isArray  = YLang.isArray,
20
 
    query    = Y.Selector.query,
21
 
    noop     = function () {};
22
 
 
23
 
/**
24
 
 * <p>The triggering mechanism used by SyntheticEvents.</p>
25
 
 *
26
 
 * <p>Implementers should not instantiate these directly.  Use the Notifier
27
 
 * provided to the event's implemented <code>on(node, sub, notifier)</code> or
28
 
 * <code>delegate(node, sub, notifier, filter)</code> methods.</p>
29
 
 *
30
 
 * @class SyntheticEvent.Notifier
31
 
 * @constructor
32
 
 * @param handle {EventHandle} the detach handle for the subscription to an
33
 
 *              internal custom event used to execute the callback passed to
34
 
 *              on(..) or delegate(..)
35
 
 * @param emitFacade {Boolean} take steps to ensure the first arg received by
36
 
 *              the subscription callback is an event facade
37
 
 * @private
38
 
 * @since 3.2.0
39
 
 */
40
 
function Notifier(handle, emitFacade) {
41
 
    this.handle     = handle;
42
 
    this.emitFacade = emitFacade;
43
 
}
44
 
 
45
 
/**
46
 
 * <p>Executes the subscription callback, passing the firing arguments as the
47
 
 * first parameters to that callback. For events that are configured with
48
 
 * emitFacade=true, it is common practice to pass the triggering DOMEventFacade
49
 
 * as the first parameter.  Barring a proper DOMEventFacade or EventFacade
50
 
 * (from a CustomEvent), a new EventFacade will be generated.  In that case, if
51
 
 * fire() is called with a simple object, it will be mixed into the facade.
52
 
 * Otherwise, the facade will be prepended to the callback parameters.</p>
53
 
 *
54
 
 * <p>For notifiers provided to delegate logic, the first argument should be an
55
 
 * object with a &quot;currentTarget&quot; property to identify what object to
56
 
 * default as 'this' in the callback.  Typically this is gleaned from the
57
 
 * DOMEventFacade or EventFacade, but if configured with emitFacade=false, an
58
 
 * object must be provided.  In that case, the object will be removed from the
59
 
 * callback parameters.</p>
60
 
 *
61
 
 * <p>Additional arguments passed during event subscription will be
62
 
 * automatically added after those passed to fire().</p>
63
 
 *
64
 
 * @method fire
65
 
 * @param e {EventFacade|DOMEventFacade|Object|any} (see description)
66
 
 * @param arg* {any} additional arguments received by all subscriptions
67
 
 * @private
68
 
 */
69
 
Notifier.prototype.fire = function (e) {
70
 
    // first arg to delegate notifier should be an object with currentTarget
71
 
    var args     = toArray(arguments, 0, true),
72
 
        handle   = this.handle,
73
 
        ce       = handle.evt,
74
 
        sub      = handle.sub,
75
 
        thisObj  = sub.context,
76
 
        delegate = sub.filter,
77
 
        event    = e || {},
78
 
        ret;
79
 
 
80
 
    if (this.emitFacade) {
81
 
        if (!e || !e.preventDefault) {
82
 
            event = ce._getFacade();
83
 
 
84
 
            if (isObject(e) && !e.preventDefault) {
85
 
                Y.mix(event, e, true);
86
 
                args[0] = event;
87
 
            } else {
88
 
                args.unshift(event);
89
 
            }
90
 
        }
91
 
 
92
 
        event.type    = ce.type;
93
 
        event.details = args.slice();
94
 
 
95
 
        if (delegate) {
96
 
            event.container = ce.host;
97
 
        }
98
 
    } else if (delegate && isObject(e) && e.currentTarget) {
99
 
        args.shift();
100
 
    }
101
 
 
102
 
    sub.context = thisObj || event.currentTarget || ce.host;
103
 
    ret = ce.fire.apply(ce, args);
104
 
    sub.context = thisObj; // reset for future firing
105
 
 
106
 
    // to capture callbacks that return false to stopPropagation.
107
 
    // Useful for delegate implementations
108
 
    return ret;
109
 
};
110
 
 
111
 
/**
112
 
 * Manager object for synthetic event subscriptions to aggregate multiple synths on the same node without colliding with actual DOM subscription entries in the global map of DOM subscriptions.  Also facilitates proper cleanup on page unload.
113
 
 *
114
 
 * @class SynthRegistry
115
 
 * @constructor
116
 
 * @param el {HTMLElement} the DOM element
117
 
 * @param yuid {String} the yuid stamp for the element
118
 
 * @param key {String} the generated id token used to identify an event type +
119
 
 *                     element in the global DOM subscription map.
120
 
 * @private
121
 
 */
122
 
function SynthRegistry(el, yuid, key) {
123
 
    this.handles = [];
124
 
    this.el      = el;
125
 
    this.key     = key;
126
 
    this.domkey  = yuid;
127
 
}
128
 
 
129
 
SynthRegistry.prototype = {
130
 
    constructor: SynthRegistry,
131
 
 
132
 
    // A few object properties to fake the CustomEvent interface for page
133
 
    // unload cleanup.  DON'T TOUCH!
134
 
    type      : '_synth',
135
 
    fn        : noop,
136
 
    capture   : false,
137
 
 
138
 
    /**
139
 
     * Adds a subscription from the Notifier registry.
140
 
     *
141
 
     * @method register
142
 
     * @param handle {EventHandle} the subscription
143
 
     * @since 3.4.0
144
 
     */
145
 
    register: function (handle) {
146
 
        handle.evt.registry = this;
147
 
        this.handles.push(handle);
148
 
    },
149
 
 
150
 
    /**
151
 
     * Removes the subscription from the Notifier registry.
152
 
     *
153
 
     * @method _unregisterSub
154
 
     * @param sub {Subscription} the subscription
155
 
     * @since 3.4.0
156
 
     */
157
 
    unregister: function (sub) {
158
 
        var handles = this.handles,
159
 
            events = DOMMap[this.domkey],
160
 
            i;
161
 
 
162
 
        for (i = handles.length - 1; i >= 0; --i) {
163
 
            if (handles[i].sub === sub) {
164
 
                handles.splice(i, 1);
165
 
                break;
166
 
            }
167
 
        }
168
 
 
169
 
        // Clean up left over objects when there are no more subscribers.
170
 
        if (!handles.length) {
171
 
            delete events[this.key];
172
 
            if (!Y.Object.size(events)) {
173
 
                delete DOMMap[this.domkey];
174
 
            }
175
 
        }
176
 
    },
177
 
 
178
 
    /**
179
 
     * Used by the event system's unload cleanup process.  When navigating
180
 
     * away from the page, the event system iterates the global map of element
181
 
     * subscriptions and detaches everything using detachAll().  Normally,
182
 
     * the map is populated with custom events, so this object needs to
183
 
     * at least support the detachAll method to duck type its way to
184
 
     * cleanliness.
185
 
     *
186
 
     * @method detachAll
187
 
     * @private
188
 
     * @since 3.4.0
189
 
     */
190
 
    detachAll : function () {
191
 
        var handles = this.handles,
192
 
            i = handles.length;
193
 
 
194
 
        while (--i >= 0) {
195
 
            handles[i].detach();
196
 
        }
197
 
    }
198
 
};
199
 
 
200
 
/**
201
 
 * <p>Wrapper class for the integration of new events into the YUI event
202
 
 * infrastructure.  Don't instantiate this object directly, use
203
 
 * <code>Y.Event.define(type, config)</code>.  See that method for details.</p>
204
 
 *
205
 
 * <p>Properties that MAY or SHOULD be specified in the configuration are noted
206
 
 * below and in the description of <code>Y.Event.define</code>.</p>
207
 
 *
208
 
 * @class SyntheticEvent
209
 
 * @constructor
210
 
 * @param cfg {Object} Implementation pieces and configuration
211
 
 * @since 3.1.0
212
 
 * @in event-synthetic
213
 
 */
214
 
function SyntheticEvent() {
215
 
    this._init.apply(this, arguments);
216
 
}
217
 
 
218
 
Y.mix(SyntheticEvent, {
219
 
    Notifier: Notifier,
220
 
    SynthRegistry: SynthRegistry,
221
 
 
222
 
    /**
223
 
     * Returns the array of subscription handles for a node for the given event
224
 
     * type.  Passing true as the third argument will create a registry entry
225
 
     * in the event system's DOM map to host the array if one doesn't yet exist.
226
 
     *
227
 
     * @method getRegistry
228
 
     * @param node {Node} the node
229
 
     * @param type {String} the event
230
 
     * @param create {Boolean} create a registration entry to host a new array
231
 
     *                  if one doesn't exist.
232
 
     * @return {Array}
233
 
     * @static
234
 
     * @protected
235
 
     * @since 3.2.0
236
 
     */
237
 
    getRegistry: function (node, type, create) {
238
 
        var el     = node._node,
239
 
            yuid   = Y.stamp(el),
240
 
            key    = 'event:' + yuid + type + '_synth',
241
 
            events = DOMMap[yuid];
242
 
            
243
 
        if (create) {
244
 
            if (!events) {
245
 
                events = DOMMap[yuid] = {};
246
 
            }
247
 
            if (!events[key]) {
248
 
                events[key] = new SynthRegistry(el, yuid, key);
249
 
            }
250
 
        }
251
 
 
252
 
        return (events && events[key]) || null;
253
 
    },
254
 
 
255
 
    /**
256
 
     * Alternate <code>_delete()</code> method for the CustomEvent object
257
 
     * created to manage SyntheticEvent subscriptions.
258
 
     *
259
 
     * @method _deleteSub
260
 
     * @param sub {Subscription} the subscription to clean up
261
 
     * @private
262
 
     * @since 3.2.0
263
 
     */
264
 
    _deleteSub: function (sub) {
265
 
        if (sub && sub.fn) {
266
 
            var synth = this.eventDef,
267
 
                method = (sub.filter) ? 'detachDelegate' : 'detach';
268
 
 
269
 
            this.subscribers = {};
270
 
            this.subCount = 0;
271
 
 
272
 
            synth[method](sub.node, sub, this.notifier, sub.filter);
273
 
            this.registry.unregister(sub);
274
 
 
275
 
            delete sub.fn;
276
 
            delete sub.node;
277
 
            delete sub.context;
278
 
        }
279
 
    },
280
 
 
281
 
    prototype: {
282
 
        constructor: SyntheticEvent,
283
 
 
284
 
        /**
285
 
         * Construction logic for the event.
286
 
         *
287
 
         * @method _init
288
 
         * @protected
289
 
         */
290
 
        _init: function () {
291
 
            var config = this.publishConfig || (this.publishConfig = {});
292
 
 
293
 
            // The notification mechanism handles facade creation
294
 
            this.emitFacade = ('emitFacade' in config) ?
295
 
                                config.emitFacade :
296
 
                                true;
297
 
            config.emitFacade  = false;
298
 
        },
299
 
 
300
 
        /**
301
 
         * <p>Implementers MAY provide this method definition.</p>
302
 
         *
303
 
         * <p>Implement this function if the event supports a different
304
 
         * subscription signature.  This function is used by both
305
 
         * <code>on()</code> and <code>delegate()</code>.  The second parameter
306
 
         * indicates that the event is being subscribed via
307
 
         * <code>delegate()</code>.</p>
308
 
         *
309
 
         * <p>Implementations must remove extra arguments from the args list
310
 
         * before returning.  The required args for <code>on()</code>
311
 
         * subscriptions are</p>
312
 
         * <pre><code>[type, callback, target, context, argN...]</code></pre>
313
 
         *
314
 
         * <p>The required args for <code>delegate()</code>
315
 
         * subscriptions are</p>
316
 
         *
317
 
         * <pre><code>[type, callback, target, filter, context, argN...]</code></pre>
318
 
         *
319
 
         * <p>The return value from this function will be stored on the
320
 
         * subscription in the '_extra' property for reference elsewhere.</p>
321
 
         *
322
 
         * @method processArgs
323
 
         * @param args {Array} parmeters passed to Y.on(..) or Y.delegate(..)
324
 
         * @param delegate {Boolean} true if the subscription is from Y.delegate
325
 
         * @return {any}
326
 
         */
327
 
        processArgs: noop,
328
 
 
329
 
        /**
330
 
         * <p>Implementers MAY override this property.</p>
331
 
         *
332
 
         * <p>Whether to prevent multiple subscriptions to this event that are
333
 
         * classified as being the same.  By default, this means the subscribed
334
 
         * callback is the same function.  See the <code>subMatch</code>
335
 
         * method.  Setting this to true will impact performance for high volume
336
 
         * events.</p>
337
 
         *
338
 
         * @property preventDups
339
 
         * @type {Boolean}
340
 
         * @default false
341
 
         */
342
 
        //preventDups  : false,
343
 
 
344
 
        /**
345
 
         * <p>Implementers SHOULD provide this method definition.</p>
346
 
         *
347
 
         * Implementation logic for subscriptions done via <code>node.on(type,
348
 
         * fn)</code> or <code>Y.on(type, fn, target)</code>.  This
349
 
         * function should set up the monitor(s) that will eventually fire the
350
 
         * event.  Typically this involves subscribing to at least one DOM
351
 
         * event.  It is recommended to store detach handles from any DOM
352
 
         * subscriptions to make for easy cleanup in the <code>detach</code>
353
 
         * method.  Typically these handles are added to the <code>sub</code>
354
 
         * object.  Also for SyntheticEvents that leverage a single DOM
355
 
         * subscription under the hood, it is recommended to pass the DOM event
356
 
         * object to <code>notifier.fire(e)</code>.  (The event name on the
357
 
         * object will be updated).
358
 
         *
359
 
         * @method on
360
 
         * @param node {Node} the node the subscription is being applied to
361
 
         * @param sub {Subscription} the object to track this subscription
362
 
         * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
363
 
         *              trigger the execution of the subscribers
364
 
         */
365
 
        on: noop,
366
 
 
367
 
        /**
368
 
         * <p>Implementers SHOULD provide this method definition.</p>
369
 
         *
370
 
         * <p>Implementation logic for detaching subscriptions done via
371
 
         * <code>node.on(type, fn)</code>.  This function should clean up any
372
 
         * subscriptions made in the <code>on()</code> phase.</p>
373
 
         *
374
 
         * @method detach
375
 
         * @param node {Node} the node the subscription was applied to
376
 
         * @param sub {Subscription} the object tracking this subscription
377
 
         * @param notifier {SyntheticEvent.Notifier} the Notifier used to
378
 
         *              trigger the execution of the subscribers
379
 
         */
380
 
        detach: noop,
381
 
 
382
 
        /**
383
 
         * <p>Implementers SHOULD provide this method definition.</p>
384
 
         *
385
 
         * <p>Implementation logic for subscriptions done via
386
 
         * <code>node.delegate(type, fn, filter)</code> or
387
 
         * <code>Y.delegate(type, fn, container, filter)</code>.  Like with
388
 
         * <code>on()</code> above, this function should monitor the environment
389
 
         * for the event being fired, and trigger subscription execution by
390
 
         * calling <code>notifier.fire(e)</code>.</p>
391
 
         *
392
 
         * <p>This function receives a fourth argument, which is the filter
393
 
         * used to identify which Node's are of interest to the subscription.
394
 
         * The filter will be either a boolean function that accepts a target
395
 
         * Node for each hierarchy level as the event bubbles, or a selector
396
 
         * string.  To translate selector strings into filter functions, use
397
 
         * <code>Y.delegate.compileFilter(filter)</code>.</p>
398
 
         *
399
 
         * @method delegate
400
 
         * @param node {Node} the node the subscription is being applied to
401
 
         * @param sub {Subscription} the object to track this subscription
402
 
         * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
403
 
         *              trigger the execution of the subscribers
404
 
         * @param filter {String|Function} Selector string or function that
405
 
         *              accepts an event object and returns null, a Node, or an
406
 
         *              array of Nodes matching the criteria for processing.
407
 
         * @since 3.2.0
408
 
         */
409
 
        delegate       : noop,
410
 
 
411
 
        /**
412
 
         * <p>Implementers SHOULD provide this method definition.</p>
413
 
         *
414
 
         * <p>Implementation logic for detaching subscriptions done via
415
 
         * <code>node.delegate(type, fn, filter)</code> or
416
 
         * <code>Y.delegate(type, fn, container, filter)</code>.  This function
417
 
         * should clean up any subscriptions made in the
418
 
         * <code>delegate()</code> phase.</p>
419
 
         *
420
 
         * @method detachDelegate
421
 
         * @param node {Node} the node the subscription was applied to
422
 
         * @param sub {Subscription} the object tracking this subscription
423
 
         * @param notifier {SyntheticEvent.Notifier} the Notifier used to
424
 
         *              trigger the execution of the subscribers
425
 
         * @param filter {String|Function} Selector string or function that
426
 
         *              accepts an event object and returns null, a Node, or an
427
 
         *              array of Nodes matching the criteria for processing.
428
 
         * @since 3.2.0
429
 
         */
430
 
        detachDelegate : noop,
431
 
 
432
 
        /**
433
 
         * Sets up the boilerplate for detaching the event and facilitating the
434
 
         * execution of subscriber callbacks.
435
 
         *
436
 
         * @method _on
437
 
         * @param args {Array} array of arguments passed to
438
 
         *              <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
439
 
         * @param delegate {Boolean} true if called from
440
 
         * <code>Y.delegate(...)</code>
441
 
         * @return {EventHandle} the detach handle for this subscription
442
 
         * @private
443
 
         * since 3.2.0
444
 
         */
445
 
        _on: function (args, delegate) {
446
 
            var handles  = [],
447
 
                originalArgs = args.slice(),
448
 
                extra    = this.processArgs(args, delegate),
449
 
                selector = args[2],
450
 
                method   = delegate ? 'delegate' : 'on',
451
 
                nodes, handle;
452
 
 
453
 
            // Can't just use Y.all because it doesn't support window (yet?)
454
 
            nodes = (isString(selector)) ?
455
 
                query(selector) :
456
 
                toArray(selector || Y.one(Y.config.win));
457
 
 
458
 
            if (!nodes.length && isString(selector)) {
459
 
                handle = Y.on('available', function () {
460
 
                    Y.mix(handle, Y[method].apply(Y, originalArgs), true);
461
 
                }, selector);
462
 
 
463
 
                return handle;
464
 
            }
465
 
 
466
 
            Y.Array.each(nodes, function (node) {
467
 
                var subArgs = args.slice(),
468
 
                    filter;
469
 
 
470
 
                node = Y.one(node);
471
 
 
472
 
                if (node) {
473
 
                    if (delegate) {
474
 
                        filter = subArgs.splice(3, 1)[0];
475
 
                    }
476
 
 
477
 
                    // (type, fn, el, thisObj, ...) => (fn, thisObj, ...)
478
 
                    subArgs.splice(0, 4, subArgs[1], subArgs[3]);
479
 
 
480
 
                    if (!this.preventDups ||
481
 
                        !this.getSubs(node, args, null, true))
482
 
                    {
483
 
                        handles.push(this._subscribe(node, method, subArgs, extra, filter));
484
 
                    }
485
 
                }
486
 
            }, this);
487
 
 
488
 
            return (handles.length === 1) ?
489
 
                handles[0] :
490
 
                new Y.EventHandle(handles);
491
 
        },
492
 
 
493
 
        /**
494
 
         * Creates a new Notifier object for use by this event's
495
 
         * <code>on(...)</code> or <code>delegate(...)</code> implementation
496
 
         * and register the custom event proxy in the DOM system for cleanup.
497
 
         *
498
 
         * @method _subscribe
499
 
         * @param node {Node} the Node hosting the event
500
 
         * @param method {String} "on" or "delegate"
501
 
         * @param args {Array} the subscription arguments passed to either
502
 
         *              <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
503
 
         *              after running through <code>processArgs(args)</code> to
504
 
         *              normalize the argument signature
505
 
         * @param extra {any} Extra data parsed from
506
 
         *              <code>processArgs(args)</code>
507
 
         * @param filter {String|Function} the selector string or function
508
 
         *              filter passed to <code>Y.delegate(...)</code> (not
509
 
         *              present when called from <code>Y.on(...)</code>)
510
 
         * @return {EventHandle}
511
 
         * @private
512
 
         * @since 3.2.0
513
 
         */
514
 
        _subscribe: function (node, method, args, extra, filter) {
515
 
            var dispatcher = new Y.CustomEvent(this.type, this.publishConfig),
516
 
                handle     = dispatcher.on.apply(dispatcher, args),
517
 
                notifier   = new Notifier(handle, this.emitFacade),
518
 
                registry   = SyntheticEvent.getRegistry(node, this.type, true),
519
 
                sub        = handle.sub;
520
 
 
521
 
            sub.node   = node;
522
 
            sub.filter = filter;
523
 
            if (extra) {
524
 
                this.applyArgExtras(extra, sub);
525
 
            }
526
 
 
527
 
            Y.mix(dispatcher, {
528
 
                eventDef     : this,
529
 
                notifier     : notifier,
530
 
                host         : node,       // I forget what this is for
531
 
                currentTarget: node,       // for generating facades
532
 
                target       : node,       // for generating facades
533
 
                el           : node._node, // For category detach
534
 
 
535
 
                _delete      : SyntheticEvent._deleteSub
536
 
            }, true);
537
 
 
538
 
            handle.notifier = notifier;
539
 
 
540
 
            registry.register(handle);
541
 
 
542
 
            // Call the implementation's "on" or "delegate" method
543
 
            this[method](node, sub, notifier, filter);
544
 
 
545
 
            return handle;
546
 
        },
547
 
 
548
 
        /**
549
 
         * <p>Implementers MAY provide this method definition.</p>
550
 
         *
551
 
         * <p>Implement this function if you want extra data extracted during
552
 
         * processArgs to be propagated to subscriptions on a per-node basis.
553
 
         * That is to say, if you call <code>Y.on('xyz', fn, xtra, 'div')</code>
554
 
         * the data returned from processArgs will be shared
555
 
         * across the subscription objects for all the divs.  If you want each
556
 
         * subscription to receive unique information, do that processing
557
 
         * here.</p>
558
 
         *
559
 
         * <p>The default implementation adds the data extracted by processArgs
560
 
         * to the subscription object as <code>sub._extra</code>.</p>
561
 
         *
562
 
         * @method applyArgExtras
563
 
         * @param extra {any} Any extra data extracted from processArgs
564
 
         * @param sub {Subscription} the individual subscription
565
 
         */
566
 
        applyArgExtras: function (extra, sub) {
567
 
            sub._extra = extra;
568
 
        },
569
 
 
570
 
        /**
571
 
         * Removes the subscription(s) from the internal subscription dispatch
572
 
         * mechanism.  See <code>SyntheticEvent._deleteSub</code>.
573
 
         *
574
 
         * @method _detach
575
 
         * @param args {Array} The arguments passed to
576
 
         *                  <code>node.detach(...)</code>
577
 
         * @private
578
 
         * @since 3.2.0
579
 
         */
580
 
        _detach: function (args) {
581
 
            // Can't use Y.all because it doesn't support window (yet?)
582
 
            // TODO: Does Y.all support window now?
583
 
            var target = args[2],
584
 
                els    = (isString(target)) ?
585
 
                            query(target) : toArray(target),
586
 
                node, i, len, handles, j;
587
 
 
588
 
            // (type, fn, el, context, filter?) => (type, fn, context, filter?)
589
 
            args.splice(2, 1);
590
 
 
591
 
            for (i = 0, len = els.length; i < len; ++i) {
592
 
                node = Y.one(els[i]);
593
 
 
594
 
                if (node) {
595
 
                    handles = this.getSubs(node, args);
596
 
 
597
 
                    if (handles) {
598
 
                        for (j = handles.length - 1; j >= 0; --j) {
599
 
                            handles[j].detach();
600
 
                        }
601
 
                    }
602
 
                }
603
 
            }
604
 
        },
605
 
 
606
 
        /**
607
 
         * Returns the detach handles of subscriptions on a node that satisfy a
608
 
         * search/filter function.  By default, the filter used is the
609
 
         * <code>subMatch</code> method.
610
 
         *
611
 
         * @method getSubs
612
 
         * @param node {Node} the node hosting the event
613
 
         * @param args {Array} the array of original subscription args passed
614
 
         *              to <code>Y.on(...)</code> (before
615
 
         *              <code>processArgs</code>
616
 
         * @param filter {Function} function used to identify a subscription
617
 
         *              for inclusion in the returned array
618
 
         * @param first {Boolean} stop after the first match (used to check for
619
 
         *              duplicate subscriptions)
620
 
         * @return {EventHandle[]} detach handles for the matching subscriptions
621
 
         */
622
 
        getSubs: function (node, args, filter, first) {
623
 
            var registry = SyntheticEvent.getRegistry(node, this.type),
624
 
                handles  = [],
625
 
                allHandles, i, len, handle;
626
 
 
627
 
            if (registry) {
628
 
                allHandles = registry.handles;
629
 
 
630
 
                if (!filter) {
631
 
                    filter = this.subMatch;
632
 
                }
633
 
 
634
 
                for (i = 0, len = allHandles.length; i < len; ++i) {
635
 
                    handle = allHandles[i];
636
 
                    if (filter.call(this, handle.sub, args)) {
637
 
                        if (first) {
638
 
                            return handle;
639
 
                        } else {
640
 
                            handles.push(allHandles[i]);
641
 
                        }
642
 
                    }
643
 
                }
644
 
            }
645
 
 
646
 
            return handles.length && handles;
647
 
        },
648
 
 
649
 
        /**
650
 
         * <p>Implementers MAY override this to define what constitutes a
651
 
         * &quot;same&quot; subscription.  Override implementations should
652
 
         * consider the lack of a comparator as a match, so calling
653
 
         * <code>getSubs()</code> with no arguments will return all subs.</p>
654
 
         *
655
 
         * <p>Compares a set of subscription arguments against a Subscription
656
 
         * object to determine if they match.  The default implementation
657
 
         * compares the callback function against the second argument passed to
658
 
         * <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
659
 
         *
660
 
         * @method subMatch
661
 
         * @param sub {Subscription} the existing subscription
662
 
         * @param args {Array} the calling arguments passed to
663
 
         *                  <code>Y.on(...)</code> etc.
664
 
         * @return {Boolean} true if the sub can be described by the args
665
 
         *                  present
666
 
         * @since 3.2.0
667
 
         */
668
 
        subMatch: function (sub, args) {
669
 
            // Default detach cares only about the callback matching
670
 
            return !args[1] || sub.fn === args[1];
671
 
        }
672
 
    }
673
 
}, true);
674
 
 
675
 
Y.SyntheticEvent = SyntheticEvent;
676
 
 
677
 
/**
678
 
 * <p>Defines a new event in the DOM event system.  Implementers are
679
 
 * responsible for monitoring for a scenario whereby the event is fired.  A
680
 
 * notifier object is provided to the functions identified below.  When the
681
 
 * criteria defining the event are met, call notifier.fire( [args] ); to
682
 
 * execute event subscribers.</p>
683
 
 *
684
 
 * <p>The first parameter is the name of the event.  The second parameter is a
685
 
 * configuration object which define the behavior of the event system when the
686
 
 * new event is subscribed to or detached from.  The methods that should be
687
 
 * defined in this configuration object are <code>on</code>,
688
 
 * <code>detach</code>, <code>delegate</code>, and <code>detachDelegate</code>.
689
 
 * You are free to define any other methods or properties needed to define your
690
 
 * event.  Be aware, however, that since the object is used to subclass
691
 
 * SyntheticEvent, you should avoid method names used by SyntheticEvent unless
692
 
 * your intention is to override the default behavior.</p>
693
 
 *
694
 
 * <p>This is a list of properties and methods that you can or should specify
695
 
 * in the configuration object:</p>
696
 
 *
697
 
 * <dl>
698
 
 *   <dt><code>on</code></dt>
699
 
 *       <dd><code>function (node, subscription, notifier)</code> The
700
 
 *       implementation logic for subscription.  Any special setup you need to
701
 
 *       do to create the environment for the event being fired--E.g. native
702
 
 *       DOM event subscriptions.  Store subscription related objects and
703
 
 *       state on the <code>subscription</code> object.  When the
704
 
 *       criteria have been met to fire the synthetic event, call
705
 
 *       <code>notifier.fire(e)</code>.  See Notifier's <code>fire()</code>
706
 
 *       method for details about what to pass as parameters.</dd>
707
 
 *
708
 
 *   <dt><code>detach</code></dt>
709
 
 *       <dd><code>function (node, subscription, notifier)</code> The
710
 
 *       implementation logic for cleaning up a detached subscription. E.g.
711
 
 *       detach any DOM subscriptions added in <code>on</code>.</dd>
712
 
 *
713
 
 *   <dt><code>delegate</code></dt>
714
 
 *       <dd><code>function (node, subscription, notifier, filter)</code> The
715
 
 *       implementation logic for subscription via <code>Y.delegate</code> or
716
 
 *       <code>node.delegate</code>.  The filter is typically either a selector
717
 
 *       string or a function.  You can use
718
 
 *       <code>Y.delegate.compileFilter(selectorString)</code> to create a
719
 
 *       filter function from a selector string if needed.  The filter function
720
 
 *       expects an event object as input and should output either null, a
721
 
 *       matching Node, or an array of matching Nodes.  Otherwise, this acts
722
 
 *       like <code>on</code> DOM event subscriptions.  Store subscription
723
 
 *       related objects and information on the <code>subscription</code>
724
 
 *       object.  When the criteria have been met to fire the synthetic event,
725
 
 *       call <code>notifier.fire(e)</code> as noted above.</dd>
726
 
 *
727
 
 *   <dt><code>detachDelegate</code></dt>
728
 
 *       <dd><code>function (node, subscription, notifier)</code> The
729
 
 *       implementation logic for cleaning up a detached delegate subscription.
730
 
 *       E.g. detach any DOM delegate subscriptions added in
731
 
 *       <code>delegate</code>.</dd>
732
 
 *
733
 
 *   <dt><code>publishConfig</code></dt>
734
 
 *       <dd>(Object) The configuration object that will be used to instantiate
735
 
 *       the underlying CustomEvent. See Notifier's <code>fire</code> method
736
 
 *       for details.</dd>
737
 
 *
738
 
 *   <dt><code>processArgs</code></dt
739
 
 *       <dd>
740
 
 *          <p><code>function (argArray, fromDelegate)</code> Optional method
741
 
 *          to extract any additional arguments from the subscription
742
 
 *          signature.  Using this allows <code>on</code> or
743
 
 *          <code>delegate</code> signatures like
744
 
 *          <code>node.on(&quot;hover&quot;, overCallback,
745
 
 *          outCallback)</code>.</p>
746
 
 *          <p>When processing an atypical argument signature, make sure the
747
 
 *          args array is returned to the normal signature before returning
748
 
 *          from the function.  For example, in the &quot;hover&quot; example
749
 
 *          above, the <code>outCallback</code> needs to be <code>splice</code>d
750
 
 *          out of the array.  The expected signature of the args array for
751
 
 *          <code>on()</code> subscriptions is:</p>
752
 
 *          <pre>
753
 
 *              <code>[type, callback, target, contextOverride, argN...]</code>
754
 
 *          </pre>
755
 
 *          <p>And for <code>delegate()</code>:</p>
756
 
 *          <pre>
757
 
 *              <code>[type, callback, target, filter, contextOverride, argN...]</code>
758
 
 *          </pre>
759
 
 *          <p>where <code>target</code> is the node the event is being
760
 
 *          subscribed for.  You can see these signatures documented for
761
 
 *          <code>Y.on()</code> and <code>Y.delegate()</code> respectively.</p>
762
 
 *          <p>Whatever gets returned from the function will be stored on the
763
 
 *          <code>subscription</code> object under
764
 
 *          <code>subscription._extra</code>.</p></dd>
765
 
 *   <dt><code>subMatch</code></dt>
766
 
 *       <dd>
767
 
 *           <p><code>function (sub, args)</code>  Compares a set of
768
 
 *           subscription arguments against a Subscription object to determine
769
 
 *           if they match.  The default implementation compares the callback
770
 
 *           function against the second argument passed to
771
 
 *           <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
772
 
 *       </dd>
773
 
 * </dl>
774
 
 *
775
 
 * @method define
776
 
 * @param type {String} the name of the event
777
 
 * @param config {Object} the prototype definition for the new event (see above)
778
 
 * @param force {Boolean} override an existing event (use with caution)
779
 
 * @return {SyntheticEvent} the subclass implementation instance created to
780
 
 *              handle event subscriptions of this type
781
 
 * @static
782
 
 * @for Event
783
 
 * @since 3.1.0
784
 
 * @in event-synthetic
785
 
 */
786
 
Y.Event.define = function (type, config, force) {
787
 
    var eventDef, Impl, synth;
788
 
 
789
 
    if (type && type.type) {
790
 
        eventDef = type;
791
 
        force = config;
792
 
    } else if (config) {
793
 
        eventDef = Y.merge({ type: type }, config);
794
 
    }
795
 
 
796
 
    if (eventDef) {
797
 
        if (force || !Y.Node.DOM_EVENTS[eventDef.type]) {
798
 
            Impl = function () {
799
 
                SyntheticEvent.apply(this, arguments);
800
 
            };
801
 
            Y.extend(Impl, SyntheticEvent, eventDef);
802
 
            synth = new Impl();
803
 
 
804
 
            type = synth.type;
805
 
 
806
 
            Y.Node.DOM_EVENTS[type] = Y.Env.evt.plugins[type] = {
807
 
                eventDef: synth,
808
 
 
809
 
                on: function () {
810
 
                    return synth._on(toArray(arguments));
811
 
                },
812
 
 
813
 
                delegate: function () {
814
 
                    return synth._on(toArray(arguments), true);
815
 
                },
816
 
 
817
 
                detach: function () {
818
 
                    return synth._detach(toArray(arguments));
819
 
                }
820
 
            };
821
 
 
822
 
        }
823
 
    } else if (isString(type) || isArray(type)) {
824
 
        Y.Array.each(toArray(type), function (t) {
825
 
            Y.Node.DOM_EVENTS[t] = 1;
826
 
        });
827
 
    }
828
 
 
829
 
    return synth;
830
 
};
831
 
 
832
 
 
833
 
}, '3.4.1' ,{requires:['node-base', 'event-custom-complex']});