~launchpad-pqm/lazr-js/toolchain

« back to all changes in this revision

Viewing changes to src-js/lazrjs/yui/event/event-synthetic.js

  • Committer: Sidnei da Silva
  • Date: 2009-11-16 00:51:29 UTC
  • mto: This revision was merged to the branch mainline in revision 154.
  • Revision ID: sidnei.da.silva@canonical.com-20091116005129-8ibwjlboa38glaw5
- Improved generation of skin modules and revamped combo service to make it more twisty.

Show diffs side-by-side

added added

removed removed

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