/loggerhead/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/loggerhead/trunk

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/event/event.js

  • Committer: Martin Albisetti
  • Date: 2008-12-22 15:16:45 UTC
  • mfrom: (255 trunk)
  • mto: (157.1.8 loggerhead)
  • mto: This revision was merged to the branch mainline in revision 423.
  • Revision ID: argentina@gmail.com-20081222151645-vqxhqpr0fx9rc9t1
Merge from trunk revno 256

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0pr1
 
6
*/
 
7
/**
 
8
 * The YUI event system
 
9
 * @module event
 
10
 */
 
11
YUI.add("event", function(Y) {
 
12
 
 
13
    /**
 
14
     * Subscribes to the yui:load event, which fires when a Y.use operation
 
15
     * is complete.
 
16
     * @method ready
 
17
     * @param f {Function} the function to execute
 
18
     * @param c Optional execution context
 
19
     * @param args* 0..n Additional arguments to append 
 
20
     * to the signature provided when the event fires.
 
21
     * @return {YUI} the YUI instance
 
22
     */
 
23
    // Y.ready = function(f, c) {
 
24
    //     var a = arguments, m = (a.length > 1) ? Y.bind.apply(Y, a) : f;
 
25
    //     Y.on("yui:load", m);
 
26
    //     return this;
 
27
    // };
 
28
 
 
29
    /**
 
30
     * Attach an event listener, either to a DOM object
 
31
     * or to an Event.Target.
 
32
     * @param type {string} the event type
 
33
     * @param f {Function} the function to execute
 
34
     * @param o the Event.Target or element to attach to
 
35
     * @param context Optional execution context
 
36
     * @param args* 0..n additional arguments to append
 
37
     * to the signature provided when the event fires.
 
38
     * @method on
 
39
     * @for YUI
 
40
     * @return {Event.Handle} a handle object for 
 
41
     * unsubscribing to this event.
 
42
     */
 
43
    Y.on = function(type, f, o) {
 
44
 
 
45
        if (type.indexOf(':') > -1) {
 
46
            var cat = type.split(':');
 
47
            switch (cat[0]) {
 
48
                default:
 
49
                    return Y.subscribe.apply(Y, arguments);
 
50
            }
 
51
        } else {
 
52
            return Y.Event.attach.apply(Y.Event, arguments);
 
53
        }
 
54
 
 
55
    };
 
56
 
 
57
    /**
 
58
     * Detach an event listener (either a custom event or a
 
59
     * DOM event
 
60
     * @method detach
 
61
     * @param type the type of event, or a Event.Handle to
 
62
     * for the subscription.  If the Event.Handle is passed
 
63
     * in, the other parameters are not used.
 
64
     * @param f {Function} the subscribed function
 
65
     * @param o the object or element the listener is subscribed
 
66
     * to.
 
67
     * @method detach
 
68
     * @return {YUI} the YUI instance
 
69
     */
 
70
    Y.detach = function(type, f, o) {
 
71
        if (Y.Lang.isObject(type) && type.detach) {
 
72
            return type.detach();
 
73
        } else if (type.indexOf(':') > -1) {
 
74
            var cat = type.split(':');
 
75
            switch (cat[0]) {
 
76
                default:
 
77
                    return Y.unsubscribe.apply(Y, arguments);
 
78
            }
 
79
        } else {
 
80
            return Y.Event.detach.apply(Y.Event, arguments);
 
81
        }
 
82
    };
 
83
 
 
84
    /**
 
85
     * Executes the callback before a DOM event, custom event
 
86
     * or method.  If the first argument is a function, it
 
87
     * is assumed the target is a method.
 
88
     *
 
89
     * For DOM and custom events:
 
90
     * type, callback, context, 1-n arguments
 
91
     *  
 
92
     * For methods:
 
93
     * callback, object (method host), methodName, context, 1-n arguments
 
94
     *
 
95
     * @method before
 
96
     * @return unsubscribe handle
 
97
     */
 
98
    Y.before = function(type, f, o) { 
 
99
        // method override
 
100
        // callback, object, sMethod
 
101
        if (Y.Lang.isFunction(type)) {
 
102
            return Y.Do.before.apply(Y.Do, arguments);
 
103
        }
 
104
 
 
105
        return Y;
 
106
    };
 
107
 
 
108
    /**
 
109
     * Executes the callback after a DOM event, custom event
 
110
     * or method.  If the first argument is a function, it
 
111
     * is assumed the target is a method.
 
112
     *
 
113
     * @TODO add event
 
114
     *
 
115
     * For DOM and custom events:
 
116
     * type, callback, context, 1-n arguments
 
117
     *  
 
118
     * For methods:
 
119
     * callback, object (method host), methodName, context, 1-n arguments
 
120
     *
 
121
     * @method after
 
122
     * @return {Event.Handle} unsubscribe handle
 
123
     */
 
124
    Y.after = function(type, f, o) {
 
125
        if (Y.Lang.isFunction(type)) {
 
126
            return Y.Do.after.apply(Y.Do, arguments);
 
127
        }
 
128
 
 
129
        return Y;
 
130
    };
 
131
 
 
132
}, "3.0.0", {
 
133
    use: [
 
134
          "aop", 
 
135
          "event-custom", 
 
136
          "event-target", 
 
137
          "event-ready",
 
138
          "event-dom", 
 
139
          "event-facade"
 
140
          ]
 
141
});
 
142
/*
 
143
 * Method displacement
 
144
 * @submodule event-aop
 
145
 * @module event
 
146
 */
 
147
YUI.add("aop", function(Y) {
 
148
 
 
149
    var BEFORE = 0,
 
150
        AFTER = 1;
 
151
 
 
152
    /**
 
153
     * Allows for the insertion of methods that are executed before or after
 
154
     * a specified method
 
155
     * @class Do
 
156
     * @static
 
157
     */
 
158
    Y.Do = {
 
159
 
 
160
        /**
 
161
         * Cache of objects touched by the utility
 
162
         * @property objs
 
163
         * @static
 
164
         */
 
165
        objs: {},
 
166
 
 
167
        /**
 
168
         * Execute the supplied method before the specified function
 
169
         * @method before
 
170
         * @param fn {Function} the function to execute
 
171
         * @param obj the object hosting the method to displace
 
172
         * @param sFn {string} the name of the method to displace
 
173
         * @param c The execution context for fn
 
174
         * @return {string} handle for the subscription
 
175
         * @static
 
176
         */
 
177
        before: function(fn, obj, sFn, c) {
 
178
            var f = fn;
 
179
            if (c) {
 
180
                var a = [fn, c].concat(Y.Array(arguments, 4, true));
 
181
                f = Y.bind.apply(Y, a);
 
182
            }
 
183
 
 
184
            return this._inject(BEFORE, f, obj, sFn);
 
185
        },
 
186
 
 
187
        /**
 
188
         * Execute the supplied method after the specified function
 
189
         * @method after
 
190
         * @param fn {Function} the function to execute
 
191
         * @param obj the object hosting the method to displace
 
192
         * @param sFn {string} the name of the method to displace
 
193
         * @param c The execution context for fn
 
194
         * @return {string} handle for the subscription
 
195
         * @static
 
196
         */
 
197
        after: function(fn, obj, sFn, c) {
 
198
            var f = fn;
 
199
            if (c) {
 
200
                var a = [fn, c].concat(Y.Array(arguments, 4, true));
 
201
                f = Y.bind.apply(Y, a);
 
202
            }
 
203
 
 
204
            return this._inject(AFTER, f, obj, sFn);
 
205
        },
 
206
 
 
207
        /**
 
208
         * Execute the supplied method after the specified function
 
209
         * @method _inject
 
210
         * @param when {string} before or after
 
211
         * @param fn {Function} the function to execute
 
212
         * @param obj the object hosting the method to displace
 
213
         * @param sFn {string} the name of the method to displace
 
214
         * @param c The execution context for fn
 
215
         * @return {string} handle for the subscription
 
216
         * @private
 
217
         * @static
 
218
         */
 
219
        _inject: function(when, fn, obj, sFn) {
 
220
 
 
221
            // object id
 
222
            var id = Y.stamp(obj);
 
223
 
 
224
            if (! this.objs[id]) {
 
225
                // create a map entry for the obj if it doesn't exist
 
226
                this.objs[id] = {};
 
227
            }
 
228
            var o = this.objs[id];
 
229
 
 
230
            if (! o[sFn]) {
 
231
                // create a map entry for the method if it doesn't exist
 
232
                o[sFn] = new Y.Do.Method(obj, sFn);
 
233
 
 
234
                // re-route the method to our wrapper
 
235
                obj[sFn] = 
 
236
                    function() {
 
237
                        return o[sFn].exec.apply(o[sFn], arguments);
 
238
                    };
 
239
            }
 
240
 
 
241
            // subscriber id
 
242
            var sid = id + Y.stamp(fn) + sFn;
 
243
 
 
244
            // register the callback
 
245
            o[sFn].register(sid, fn, when);
 
246
 
 
247
            return sid;
 
248
 
 
249
        },
 
250
 
 
251
        /**
 
252
         * Detach a before or after subscription
 
253
         * @method detach
 
254
         * @param sid {string} the subscription handle
 
255
         */
 
256
        detach: function(sid) {
 
257
            delete this.before[sid];
 
258
            delete this.after[sid];
 
259
        },
 
260
 
 
261
        _unload: function(e, me) {
 
262
 
 
263
        }
 
264
    };
 
265
 
 
266
    //////////////////////////////////////////////////////////////////////////
 
267
 
 
268
    /**
 
269
     * Wrapper for a displaced method with aop enabled
 
270
     * @class Do.Method
 
271
     * @constructor
 
272
     * @param obj The object to operate on
 
273
     * @param sFn The name of the method to displace
 
274
     */
 
275
    Y.Do.Method = function(obj, sFn) {
 
276
        this.obj = obj;
 
277
        this.methodName = sFn;
 
278
        this.method = obj[sFn];
 
279
        // this.before = [];
 
280
        // this.after = [];
 
281
        this.before = {};
 
282
        this.after = {};
 
283
    };
 
284
 
 
285
    /**
 
286
     * Register a aop subscriber
 
287
     * @method register
 
288
     * @param sid {string} the subscriber id
 
289
     * @param fn {Function} the function to execute
 
290
     * @param when {string} when to execute the function
 
291
     */
 
292
    Y.Do.Method.prototype.register = function (sid, fn, when) {
 
293
        if (when) {
 
294
            // this.after.push(fn);
 
295
            this.after[sid] = fn;
 
296
        } else {
 
297
            // this.before.push(fn);
 
298
            this.before[sid] = fn;
 
299
        }
 
300
    };
 
301
 
 
302
    /**
 
303
     * Execute the wrapped method
 
304
     * @method exec
 
305
     */
 
306
    Y.Do.Method.prototype.exec = function () {
 
307
 
 
308
        var args = Y.Array(arguments, 0, true), 
 
309
            i, ret, newRet, 
 
310
            bf = this.before,
 
311
            af = this.after;
 
312
 
 
313
        // for (i=0; i<this.before.length; ++i) {
 
314
        for (i in bf) {
 
315
            if (bf.hasOwnProperty(i)) {
 
316
                ret = bf[i].apply(this.obj, args);
 
317
 
 
318
                // Stop processing if an Error is returned
 
319
                if (ret && ret.constructor == Y.Do.Error) {
 
320
                    return ret.retVal;
 
321
                // Check for altered arguments
 
322
                } else if (ret && ret.constructor == Y.Do.AlterArgs) {
 
323
                    args = ret.newArgs;
 
324
                }
 
325
            }
 
326
        }
 
327
 
 
328
        // execute method
 
329
        ret = this.method.apply(this.obj, args);
 
330
 
 
331
        // execute after methods.
 
332
        // for (i=0; i<this.after.length; ++i) {
 
333
        for (i in af) {
 
334
            if (af.hasOwnProperty(i)) {
 
335
                newRet = af[i].apply(this.obj, args);
 
336
                // Stop processing if an Error is returned
 
337
                if (newRet && newRet.constructor == Y.Do.Error) {
 
338
                    return newRet.retVal;
 
339
                // Check for a new return value
 
340
                } else if (newRet && newRet.constructor == Y.Do.AlterReturn) {
 
341
                    ret = newRet.newRetVal;
 
342
                }
 
343
            }
 
344
        }
 
345
 
 
346
        return ret;
 
347
    };
 
348
 
 
349
    //////////////////////////////////////////////////////////////////////////
 
350
 
 
351
    /**
 
352
     * Return an Error object when you want to terminate the execution
 
353
     * of all subsequent method calls
 
354
     * @class Do.Error
 
355
     */
 
356
    Y.Do.Error = function(msg, retVal) {
 
357
        this.msg = msg;
 
358
        this.retVal = retVal;
 
359
    };
 
360
 
 
361
    /**
 
362
     * Return an AlterArgs object when you want to change the arguments that
 
363
     * were passed into the function.  An example would be a service that scrubs
 
364
     * out illegal characters prior to executing the core business logic.
 
365
     * @class Do.AlterArgs
 
366
     */
 
367
    Y.Do.AlterArgs = function(msg, newArgs) {
 
368
        this.msg = msg;
 
369
        this.newArgs = newArgs;
 
370
    };
 
371
 
 
372
    /**
 
373
     * Return an AlterReturn object when you want to change the result returned
 
374
     * from the core method to the caller
 
375
     * @class Do.AlterReturn
 
376
     */
 
377
    Y.Do.AlterReturn = function(msg, newRetVal) {
 
378
        this.msg = msg;
 
379
        this.newRetVal = newRetVal;
 
380
    };
 
381
 
 
382
    //////////////////////////////////////////////////////////////////////////
 
383
 
 
384
// Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
 
385
 
 
386
}, "3.0.0");
 
387
/*
 
388
 * YUI Custom Events
 
389
 * @submodule event-custom
 
390
 * @module event
 
391
 */
 
392
YUI.add("event-custom", function(Y) {
 
393
 
 
394
    var onsubscribeType = "_event:onsub",
 
395
 
 
396
        AFTER = 'after', 
 
397
 
 
398
        CONFIGS = [
 
399
 
 
400
            'broadcast',
 
401
 
 
402
            'bubbles',
 
403
 
 
404
            'context',
 
405
 
 
406
            'configured',
 
407
 
 
408
            'currentTarget',
 
409
 
 
410
            'defaultFn',
 
411
 
 
412
            'details',
 
413
 
 
414
            'emitFacade',
 
415
 
 
416
            'fireOnce',
 
417
 
 
418
            'host',
 
419
 
 
420
            'preventable',
 
421
 
 
422
            'preventedFn',
 
423
 
 
424
            'queuable',
 
425
 
 
426
            'silent',
 
427
 
 
428
            'stoppedFn',
 
429
 
 
430
            'target',
 
431
 
 
432
            'type'
 
433
 
 
434
        ];
 
435
 
 
436
    /**
 
437
     * Return value from all subscribe operations
 
438
     * @class Event.Handle
 
439
     * @constructor
 
440
     * @param evt {Event.Custom} the custom event
 
441
     * @param sub {Event.Subscriber} the subscriber
 
442
     */
 
443
    Y.EventHandle = function(evt, sub) {
 
444
 
 
445
        /**
 
446
         * The custom event
 
447
         * @type Event.Custom
 
448
         */
 
449
        this.evt = evt;
 
450
 
 
451
        /**
 
452
         * The subscriber object
 
453
         * @type Event.Subscriber
 
454
         */
 
455
        this.sub = sub;
 
456
    };
 
457
 
 
458
    Y.EventHandle.prototype = {
 
459
        /**
 
460
         * Detaches this subscriber
 
461
         * @method detach
 
462
         */
 
463
        detach: function() {
 
464
            this.evt._delete(this.sub);
 
465
        }
 
466
    };
 
467
 
 
468
    /**
 
469
     * The Event.Custom class lets you define events for your application
 
470
     * that can be subscribed to by one or more independent component.
 
471
     *
 
472
     * @param {String}  type The type of event, which is passed to the callback
 
473
     *                  when the event fires
 
474
     * @param {Object}  context The context the event will fire from.  "this" will
 
475
     *                  refer to this object in the callback.  Default value: 
 
476
     *                  the window object.  The listener can override this.
 
477
     * @param {boolean} silent pass true to prevent the event from writing to
 
478
     *                  the debug system
 
479
     * @class Event.Custom
 
480
     * @constructor
 
481
     */
 
482
    Y.CustomEvent = function(type, o) {
 
483
 
 
484
        // if (arguments.length > 2) {
 
485
        // }
 
486
 
 
487
        o = o || {};
 
488
 
 
489
        this.id = Y.stamp(this);
 
490
 
 
491
        /**
 
492
         * The type of event, returned to subscribers when the event fires
 
493
         * @property type
 
494
         * @type string
 
495
         */
 
496
        this.type = type;
 
497
 
 
498
        /**
 
499
         * The context the the event will fire from by default.  Defaults to the YUI
 
500
         * instance.
 
501
         * @property context
 
502
         * @type object
 
503
         */
 
504
        this.context = Y;
 
505
 
 
506
 
 
507
        /**
 
508
         * If 0, this event does not broadcast.  If 1, the YUI instance is notified
 
509
         * every time this event fires.  If 2, the YUI instance and the YUI global
 
510
         * (if event is enabled on the global) are notified every time this event
 
511
         * fires.
 
512
         * @property broadcast
 
513
         * @type int
 
514
         */
 
515
        this.broadcast = 0;
 
516
 
 
517
        /**
 
518
         * By default all custom events are logged in the debug build, set silent
 
519
         * to true to disable debug outpu for this event.
 
520
         * @property silent
 
521
         * @type boolean
 
522
         */
 
523
 
 
524
        this.queuable = false;
 
525
 
 
526
        /**
 
527
         * The subscribers to this event
 
528
         * @property subscribers
 
529
         * @type Event.Subscriber{}
 
530
         */
 
531
        this.subscribers = {};
 
532
 
 
533
        /*
 
534
         * The publisher has configured this event
 
535
         * @property configured
 
536
         * @type boolean
 
537
         * @default true
 
538
         */
 
539
        // this.configured = true;
 
540
 
 
541
        /**
 
542
         * 'After' subscribers
 
543
         * @property afters
 
544
         * @type Event.Subscriber{}
 
545
         */
 
546
        this.afters = {};
 
547
 
 
548
        /**
 
549
         * This event has fired if true
 
550
         *
 
551
         * @property fired
 
552
         * @type boolean
 
553
         * @default false;
 
554
         */
 
555
        this.fired = false;
 
556
 
 
557
        /**
 
558
         * This event should only fire one time if true, and if
 
559
         * it has fired, any new subscribers should be notified
 
560
         * immediately.
 
561
         *
 
562
         * @property fireOnce
 
563
         * @type boolean
 
564
         * @default false;
 
565
         */
 
566
        this.fireOnce = false;
 
567
 
 
568
        /**
 
569
         * Flag for stopPropagation that is modified during fire()
 
570
         * 1 means to stop propagation to bubble targets.  2 means
 
571
         * to also stop additional subscribers on this target.
 
572
         * @property stopped
 
573
         * @type int
 
574
         */
 
575
        this.stopped = 0;
 
576
 
 
577
        /**
 
578
         * Flag for preventDefault that is modified during fire().
 
579
         * if it is not 0, the default behavior for this event
 
580
         * @property prevented
 
581
         * @type int
 
582
         */
 
583
        this.prevented = 0;
 
584
 
 
585
        /**
 
586
         * Specifies the host for this custom event.  This is used
 
587
         * to enable event bubbling
 
588
         * @property host
 
589
         * @type Event.Target
 
590
         */
 
591
        this.host = null;
 
592
 
 
593
        /**
 
594
         * The default function to execute after event listeners
 
595
         * have fire, but only if the default action was not
 
596
         * prevented.
 
597
         * @property defaultFn
 
598
         * @type Function
 
599
         */
 
600
        this.defaultFn = null;
 
601
 
 
602
        /**
 
603
         * The function to execute if a subscriber calls
 
604
         * stopPropagation or stopImmediatePropagation
 
605
         * @property stoppedFn
 
606
         * @type Function
 
607
         */
 
608
        this.stoppedFn = null;
 
609
 
 
610
        /**
 
611
         * The function to execute if a subscriber calls
 
612
         * preventDefault
 
613
         * @property preventedFn
 
614
         * @type Function
 
615
         */
 
616
        this.preventedFn = null;
 
617
 
 
618
        /**
 
619
         * Specifies whether or not this event's default function
 
620
         * can be cancelled by a subscriber by executing preventDefault() 
 
621
         * on the event facade 
 
622
         * @property preventable 
 
623
         * @type boolean 
 
624
         * @default true
 
625
         */
 
626
        this.preventable = true;
 
627
 
 
628
        /**
 
629
         * Specifies whether or not a subscriber can stop the event propagation
 
630
         * via stopPropagation(), stopImmediatePropagation(), or halt()
 
631
         * @property bubbles
 
632
         * @type boolean
 
633
         * @default true
 
634
         */
 
635
        this.bubbles = true;
 
636
 
 
637
        this.emitFacade = false;
 
638
 
 
639
        this.applyConfig(o, true);
 
640
 
 
641
 
 
642
        // Only add subscribe events for events that are not generated by 
 
643
        // Event.Custom
 
644
        if (type !== onsubscribeType) {
 
645
 
 
646
            /**
 
647
             * Custom events provide a custom event that fires whenever there is
 
648
             * a new subscriber to the event.  This provides an opportunity to
 
649
             * handle the case where there is a non-repeating event that has
 
650
             * already fired has a new subscriber.  
 
651
             *
 
652
             * @event subscribeEvent
 
653
             * @type Y.Event.Custom
 
654
             * @param {Function} fn The function to execute
 
655
             * @param {Object}   obj An object to be passed along when the event 
 
656
             *                       fires
 
657
             * @param {boolean|Object}  override If true, the obj passed in becomes 
 
658
             *                                   the execution context of the listener.
 
659
             *                                   if an object, that object becomes the
 
660
             *                                   the execution context.
 
661
             */
 
662
            this.subscribeEvent = new Y.CustomEvent(onsubscribeType, {
 
663
                    context: this,
 
664
                    silent: true
 
665
                });
 
666
        } 
 
667
 
 
668
    };
 
669
 
 
670
    Y.CustomEvent.prototype = {
 
671
 
 
672
        _YUI_EVENT: true,
 
673
 
 
674
        /**
 
675
         * Apply configuration properties.  Only applies the CONFIG whitelist
 
676
         * @method applyConfig
 
677
         * @param o hash of properties to apply
 
678
         * @param force {boolean} if true, properties that exist on the event 
 
679
         * will be overwritten.
 
680
         */
 
681
        applyConfig: function(o, force) {
 
682
            if (o) {
 
683
                Y.mix(this, o, force, CONFIGS);
 
684
            }
 
685
        },
 
686
 
 
687
        _subscribe: function(fn, obj, args, when) {
 
688
 
 
689
            if (!fn) {
 
690
                Y.fail("Invalid callback for CE: " + this.type);
 
691
            }
 
692
 
 
693
            var se = this.subscribeEvent;
 
694
            if (se) {
 
695
                se.fire.apply(se, args);
 
696
            }
 
697
 
 
698
            var s = new Y.Subscriber(fn, obj, args, when);
 
699
 
 
700
 
 
701
            if (this.fireOnce && this.fired) {
 
702
 
 
703
                // this._notify(s);
 
704
                // setTimeout(Y.bind(this._notify, this, s), 0);
 
705
                Y.later(0, this, this._notify, s);
 
706
            }
 
707
 
 
708
            if (when == AFTER) {
 
709
                this.afters[s.id] = s;
 
710
            } else {
 
711
                this.subscribers[s.id] = s;
 
712
            }
 
713
 
 
714
            return new Y.EventHandle(this, s);
 
715
 
 
716
        },
 
717
 
 
718
        /**
 
719
         * Listen for this event
 
720
         * @method subscribe
 
721
         * @param {Function} fn        The function to execute
 
722
         * @param {Object}   obj       An object to be passed along when the event fires
 
723
         * @param args* 1..n params to provide to the listener
 
724
         * @return {Event.Handle} unsubscribe handle
 
725
         */
 
726
        subscribe: function(fn, obj) {
 
727
            return this._subscribe(fn, obj, Y.Array(arguments, 2, true));
 
728
        },
 
729
 
 
730
        /**
 
731
         * Listen for this event after the normal subscribers have been notified and
 
732
         * the default behavior has been applied.  If a normal subscriber prevents the 
 
733
         * default behavior, it also prevents after listeners from firing.
 
734
         * @method after
 
735
         * @param {Function} fn        The function to execute
 
736
         * @param {Object}   obj       An object to be passed along when the event fires
 
737
         * @param args* 1..n params to provide to the listener
 
738
         * @return {Event.Handle} unsubscribe handle
 
739
         */
 
740
        after: function(fn, obj) {
 
741
            return this._subscribe(fn, obj, Y.Array(arguments, 2, true), AFTER);
 
742
        },
 
743
 
 
744
        /**
 
745
         * Unsubscribes subscribers.
 
746
         * @method unsubscribe
 
747
         * @param {Function} fn  The subscribed function to remove, if not supplied
 
748
         *                       all will be removed
 
749
         * @param {Object}   obj  The custom object passed to subscribe.  This is
 
750
         *                        optional, but if supplied will be used to
 
751
         *                        disambiguate multiple listeners that are the same
 
752
         *                        (e.g., you subscribe many object using a function
 
753
         *                        that lives on the prototype)
 
754
         * @return {boolean} True if the subscriber was found and detached.
 
755
         */
 
756
        unsubscribe: function(fn, obj) {
 
757
 
 
758
            // if arg[0] typeof unsubscribe handle
 
759
            if (fn && fn.detach) {
 
760
                return fn.detach();
 
761
            }
 
762
 
 
763
            if (!fn) {
 
764
                return this.unsubscribeAll();
 
765
            }
 
766
 
 
767
            var found = false, subs = this.subscribers;
 
768
            for (var i in subs) {
 
769
                if (subs.hasOwnProperty(i)) {
 
770
                    var s = subs[i];
 
771
                    if (s && s.contains(fn, obj)) {
 
772
                        this._delete(s);
 
773
                        found = true;
 
774
                    }
 
775
                }
 
776
            }
 
777
 
 
778
            return found;
 
779
        },
 
780
 
 
781
        _getFacade: function(args) {
 
782
 
 
783
            var ef = this._facade;
 
784
 
 
785
            if (!ef) {
 
786
                ef = new Y.Event.Facade(this, this.currentTarget);
 
787
            }
 
788
 
 
789
            // if the first argument is an object literal, apply the
 
790
            // properties to the event facade
 
791
            var o = args && args[0];
 
792
            if (Y.Lang.isObject(o, true) && !o._yuifacade) {
 
793
                Y.mix(ef, o, true);
 
794
            }
 
795
 
 
796
            // update the details field with the arguments
 
797
            ef.details = this.details;
 
798
            ef.target = this.target;
 
799
            ef.currentTarget = this.currentTarget;
 
800
            ef.stopped = 0;
 
801
            ef.prevented = 0;
 
802
 
 
803
            this._facade = ef;
 
804
 
 
805
            return this._facade;
 
806
        },
 
807
 
 
808
        /**
 
809
         * Notify a single subscriber
 
810
         * @method _notify
 
811
         * @param s {Event.Subscriber} the subscriber
 
812
         * @param args {Array} the arguments array to apply to the listener
 
813
         * @private
 
814
         */
 
815
        _notify: function(s, args, ef) {
 
816
 
 
817
 
 
818
            var ret;
 
819
 
 
820
            // emit an Event.Facade if this is that sort of event
 
821
            // if (this.emitFacade && (!args[0] || !args[0]._yuifacade)) {
 
822
            if (this.emitFacade) {
 
823
 
 
824
                // @TODO object literal support to fire makes it possible for
 
825
                // config info to be passed if we wish.
 
826
                
 
827
                if (!ef) {
 
828
                    ef = this._getFacade(args);
 
829
                    args[0] = ef;
 
830
                }
 
831
 
 
832
            }
 
833
             
 
834
            ret = s.notify(this.context, args);
 
835
 
 
836
            if (false === ret || this.stopped > 1) {
 
837
                return false;
 
838
            }
 
839
 
 
840
            return true;
 
841
        },
 
842
 
 
843
        /**
 
844
         * Logger abstraction to centralize the application of the silent flag
 
845
         * @method log
 
846
         * @param msg {string} message to log
 
847
         * @param cat {string} log category
 
848
         */
 
849
        log: function(msg, cat) {
 
850
            var es = Y.Env._eventstack, s =  es && es.silent;
 
851
            // if (!s && !this.silent) {
 
852
            if (!this.silent) {
 
853
            }
 
854
        },
 
855
 
 
856
        /**
 
857
         * Notifies the subscribers.  The callback functions will be executed
 
858
         * from the context specified when the event was created, and with the 
 
859
         * following parameters:
 
860
         *   <ul>
 
861
         *   <li>The type of event</li>
 
862
         *   <li>All of the arguments fire() was executed with as an array</li>
 
863
         *   <li>The custom object (if any) that was passed into the subscribe() 
 
864
         *       method</li>
 
865
         *   </ul>
 
866
         * @method fire 
 
867
         * @param {Object*} arguments an arbitrary set of parameters to pass to 
 
868
         *                            the handler.
 
869
         * @return {boolean} false if one of the subscribers returned false, 
 
870
         *                   true otherwise
 
871
         */
 
872
        fire: function() {
 
873
 
 
874
            var es = Y.Env._eventstack;
 
875
 
 
876
            if (es) {
 
877
 
 
878
                // var b = this.bubbles, h = this.host;
 
879
                // if (b && h) {
 
880
                //     b = (h._yuievt.targets.length);
 
881
                // }
 
882
 
 
883
                // es.silent = (es.silent || this.silent);
 
884
 
 
885
                // queue this event if the current item in the queue bubbles
 
886
                // if (b && this.queuable && this.type != es.next.type) {
 
887
                if (this.queuable && this.type != es.next.type) {
 
888
 
 
889
 
 
890
                    es.queue.push([this, arguments]);
 
891
                    return true;
 
892
                }
 
893
 
 
894
            } else {
 
895
 
 
896
                Y.Env._eventstack = {
 
897
                   // id of the first event in the stack
 
898
                   id: this.id,
 
899
                   next: this,
 
900
                   silent: this.silent,
 
901
                   logging: (this.type === 'yui:log'),
 
902
                   stopped: 0,
 
903
                   prevented: 0,
 
904
                   queue: []
 
905
                };
 
906
 
 
907
                es = Y.Env._eventstack;
 
908
            }
 
909
 
 
910
            var ret = true;
 
911
 
 
912
            if (this.fireOnce && this.fired) {
 
913
 
 
914
 
 
915
            } else {
 
916
 
 
917
                // var subs = this.subscribers.slice(), len=subs.length,
 
918
                var subs = Y.merge(this.subscribers), s,
 
919
                           args=Y.Array(arguments, 0, true), i;
 
920
 
 
921
                this.stopped = 0;
 
922
                this.prevented = 0;
 
923
                this.target = this.target || this.host;
 
924
 
 
925
                this.currentTarget = this.host || this.currentTarget;
 
926
 
 
927
                this.fired = true;
 
928
                this.details = args.slice(); // original arguments in the details
 
929
 
 
930
 
 
931
                var hasSub = false;
 
932
                es.lastLogState = es.logging;
 
933
 
 
934
 
 
935
                var ef = null;
 
936
                if (this.emitFacade) {
 
937
                    ef = this._getFacade(args);
 
938
                    args[0] = ef;
 
939
                }
 
940
 
 
941
                for (i in subs) {
 
942
                    if (subs.hasOwnProperty(i)) {
 
943
 
 
944
                        if (!hasSub) {
 
945
                            es.logging = (es.logging || (this.type === 'yui:log'));
 
946
                            hasSub = true;
 
947
                        }
 
948
 
 
949
                        // stopImmediatePropagation
 
950
                        if (this.stopped == 2) {
 
951
                            break;
 
952
                        }
 
953
 
 
954
                        s = subs[i];
 
955
                        if (s && s.fn) {
 
956
                            ret = this._notify(s, args, ef);
 
957
                            if (false === ret) {
 
958
                                this.stopped = 2;
 
959
                            }
 
960
                        }
 
961
                    }
 
962
                }
 
963
 
 
964
                es.logging = (es.lastLogState);
 
965
 
 
966
                // bubble if this is hosted in an event target and propagation has not been stopped
 
967
                // @TODO check if we need to worry about defaultFn order
 
968
                if (this.bubbles && this.host && !this.stopped) {
 
969
                    es.stopped = 0;
 
970
                    es.prevented = 0;
 
971
                    ret = this.host.bubble(this);
 
972
 
 
973
                    this.stopped = Math.max(this.stopped, es.stopped);
 
974
                    this.prevented = Math.max(this.prevented, es.prevented);
 
975
                }
 
976
 
 
977
                // execute the default behavior if not prevented
 
978
                // @TODO need context
 
979
                if (this.defaultFn && !this.prevented) {
 
980
                    this.defaultFn.apply(this.host || this, args);
 
981
                }
 
982
 
 
983
                // process after listeners.  If the default behavior was
 
984
                // prevented, the after events don't fire.
 
985
                if (!this.prevented && this.stopped < 2) {
 
986
                    subs = Y.merge(this.afters);
 
987
                    for (i in subs) {
 
988
                        if (subs.hasOwnProperty(i)) {
 
989
 
 
990
                            if (!hasSub) {
 
991
                                es.logging = (es.logging || (this.type === 'yui:log'));
 
992
                                hasSub = true;
 
993
                            }
 
994
 
 
995
                            // stopImmediatePropagation
 
996
                            if (this.stopped == 2) {
 
997
                                break;
 
998
                            }
 
999
 
 
1000
                            s = subs[i];
 
1001
                            if (s && s.fn) {
 
1002
                                ret = this._notify(s, args, ef);
 
1003
                                if (false === ret) {
 
1004
                                    this.stopped = 2;
 
1005
                                }
 
1006
                            }
 
1007
                        }
 
1008
                    }
 
1009
                }
 
1010
            }
 
1011
 
 
1012
            if (es.id === this.id) {
 
1013
// console.log('clearing stack: ' + es.id + ', ' + this);
 
1014
 
 
1015
// reset propragation properties while processing the rest of the queue
 
1016
 
 
1017
// process queued events
 
1018
                var queue = es.queue;
 
1019
 
 
1020
                while (queue.length) {
 
1021
                    // q[0] = the event, q[1] = arguments to fire
 
1022
                    var q = queue.pop(), ce = q[0];
 
1023
 
 
1024
                    es.stopped = 0;
 
1025
                    es.prevented = 0;
 
1026
                    
 
1027
// set up stack to allow the next item to be processed
 
1028
                    es.next = ce;
 
1029
 
 
1030
                    ret = ce.fire.apply(ce, q[1]);
 
1031
                }
 
1032
 
 
1033
                Y.Env._eventstack = null;
 
1034
            } 
 
1035
 
 
1036
            return (ret !== false);
 
1037
        },
 
1038
 
 
1039
        /**
 
1040
         * Removes all listeners
 
1041
         * @method unsubscribeAll
 
1042
         * @return {int} The number of listeners unsubscribed
 
1043
         */
 
1044
        unsubscribeAll: function() {
 
1045
            var subs = this.subscribers, i;
 
1046
            for (i in subs) {
 
1047
                if (subs.hasOwnProperty(i)) {
 
1048
                    this._delete(subs[i]);
 
1049
                }
 
1050
            }
 
1051
 
 
1052
            this.subscribers={};
 
1053
 
 
1054
            return i;
 
1055
        },
 
1056
 
 
1057
        /**
 
1058
         * @method _delete
 
1059
         * @param subscriber object
 
1060
         * @private
 
1061
         */
 
1062
        _delete: function(s) {
 
1063
 
 
1064
            if (s) {
 
1065
                delete s.fn;
 
1066
                delete s.obj;
 
1067
                delete this.subscribers[s.id];
 
1068
                delete this.afters[s.id];
 
1069
            }
 
1070
 
 
1071
        },
 
1072
 
 
1073
        /**
 
1074
         * @method toString
 
1075
         */
 
1076
        toString: function() {
 
1077
             // return "{ CE '" + this.type + "' " + "id: " + this.id +
 
1078
                  // ", host: " + (this.host && Y.stamp(this.host) + " }");
 
1079
             return this.type;
 
1080
        },
 
1081
 
 
1082
        /**
 
1083
         * Stop propagation to bubble targets
 
1084
         * @method stopPropagation
 
1085
         */
 
1086
        stopPropagation: function() {
 
1087
            this.stopped = 1;
 
1088
            Y.Env._eventstack.stopped = 1;
 
1089
            if (this.stoppedFn) {
 
1090
                this.stoppedFn.call(this.host || this, this);
 
1091
            }
 
1092
        },
 
1093
 
 
1094
        /**
 
1095
         * Stops propagation to bubble targets, and prevents any remaining
 
1096
         * subscribers on the current target from executing.
 
1097
         * @method stopImmediatePropagation
 
1098
         */
 
1099
        stopImmediatePropagation: function() {
 
1100
            this.stopped = 2;
 
1101
            Y.Env._eventstack.stopped = 2;
 
1102
            if (this.stoppedFn) {
 
1103
                this.stoppedFn.call(this.host || this, this);
 
1104
            }
 
1105
        },
 
1106
 
 
1107
        /**
 
1108
         * Prevents the execution of this event's defaultFn
 
1109
         * @method preventDefault
 
1110
         */
 
1111
        preventDefault: function() {
 
1112
            if (this.preventable) {
 
1113
                this.prevented = 1;
 
1114
                Y.Env._eventstack.prevented = 1;
 
1115
            }
 
1116
            if (this.preventedFn) {
 
1117
                this.preventedFn.call(this.host || this, this);
 
1118
            }
 
1119
        }
 
1120
 
 
1121
    };
 
1122
 
 
1123
    /////////////////////////////////////////////////////////////////////
 
1124
 
 
1125
    /**
 
1126
     * Stores the subscriber information to be used when the event fires.
 
1127
     * @param {Function} fn       The wrapped function to execute
 
1128
     * @param {Object}   obj      An object to be passed along when the event fires
 
1129
     * @param {Array} args        subscribe() additional arguments
 
1130
     *
 
1131
     * @class Event.Subscriber
 
1132
     * @constructor
 
1133
     */
 
1134
    Y.Subscriber = function(fn, obj, args) {
 
1135
 
 
1136
        /**
 
1137
         * The callback that will be execute when the event fires
 
1138
         * This is wrapped by Y.bind if obj was supplied.
 
1139
         * @property fn
 
1140
         * @type Function
 
1141
         */
 
1142
        this.fn = fn;
 
1143
 
 
1144
        /**
 
1145
         * An optional custom object that will passed to the callback when
 
1146
         * the event fires
 
1147
         * @property obj
 
1148
         * @type Object
 
1149
         */
 
1150
        this.obj = obj;
 
1151
 
 
1152
        /**
 
1153
         * Unique subscriber id
 
1154
         * @property id
 
1155
         * @type String
 
1156
         */
 
1157
        this.id = Y.stamp(this);
 
1158
 
 
1159
        /**
 
1160
         * Optional additional arguments supplied to subscribe().  If present,
 
1161
         * these will be appended to the arguments supplied to fire()
 
1162
         * @property args
 
1163
         * @type Array
 
1164
         */
 
1165
        // this.args = args;
 
1166
 
 
1167
        var m = fn;
 
1168
        
 
1169
        if (obj) {
 
1170
            var a = (args) ? Y.Array(args) : [];
 
1171
            a.unshift(fn, obj);
 
1172
            m = Y.bind.apply(Y, a);
 
1173
        }
 
1174
        
 
1175
        /**
 
1176
         * }
 
1177
         * fn bound to obj with additional arguments applied via Y.bind
 
1178
         * @property wrappedFn
 
1179
         * @type Function
 
1180
         */
 
1181
        this.wrappedFn = m;
 
1182
 
 
1183
    };
 
1184
 
 
1185
    Y.Subscriber.prototype = {
 
1186
 
 
1187
        /**
 
1188
         * Executes the subscriber.
 
1189
         * @method notify
 
1190
         * @param defaultContext The execution context if not overridden
 
1191
         * by the subscriber
 
1192
         * @param args {Array} Arguments array for the subscriber
 
1193
         */
 
1194
        notify: function(defaultContext, args) {
 
1195
            var c = this.obj || defaultContext, ret = true;
 
1196
 
 
1197
            try {
 
1198
                ret = this.wrappedFn.apply(c, args);
 
1199
            } catch(e) {
 
1200
                Y.fail(this + ' failed: ' + e.message, e);
 
1201
            }
 
1202
 
 
1203
            return ret;
 
1204
        },
 
1205
 
 
1206
        /**
 
1207
         * Returns true if the fn and obj match this objects properties.
 
1208
         * Used by the unsubscribe method to match the right subscriber.
 
1209
         *
 
1210
         * @method contains
 
1211
         * @param {Function} fn the function to execute
 
1212
         * @param {Object} obj an object to be passed along when the event fires
 
1213
         * @return {boolean} true if the supplied arguments match this 
 
1214
         *                   subscriber's signature.
 
1215
         */
 
1216
        contains: function(fn, obj) {
 
1217
            if (obj) {
 
1218
                return ((this.fn == fn) && this.obj == obj);
 
1219
            } else {
 
1220
                return (this.fn == fn);
 
1221
            }
 
1222
        },
 
1223
 
 
1224
        /**
 
1225
         * @method toString
 
1226
         */
 
1227
        toString: function() {
 
1228
            return "Subscriber " + this.id;
 
1229
        }
 
1230
    };
 
1231
 
 
1232
}, "3.0.0");
 
1233
/*
 
1234
 * Configures an object to be able to be targeted for events, and to publish events
 
1235
 * @submodule event-target
 
1236
 * @module event
 
1237
 */
 
1238
YUI.add("event-target", function(Y) {
 
1239
 
 
1240
    var SILENT = { 'yui:log': true };
 
1241
 
 
1242
    /**
 
1243
     * Event.Target is designed to be used with Y.augment to wrap 
 
1244
     * Event.Custom in an interface that allows events to be subscribed to 
 
1245
     * and fired by name.  This makes it possible for implementing code to
 
1246
     * subscribe to an event that either has not been created yet, or will
 
1247
     * not be created at all.
 
1248
     *
 
1249
     * @Class Event.Target
 
1250
     */
 
1251
    Y.EventTarget = function(opts) { 
 
1252
 
 
1253
        // console.log('Event.Target constructor executed: ' + this._yuid);
 
1254
 
 
1255
        var o = (Y.Lang.isObject(opts)) ? opts : {};
 
1256
 
 
1257
        this._yuievt = {
 
1258
 
 
1259
            events: {},
 
1260
 
 
1261
            targets: {},
 
1262
 
 
1263
            config: o,
 
1264
 
 
1265
            defaults: {
 
1266
                context: this, 
 
1267
                host: this,
 
1268
                emitFacade: o.emitFacade || false,
 
1269
                bubbles: ('bubbles' in o) ? o.bubbles : true
 
1270
            }
 
1271
            
 
1272
        };
 
1273
 
 
1274
    };
 
1275
 
 
1276
    var ET = Y.EventTarget;
 
1277
 
 
1278
    ET.prototype = {
 
1279
 
 
1280
        /**
 
1281
         * Subscribe to a custom event hosted by this object
 
1282
         * @method subscribe
 
1283
         * @param type    {string}   The type of the event
 
1284
         * @param fn {Function} The callback
 
1285
         * @param context The execution context
 
1286
         * @param args* 1..n params to supply to the callback
 
1287
         */
 
1288
        subscribe: function(type, fn, context) {
 
1289
 
 
1290
            var ce = this._yuievt.events[type] || 
 
1291
                // this.publish(type, {
 
1292
                //     configured: false
 
1293
                // }),
 
1294
                this.publish(type),
 
1295
                a = Y.Array(arguments, 1, true);
 
1296
 
 
1297
            return ce.subscribe.apply(ce, a);
 
1298
 
 
1299
        },
 
1300
 
 
1301
        /**
 
1302
         * Unsubscribes one or more listeners the from the specified event
 
1303
         * @method unsubscribe
 
1304
         * @param type {string|Object}   Either the handle to the subscriber or the 
 
1305
         *                        type of event.  If the type
 
1306
         *                        is not specified, it will attempt to remove
 
1307
         *                        the listener from all hosted events.
 
1308
         * @param fn   {Function} The subscribed function to unsubscribe, if not
 
1309
         *                          supplied, all subscribers will be removed.
 
1310
         * @param context  {Object}   The custom object passed to subscribe.  This is
 
1311
         *                        optional, but if supplied will be used to
 
1312
         *                        disambiguate multiple listeners that are the same
 
1313
         *                        (e.g., you subscribe many object using a function
 
1314
         *                        that lives on the prototype)
 
1315
         * @return {boolean} true if the subscriber was found and detached.
 
1316
         */
 
1317
        unsubscribe: function(type, fn, context) {
 
1318
 
 
1319
            // If this is an event handle, use it to detach
 
1320
            if (Y.Lang.isObject(type) && type.detach) {
 
1321
                return type.detach();
 
1322
            }
 
1323
 
 
1324
            var evts = this._yuievt.events;
 
1325
 
 
1326
            if (type) {
 
1327
                var ce = evts[type];
 
1328
                if (ce) {
 
1329
                    return ce.unsubscribe(fn, context);
 
1330
                }
 
1331
            } else {
 
1332
                var ret = true;
 
1333
                for (var i in evts) {
 
1334
                    if (Y.Object.owns(evts, i)) {
 
1335
                        ret = ret && evts[i].unsubscribe(fn, context);
 
1336
                    }
 
1337
                }
 
1338
                return ret;
 
1339
            }
 
1340
 
 
1341
            return false;
 
1342
        },
 
1343
        
 
1344
        /**
 
1345
         * Removes all listeners from the specified event.  If the event type
 
1346
         * is not specified, all listeners from all hosted custom events will
 
1347
         * be removed.
 
1348
         * @method unsubscribeAll
 
1349
         * @param type {string}   The type, or name of the event
 
1350
         */
 
1351
        unsubscribeAll: function(type) {
 
1352
            return this.unsubscribe(type);
 
1353
        },
 
1354
 
 
1355
        /**
 
1356
         * Creates a new custom event of the specified type.  If a custom event
 
1357
         * by that name already exists, it will not be re-created.  In either
 
1358
         * case the custom event is returned. 
 
1359
         *
 
1360
         * @method publish
 
1361
         *
 
1362
         * @param type {string} the type, or name of the event
 
1363
         * @param opts {object} optional config params.  Valid properties are:
 
1364
         *
 
1365
         *  <ul>
 
1366
         *    <li>
 
1367
         *   'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
 
1368
         *    </li>
 
1369
         *    <li>
 
1370
         *   'bubbles': whether or not this event bubbles (true)
 
1371
         *    </li>
 
1372
         *    <li>
 
1373
         *   'context': the default execution context for the listeners (this)
 
1374
         *    </li>
 
1375
         *    <li>
 
1376
         *   'defaultFn': the default function to execute when this event fires if preventDefault was not called
 
1377
         *    </li>
 
1378
         *    <li>
 
1379
         *   'emitFacade': whether or not this event emits a facade (false)
 
1380
         *    </li>
 
1381
         *    <li>
 
1382
         *   'fireOnce': if an event is configured to fire once, new subscribers after
 
1383
         *   the fire will be notified immediately.
 
1384
         *    </li>
 
1385
         *    <li>
 
1386
         *   'preventable': whether or not preventDefault() has an effect (true)
 
1387
         *    </li>
 
1388
         *    <li>
 
1389
         *   'preventedFn': a function that is executed when preventDefault is called
 
1390
         *    </li>
 
1391
         *    <li>
 
1392
         *   'queuable': whether or not this event can be queued during bubbling (false)
 
1393
         *    </li>
 
1394
         *    <li>
 
1395
         *   'silent': if silent is true, debug messages are not provided for this event.
 
1396
         *    </li>
 
1397
         *    <li>
 
1398
         *   'stoppedFn': a function that is executed when stopPropagation is called
 
1399
         *    </li>
 
1400
         *    <li>
 
1401
         *   'type': the event type (valid option if not provided as the first parameter to publish)
 
1402
         *    </li>
 
1403
         *  </ul>
 
1404
         *
 
1405
         *  @return {Event.Custom} the custom event
 
1406
         *
 
1407
         */
 
1408
        publish: function(type, opts) {
 
1409
 
 
1410
            var events = this._yuievt.events, ce = events[type];
 
1411
 
 
1412
            //if (ce && !ce.configured) {
 
1413
            if (ce) {
 
1414
 
 
1415
                // This event could have been published
 
1416
                ce.applyConfig(opts, true);
 
1417
                // ce.configured = true;
 
1418
 
 
1419
            } else {
 
1420
                var o = opts || {};
 
1421
 
 
1422
                // apply defaults
 
1423
                Y.mix(o, this._yuievt.defaults);
 
1424
 
 
1425
                ce = new Y.CustomEvent(type, o);
 
1426
 
 
1427
                events[type] = ce;
 
1428
 
 
1429
                if (o.onSubscribeCallback) {
 
1430
                    ce.subscribeEvent.subscribe(o.onSubscribeCallback);
 
1431
                }
 
1432
 
 
1433
            }
 
1434
 
 
1435
            return events[type];
 
1436
        },
 
1437
 
 
1438
        /**
 
1439
         * Registers another Event.Target as a bubble target.  Bubble order
 
1440
         * is determined by the order registered.  Multiple targets can
 
1441
         * be specified.
 
1442
         * @method addTarget
 
1443
         * @param o {Event.Target} the target to add
 
1444
         */
 
1445
        addTarget: function(o) {
 
1446
            this._yuievt.targets[Y.stamp(o)] = o;
 
1447
            this._yuievt.hasTargets = true;
 
1448
        },
 
1449
 
 
1450
        /**
 
1451
         * Removes a bubble target
 
1452
         * @method removeTarget
 
1453
         * @param o {Event.Target} the target to remove
 
1454
         */
 
1455
        removeTarget: function(o) {
 
1456
            delete this._yuievt.targets[Y.stamp(o)];
 
1457
        },
 
1458
 
 
1459
       /**
 
1460
         * Fire a custom event by name.  The callback functions will be executed
 
1461
         * from the context specified when the event was created, and with the 
 
1462
         * following parameters.
 
1463
         *
 
1464
         * If the custom event object hasn't been created, then the event hasn't 
 
1465
         * been published and it has no subscribers.  For performance sake, we 
 
1466
         * immediate exit in this case.  This means the event won't bubble, so 
 
1467
         * if the intention is that a bubble target be notified, the event must 
 
1468
         * be published on this object first.
 
1469
         *
 
1470
         * @method fire
 
1471
         * @param type {String|Object} The type of the event, or an object that contains
 
1472
         * a 'type' property.
 
1473
         * @param arguments {Object*} an arbitrary set of parameters to pass to 
 
1474
         * the handler.
 
1475
         * @return {boolean} the return value from Event.Custom.fire
 
1476
         *                   
 
1477
         */
 
1478
        fire: function(type) {
 
1479
 
 
1480
            var typeIncluded = Y.Lang.isString(type),
 
1481
                t = (typeIncluded) ? type : (type && type.type);
 
1482
 
 
1483
            var ce = this.getEvent(t);
 
1484
 
 
1485
            // this event has not been published or subscribed to
 
1486
            if (!ce) {
 
1487
                
 
1488
                // if this object has bubble targets, we need to publish the
 
1489
                // event in order for it to bubble.
 
1490
                if (this._yuievt.hasTargets) {
 
1491
                    // ce = this.publish(t, {
 
1492
                    //     configured: false
 
1493
                    // });
 
1494
                    ce = this.publish(t);
 
1495
                    ce.details = Y.Array(arguments, (typeIncluded) ? 1 : 0, true);
 
1496
 
 
1497
                    return this.bubble(ce);
 
1498
                }
 
1499
 
 
1500
                // otherwise there is nothing to be done
 
1501
                return true;
 
1502
            }
 
1503
 
 
1504
            // Provide this object's subscribers the object they are listening to.
 
1505
            // ce.currentTarget = this;
 
1506
 
 
1507
            // This this the target unless target is current not null
 
1508
            // (set in bubble()).
 
1509
            // ce.target = ce.target || this;
 
1510
 
 
1511
            var a = Y.Array(arguments, (typeIncluded) ? 1 : 0, true);
 
1512
            var ret = ce.fire.apply(ce, a);
 
1513
 
 
1514
            // clear target for next fire()
 
1515
            ce.target = null;
 
1516
 
 
1517
            return ret;
 
1518
        },
 
1519
 
 
1520
        /**
 
1521
         * Returns the custom event of the provided type has been created, a
 
1522
         * falsy value otherwise
 
1523
         * @method getEvent
 
1524
         * @param type {string} the type, or name of the event
 
1525
         * @return {Event.Custom} the custom event or null
 
1526
         */
 
1527
        getEvent: function(type) {
 
1528
            var e = this._yuievt.events;
 
1529
            return (e && type in e) ? e[type] : null;
 
1530
        },
 
1531
 
 
1532
        /**
 
1533
         * Propagate an event
 
1534
         * @method bubble
 
1535
         * @param evt {Event.Custom} the custom event to propagate
 
1536
         * @return {boolean} the aggregated return value from Event.Custom.fire
 
1537
         */
 
1538
        bubble: function(evt) {
 
1539
 
 
1540
            var targs = this._yuievt.targets, ret = true;
 
1541
 
 
1542
            if (!evt.stopped && targs) {
 
1543
 
 
1544
 
 
1545
                for (var i in targs) {
 
1546
                    if (targs.hasOwnProperty(i)) {
 
1547
 
 
1548
                        var t = targs[i], type = evt.type,
 
1549
                            ce = t.getEvent(type), targetProp = evt.target || this;
 
1550
                            
 
1551
                        // if this event was not published on the bubble target,
 
1552
                        // publish it with sensible default properties
 
1553
                        if (!ce) {
 
1554
 
 
1555
                            // publish the event on the bubble target using this event
 
1556
                            // for its configuration
 
1557
                            ce = t.publish(type, evt);
 
1558
                            // ce.configured = false;
 
1559
 
 
1560
                            // set the host and context appropriately
 
1561
                            ce.context = (evt.host === evt.context) ? t : evt.context;
 
1562
                            ce.host = t;
 
1563
 
 
1564
                            // clear handlers if specified on this event
 
1565
                            ce.defaultFn = null;
 
1566
                            ce.preventedFn = null;
 
1567
                            ce.stoppedFn = null;
 
1568
                        }
 
1569
 
 
1570
                        ce.target = targetProp;
 
1571
                        ce.currentTarget = t;
 
1572
 
 
1573
                        // ce.target = evt.target;
 
1574
 
 
1575
                        ret = ret && ce.fire.apply(ce, evt.details);
 
1576
 
 
1577
                        // stopPropagation() was called
 
1578
                        if (ce.stopped) {
 
1579
                            break;
 
1580
                        }
 
1581
                    }
 
1582
                }
 
1583
            }
 
1584
 
 
1585
            return ret;
 
1586
        },
 
1587
 
 
1588
        /**
 
1589
         * Subscribe to a custom event hosted by this object.  The
 
1590
         * supplied callback will execute after any listeners add
 
1591
         * via the subscribe method, and after the default function,
 
1592
         * if configured for the event, has executed.
 
1593
         * @method after
 
1594
         * @param type    {string}   The type of the event
 
1595
         * @param fn {Function} The callback
 
1596
         * @param context The execution context
 
1597
         * @param args* 1..n params to supply to the callback
 
1598
         */
 
1599
        after: function(type, fn) {
 
1600
            var ce = this._yuievt.events[type] || 
 
1601
                // this.publish(type, {
 
1602
                //     configured: false
 
1603
                // }),
 
1604
                this.publish(type),
 
1605
                a = Y.Array(arguments, 1, true);
 
1606
 
 
1607
            return ce.after.apply(ce, a);
 
1608
        }
 
1609
 
 
1610
    };
 
1611
 
 
1612
    // make Y an event target
 
1613
    Y.mix(Y, ET.prototype, false, false, { 
 
1614
        bubbles: false 
 
1615
    });
 
1616
    ET.call(Y);
 
1617
 
 
1618
 
 
1619
}, "3.0.0");
 
1620
 
 
1621
/*
 
1622
 * DOMReady
 
1623
 * @submodule event-ready
 
1624
 * @module event
 
1625
 */
 
1626
 
 
1627
(function() {
 
1628
 
 
1629
var Env = YUI.Env, 
 
1630
    C = YUI.config, 
 
1631
    D = C.doc, 
 
1632
    POLL_INTERVAL = C.pollInterval || 20;
 
1633
 
 
1634
    if (!Env._ready) {
 
1635
 
 
1636
        Env.windowLoaded = false;
 
1637
 
 
1638
        Env._ready = function() {
 
1639
            if (!Env.DOMReady) {
 
1640
                Env.DOMReady=true;
 
1641
 
 
1642
                // Remove the DOMContentLoaded (FF/Opera)
 
1643
                if (D.removeEventListener) {
 
1644
                    D.removeEventListener("DOMContentLoaded", _ready, false);
 
1645
                }
 
1646
            }
 
1647
        };
 
1648
 
 
1649
        var _ready = function(e) {
 
1650
            YUI.Env._ready();
 
1651
        };
 
1652
 
 
1653
        // create custom event
 
1654
 
 
1655
        /////////////////////////////////////////////////////////////
 
1656
        // DOMReady
 
1657
        // based on work by: Dean Edwards/John Resig/Matthias Miller 
 
1658
 
 
1659
        // Internet Explorer: use the readyState of a defered script.
 
1660
        // This isolates what appears to be a safe moment to manipulate
 
1661
        // the DOM prior to when the document's readyState suggests
 
1662
        // it is safe to do so.
 
1663
        if (navigator.userAgent.match(/MSIE/)) {
 
1664
 
 
1665
            Env._dri = setInterval(function() {
 
1666
                try {
 
1667
                    // throws an error if doc is not ready
 
1668
                    document.documentElement.doScroll('left');
 
1669
                    clearInterval(Env._dri);
 
1670
                    Env._dri = null;
 
1671
                    _ready();
 
1672
                } catch (ex) { 
 
1673
                }
 
1674
            }, POLL_INTERVAL); 
 
1675
 
 
1676
        // FireFox and Opera: These browsers provide a event for this
 
1677
        // moment.  The latest WebKit releases now support this event.
 
1678
        } else {
 
1679
            D.addEventListener("DOMContentLoaded", _ready, false);
 
1680
        }
 
1681
 
 
1682
        /////////////////////////////////////////////////////////////
 
1683
    }
 
1684
 
 
1685
    YUI.add("event-ready", function(Y) {
 
1686
 
 
1687
        if (Y === YUI) {
 
1688
            return;
 
1689
        }
 
1690
 
 
1691
        Y.publish('event:ready', {
 
1692
            fireOnce: true
 
1693
        });
 
1694
 
 
1695
        var yready = function() {
 
1696
            Y.fire('event:ready');
 
1697
        };
 
1698
 
 
1699
        if (Env.DOMReady) {
 
1700
            yready();
 
1701
        } else {
 
1702
            Y.before(yready, Env, "_ready");
 
1703
        }
 
1704
 
 
1705
    }, "3.0.0");
 
1706
 
 
1707
})();
 
1708
/*
 
1709
 * The YUI DOM event system
 
1710
 * @submodule event-dom
 
1711
 * @module event
 
1712
 */
 
1713
(function() {
 
1714
 
 
1715
    var add = function(el, type, fn, capture) {
 
1716
        if (el.addEventListener) {
 
1717
                el.addEventListener(type, fn, !!capture);
 
1718
        } else if (el.attachEvent) {
 
1719
                el.attachEvent("on" + type, fn);
 
1720
        } 
 
1721
    },
 
1722
 
 
1723
    remove = function(el, type, fn, capture) {
 
1724
        if (el.removeEventListener) {
 
1725
                el.removeEventListener(type, fn, !!capture);
 
1726
        } else if (el.detachEvent) {
 
1727
                el.detachEvent("on" + type, fn);
 
1728
        }
 
1729
    },
 
1730
 
 
1731
    onLoad = function() {
 
1732
        YUI.Env.windowLoaded = true;
 
1733
        remove(window, "load", onLoad);
 
1734
    };
 
1735
 
 
1736
    add(window, "load", onLoad);
 
1737
 
 
1738
YUI.add("event-dom", function(Y) {
 
1739
 
 
1740
    /*
 
1741
     * The Event Utility provides utilities for managing DOM Events and tools
 
1742
     * for building event systems
 
1743
     *
 
1744
     * @module event
 
1745
     * @title Event Utility
 
1746
     */
 
1747
 
 
1748
    /**
 
1749
     * The event utility provides functions to add and remove event listeners,
 
1750
     * event cleansing.  It also tries to automatically remove listeners it
 
1751
     * registers during the unload event.
 
1752
     *
 
1753
     * @class Event
 
1754
     * @static
 
1755
     */
 
1756
        Y.Event = function() {
 
1757
 
 
1758
            /**
 
1759
             * True after the onload event has fired
 
1760
             * @property loadComplete
 
1761
             * @type boolean
 
1762
             * @static
 
1763
             * @private
 
1764
             */
 
1765
            var loadComplete =  false;
 
1766
 
 
1767
            /**
 
1768
             * The number of times to poll after window.onload.  This number is
 
1769
             * increased if additional late-bound handlers are requested after
 
1770
             * the page load.
 
1771
             * @property _retryCount
 
1772
             * @static
 
1773
             * @private
 
1774
             */
 
1775
            var _retryCount = 0;
 
1776
 
 
1777
            /**
 
1778
             * onAvailable listeners
 
1779
             * @property _avail
 
1780
             * @static
 
1781
             * @private
 
1782
             */
 
1783
            var _avail = [];
 
1784
 
 
1785
            /**
 
1786
             * Custom event wrappers for DOM events.  Key is 
 
1787
             * 'event:' + Element uid stamp + event type
 
1788
             * @property _wrappers
 
1789
             * @type Y.Event.Custom
 
1790
             * @static
 
1791
             * @private
 
1792
             */
 
1793
            var _wrappers = {};
 
1794
 
 
1795
            var _windowLoadKey = null;
 
1796
 
 
1797
            /**
 
1798
             * Custom event wrapper map DOM events.  Key is 
 
1799
             * Element uid stamp.  Each item is a hash of custom event
 
1800
             * wrappers as provided in the _wrappers collection.  This
 
1801
             * provides the infrastructure for getListeners.
 
1802
             * @property _el_events
 
1803
             * @static
 
1804
             * @private
 
1805
             */
 
1806
            var _el_events = {};
 
1807
 
 
1808
            return {
 
1809
 
 
1810
                /**
 
1811
                 * The number of times we should look for elements that are not
 
1812
                 * in the DOM at the time the event is requested after the document
 
1813
                 * has been loaded.  The default is 2000@amp;20 ms, so it will poll
 
1814
                 * for 40 seconds or until all outstanding handlers are bound
 
1815
                 * (whichever comes first).
 
1816
                 * @property POLL_RETRYS
 
1817
                 * @type int
 
1818
                 * @static
 
1819
                 * @final
 
1820
                 */
 
1821
                POLL_RETRYS: 2000,
 
1822
 
 
1823
                /**
 
1824
                 * The poll interval in milliseconds
 
1825
                 * @property POLL_INTERVAL
 
1826
                 * @type int
 
1827
                 * @static
 
1828
                 * @final
 
1829
                 */
 
1830
                POLL_INTERVAL: 20,
 
1831
 
 
1832
                /**
 
1833
                 * addListener/removeListener can throw errors in unexpected scenarios.
 
1834
                 * These errors are suppressed, the method returns false, and this property
 
1835
                 * is set
 
1836
                 * @property lastError
 
1837
                 * @static
 
1838
                 * @type Error
 
1839
                 */
 
1840
                lastError: null,
 
1841
 
 
1842
 
 
1843
                /**
 
1844
                 * poll handle
 
1845
                 * @property _interval
 
1846
                 * @static
 
1847
                 * @private
 
1848
                 */
 
1849
                _interval: null,
 
1850
 
 
1851
                /**
 
1852
                 * document readystate poll handle
 
1853
                 * @property _dri
 
1854
                 * @static
 
1855
                 * @private
 
1856
                 */
 
1857
                 _dri: null,
 
1858
 
 
1859
                /**
 
1860
                 * True when the document is initially usable
 
1861
                 * @property DOMReady
 
1862
                 * @type boolean
 
1863
                 * @static
 
1864
                 */
 
1865
                DOMReady: false,
 
1866
 
 
1867
                /**
 
1868
                 * @method startInterval
 
1869
                 * @static
 
1870
                 * @private
 
1871
                 */
 
1872
                startInterval: function() {
 
1873
                    if (!this._interval) {
 
1874
this._interval = setInterval(Y.bind(this._tryPreloadAttach, this), this.POLL_INTERVAL);
 
1875
                    }
 
1876
                },
 
1877
 
 
1878
                /**
 
1879
                 * Executes the supplied callback when the item with the supplied
 
1880
                 * id is found.  This is meant to be used to execute behavior as
 
1881
                 * soon as possible as the page loads.  If you use this after the
 
1882
                 * initial page load it will poll for a fixed time for the element.
 
1883
                 * The number of times it will poll and the frequency are
 
1884
                 * configurable.  By default it will poll for 10 seconds.
 
1885
                 *
 
1886
                 * <p>The callback is executed with a single parameter:
 
1887
                 * the custom object parameter, if provided.</p>
 
1888
                 *
 
1889
                 * @method onAvailable
 
1890
                 *
 
1891
                 * @param {string||string[]}   id the id of the element, or an array
 
1892
                 * of ids to look for.
 
1893
                 * @param {function} fn what to execute when the element is found.
 
1894
                 * @param {object}   p_obj an optional object to be passed back as
 
1895
                 *                   a parameter to fn.
 
1896
                 * @param {boolean|object}  p_override If set to true, fn will execute
 
1897
                 *                   in the context of p_obj, if set to an object it
 
1898
                 *                   will execute in the context of that object
 
1899
                 * @param checkContent {boolean} check child node readiness (onContentReady)
 
1900
                 * @static
 
1901
                 * @deprecated This will be replaced with a special Y.on custom event
 
1902
                 */
 
1903
                // @TODO fix arguments
 
1904
                onAvailable: function(id, fn, p_obj, p_override, checkContent) {
 
1905
 
 
1906
                    // var a = (Y.Lang.isString(id)) ? [id] : id;
 
1907
                    var a = Y.Array(id);
 
1908
 
 
1909
                    for (var i=0; i<a.length; i=i+1) {
 
1910
                        _avail.push({ id:         a[i], 
 
1911
                                      fn:         fn, 
 
1912
                                      obj:        p_obj, 
 
1913
                                      override:   p_override, 
 
1914
                                      checkReady: checkContent });
 
1915
                    }
 
1916
                    _retryCount = this.POLL_RETRYS;
 
1917
                    // this.startInterval();
 
1918
                    // this._tryPreloadAttach();
 
1919
 
 
1920
                    // We want the first test to be immediate, but async
 
1921
                    setTimeout(Y.bind(this._tryPreloadAttach, this), 0);
 
1922
                },
 
1923
 
 
1924
                /**
 
1925
                 * Works the same way as onAvailable, but additionally checks the
 
1926
                 * state of sibling elements to determine if the content of the
 
1927
                 * available element is safe to modify.
 
1928
                 *
 
1929
                 * <p>The callback is executed with a single parameter:
 
1930
                 * the custom object parameter, if provided.</p>
 
1931
                 *
 
1932
                 * @method onContentReady
 
1933
                 *
 
1934
                 * @param {string}   id the id of the element to look for.
 
1935
                 * @param {function} fn what to execute when the element is ready.
 
1936
                 * @param {object}   p_obj an optional object to be passed back as
 
1937
                 *                   a parameter to fn.
 
1938
                 * @param {boolean|object}  p_override If set to true, fn will execute
 
1939
                 *                   in the context of p_obj.  If an object, fn will
 
1940
                 *                   exectute in the context of that object
 
1941
                 *
 
1942
                 * @static
 
1943
                 * @deprecated This will be replaced with a special Y.on custom event
 
1944
                 */
 
1945
                // @TODO fix arguments
 
1946
                onContentReady: function(id, fn, p_obj, p_override) {
 
1947
                    this.onAvailable(id, fn, p_obj, p_override, true);
 
1948
                },
 
1949
 
 
1950
                /**
 
1951
                 * Executes the supplied callback when the DOM is first usable.  This
 
1952
                 * will execute immediately if called after the DOMReady event has
 
1953
                 * fired.   @todo the DOMContentReady event does not fire when the
 
1954
                 * script is dynamically injected into the page.  This means the
 
1955
                 * DOMReady custom event will never fire in FireFox or Opera when the
 
1956
                 * library is injected.  It _will_ fire in Safari, and the IE 
 
1957
                 * implementation would allow for us to fire it if the defered script
 
1958
                 * is not available.  We want this to behave the same in all browsers.
 
1959
                 * Is there a way to identify when the script has been injected 
 
1960
                 * instead of included inline?  Is there a way to know whether the 
 
1961
                 * window onload event has fired without having had a listener attached 
 
1962
                 * to it when it did so?
 
1963
                 *
 
1964
                 * <p>The callback is a Event.Custom, so the signature is:</p>
 
1965
                 * <p>type &lt;string&gt;, args &lt;array&gt;, customobject &lt;object&gt;</p>
 
1966
                 * <p>For DOMReady events, there are no fire argments, so the
 
1967
                 * signature is:</p>
 
1968
                 * <p>"DOMReady", [], obj</p>
 
1969
                 *
 
1970
                 *
 
1971
                 * @method onDOMReady
 
1972
                 *
 
1973
                 * @param {function} fn what to execute when the element is found.
 
1974
                 * @optional context execution context
 
1975
                 * @optional args 1..n arguments to send to the listener
 
1976
                 *
 
1977
                 * @static
 
1978
                 * @deprecated Use Y.on('event:ready');
 
1979
                 */
 
1980
                onDOMReady: function(fn) {
 
1981
                    // var ev = Y.Event.DOMReadyEvent;
 
1982
                    // ev.subscribe.apply(ev, arguments);
 
1983
                    var a = Y.Array(arguments, 0, true);
 
1984
                    a.unshift('event:ready');
 
1985
                    Y.on.apply(Y, a);
 
1986
                },
 
1987
 
 
1988
                /**
 
1989
                 * Appends an event handler
 
1990
                 *
 
1991
                 * @method addListener
 
1992
                 *
 
1993
                 * @param {String|HTMLElement|Array|NodeList} el An id, an element 
 
1994
                 *  reference, or a collection of ids and/or elements to assign the 
 
1995
                 *  listener to.
 
1996
                 * @param {String}   type     The type of event to append
 
1997
                 * @param {Function} fn        The method the event invokes
 
1998
                 * @param {Object}   obj    An arbitrary object that will be 
 
1999
                 *                             passed as a parameter to the handler
 
2000
                 * @param {Boolean|object}  args 1..n ar
 
2001
                 * @return {Boolean} True if the action was successful or defered,
 
2002
                 *                        false if one or more of the elements 
 
2003
                 *                        could not have the listener attached,
 
2004
                 *                        or if the operation throws an exception.
 
2005
                 * @static
 
2006
                 * @deprecated Use Y.on instead.  This will be removed in PR2
 
2007
                 */
 
2008
                addListener: function(el, type, fn, obj) {
 
2009
 
 
2010
 
 
2011
                    var a=Y.Array(arguments, 1, true), override = a[3], E = Y.Event,
 
2012
                        aa=Y.Array(arguments, 0, true);
 
2013
 
 
2014
                    if (!fn || !fn.call) {
 
2015
    // throw new TypeError(type + " addListener call failed, callback undefined");
 
2016
                        return false;
 
2017
                    }
 
2018
 
 
2019
                    // The el argument can be an array of elements or element ids.
 
2020
                    if (this._isValidCollection(el)) {
 
2021
 
 
2022
 
 
2023
                        var handles=[], h, i, l, proc = function(v, k) {
 
2024
                            // handles.push(this.addListener(el[i], type, fn, obj, override));
 
2025
                            // var node = el.item(k);
 
2026
                            
 
2027
                            var b = a.slice();
 
2028
                            b.unshift(v);
 
2029
                            h = E.addListener.apply(E, b);
 
2030
                            handles.push(h);
 
2031
                        };
 
2032
 
 
2033
                        Y.each(el, proc, E);
 
2034
 
 
2035
 
 
2036
                        return handles;
 
2037
 
 
2038
 
 
2039
                    } else if (Y.Lang.isString(el)) {
 
2040
                        var oEl = Y.all(el);
 
2041
                        // If the el argument is a string, we assume it is 
 
2042
                        // actually the id of the element.  If the page is loaded
 
2043
                        // we convert el to the actual element, otherwise we 
 
2044
                        // defer attaching the event until onload event fires
 
2045
 
 
2046
                        // check to see if we need to delay hooking up the event 
 
2047
                        // until after the page loads.
 
2048
                        var size = oEl.size();
 
2049
                        if (size) {
 
2050
                            if (size > 1) {
 
2051
                                aa[0] = oEl;
 
2052
                                return E.addListener.apply(E, aa);
 
2053
                            } else {
 
2054
                                el = oEl.item(0);
 
2055
                            }
 
2056
                        } else {
 
2057
                            //
 
2058
                            // defer adding the event until the element is available
 
2059
                            this.onAvailable(el, function() {
 
2060
                                // Y.Event.addListener(el, type, fn, obj, override);
 
2061
                                Y.Event.addListener.apply(Y.Event, aa);
 
2062
                            });
 
2063
 
 
2064
                            return true;
 
2065
                        }
 
2066
                    }
 
2067
 
 
2068
                    // Element should be an html element or an array if we get 
 
2069
                    // here.
 
2070
                    if (!el) {
 
2071
                        return false;
 
2072
                    }
 
2073
 
 
2074
                    // the custom event key is the uid for the element + type
 
2075
 
 
2076
                    var ek = Y.stamp(el), key = 'event:' + ek + type,
 
2077
                        cewrapper = _wrappers[key];
 
2078
 
 
2079
 
 
2080
                    if (!cewrapper) {
 
2081
                        // create CE wrapper
 
2082
                        cewrapper = Y.publish(key, {
 
2083
                            silent: true,
 
2084
                            // host: this,
 
2085
                            bubbles: false
 
2086
                        });
 
2087
 
 
2088
                        // cache the dom event details in the custom event
 
2089
                        // for later removeListener calls
 
2090
                        cewrapper.el = el;
 
2091
                        cewrapper.type = type;
 
2092
                        cewrapper.fn = function(e) {
 
2093
                            cewrapper.fire(Y.Event.getEvent(e, el));
 
2094
                        };
 
2095
 
 
2096
                        if (el == Y.config.win && type == "load") {
 
2097
                            // window load happens once
 
2098
                            cewrapper.fireOnce = true;
 
2099
                            _windowLoadKey = key;
 
2100
 
 
2101
                            // if the load is complete, fire immediately.
 
2102
                            // all subscribers, including the current one
 
2103
                            // will be notified.
 
2104
                            if (YUI.Env.windowLoaded) {
 
2105
                                cewrapper.fire();
 
2106
                            }
 
2107
                        }
 
2108
 
 
2109
                        _wrappers[key] = cewrapper;
 
2110
                        _el_events[ek] = _el_events[ek] || {};
 
2111
                        _el_events[ek][key] = cewrapper;
 
2112
 
 
2113
                        // var capture = (Y.lang.isObject(obj) && obj.capture);
 
2114
                        // attach a listener that fires the custom event
 
2115
                        this.nativeAdd(el, type, cewrapper.fn, false);
 
2116
                    }
 
2117
 
 
2118
        
 
2119
                    // from type, fn, etc to fn, obj, override
 
2120
                    a = Y.Array(arguments, 2, true);
 
2121
                    // a = a.shift();
 
2122
 
 
2123
                    var context = obj || Y.get(el);
 
2124
                    // if (override) {
 
2125
                        // if (override === true) {
 
2126
                            // context = obj;
 
2127
                        // } else {
 
2128
                            // context = override;
 
2129
                        // }
 
2130
                    // }
 
2131
 
 
2132
                    a[1] = context;
 
2133
 
 
2134
                    // set context to the Node if not specified
 
2135
                    return cewrapper.subscribe.apply(cewrapper, a);
 
2136
 
 
2137
 
 
2138
                },
 
2139
 
 
2140
                /**
 
2141
                 * Removes an event listener.  Supports the signature the event was bound
 
2142
                 * with, but the preferred way to remove listeners is using the handle
 
2143
                 * that is returned when using Y.on
 
2144
                 *
 
2145
                 * @method removeListener
 
2146
                 *
 
2147
                 * @param {String|HTMLElement|Array|NodeList} el An id, an element 
 
2148
                 *  reference, or a collection of ids and/or elements to remove
 
2149
                 *  the listener from.
 
2150
                 * @param {String} type the type of event to remove.
 
2151
                 * @param {Function} fn the method the event invokes.  If fn is
 
2152
                 *  undefined, then all event handlers for the type of event are *  removed.
 
2153
                 * @return {boolean} true if the unbind was successful, false *  otherwise.
 
2154
                 * @static
 
2155
                 */
 
2156
                removeListener: function(el, type, fn) {
 
2157
 
 
2158
                    if (el && el.detach) {
 
2159
                        return el.detach();
 
2160
                    }
 
2161
                    var i, len, li;
 
2162
 
 
2163
                    // The el argument can be a string
 
2164
                    if (typeof el == "string") {
 
2165
                        el = Y.get(el);
 
2166
                    // The el argument can be an array of elements or element ids.
 
2167
                    } else if ( this._isValidCollection(el)) {
 
2168
                        var ok = true;
 
2169
                        for (i=0,len=el.length; i<len; ++i) {
 
2170
                            ok = ( this.removeListener(el[i], type, fn) && ok );
 
2171
                        }
 
2172
                        return ok;
 
2173
                    }
 
2174
 
 
2175
                    if (!fn || !fn.call) {
 
2176
                        //return false;
 
2177
                        return this.purgeElement(el, false, type);
 
2178
                    }
 
2179
 
 
2180
 
 
2181
                    var id = 'event:' + Y.stamp(el) + type, 
 
2182
                        ce = _wrappers[id];
 
2183
                    if (ce) {
 
2184
                        return ce.unsubscribe(fn);
 
2185
                    } else {
 
2186
                        return false;
 
2187
                    }
 
2188
 
 
2189
                },
 
2190
 
 
2191
                /**
 
2192
                 * Finds the event in the window object, the caller's arguments, or
 
2193
                 * in the arguments of another method in the callstack.  This is
 
2194
                 * executed automatically for events registered through the event
 
2195
                 * manager, so the implementer should not normally need to execute
 
2196
                 * this function at all.
 
2197
                 * @method getEvent
 
2198
                 * @param {Event} e the event parameter from the handler
 
2199
                 * @param {HTMLElement} boundEl the element the listener is attached to
 
2200
                 * @return {Event} the event 
 
2201
                 * @static
 
2202
                 */
 
2203
                getEvent: function(e, boundEl) {
 
2204
                    var ev = e || window.event;
 
2205
 
 
2206
                    if (!ev) {
 
2207
                        var c = this.getEvent.caller;
 
2208
                        while (c) {
 
2209
                            ev = c.arguments[0];
 
2210
                            if (ev && Event == ev.constructor) {
 
2211
                                break;
 
2212
                            }
 
2213
                            c = c.caller;
 
2214
                        }
 
2215
                    }
 
2216
 
 
2217
 
 
2218
                    return new Y.Event.Facade(ev, boundEl, _wrappers['event:' + Y.stamp(boundEl) + e.type]);
 
2219
                },
 
2220
 
 
2221
 
 
2222
                /**
 
2223
                 * Generates an unique ID for the element if it does not already 
 
2224
                 * have one.
 
2225
                 * @method generateId
 
2226
                 * @param el the element to create the id for
 
2227
                 * @return {string} the resulting id of the element
 
2228
                 * @static
 
2229
                 */
 
2230
                generateId: function(el) {
 
2231
                    var id = el.id;
 
2232
 
 
2233
                    if (!id) {
 
2234
                        id = Y.stamp(el);
 
2235
                        el.id = id;
 
2236
                    }
 
2237
 
 
2238
                    return id;
 
2239
                },
 
2240
 
 
2241
 
 
2242
                /**
 
2243
                 * We want to be able to use getElementsByTagName as a collection
 
2244
                 * to attach a group of events to.  Unfortunately, different 
 
2245
                 * browsers return different types of collections.  This function
 
2246
                 * tests to determine if the object is array-like.  It will also 
 
2247
                 * fail if the object is an array, but is empty.
 
2248
                 * @method _isValidCollection
 
2249
                 * @param o the object to test
 
2250
                 * @return {boolean} true if the object is array-like and populated
 
2251
                 * @static
 
2252
                 * @private
 
2253
                 */
 
2254
                _isValidCollection: function(o) {
 
2255
                    try {
 
2256
                        return ( o                     && // o is something
 
2257
                                 typeof o !== "string" && // o is not a string
 
2258
                                 (o.each || o.length)  && // o is indexed
 
2259
                                 !o.tagName            && // o is not an HTML element
 
2260
                                 !o.alert              && // o is not a window
 
2261
                                 (o.item || typeof o[0] !== "undefined") );
 
2262
                    } catch(ex) {
 
2263
                        return false;
 
2264
                    }
 
2265
 
 
2266
                },
 
2267
 
 
2268
                /*
 
2269
                 * Custom event the fires when the dom is initially usable
 
2270
                 * @event DOMReadyEvent
 
2271
                 */
 
2272
                // DOMReadyEvent: new Y.CustomEvent("event:ready", this),
 
2273
                // DOMReadyEvent: Y.publish("event:ready", this, {
 
2274
                    // fireOnce: true
 
2275
                // }),
 
2276
 
 
2277
                /**
 
2278
                 * hook up any deferred listeners
 
2279
                 * @method _load
 
2280
                 * @static
 
2281
                 * @private
 
2282
                 */
 
2283
                _load: function(e) {
 
2284
 
 
2285
                    if (!loadComplete) {
 
2286
 
 
2287
 
 
2288
                        loadComplete = true;
 
2289
 
 
2290
                        // Just in case DOMReady did not go off for some reason
 
2291
                        // E._ready();
 
2292
                        if (Y.fire) {
 
2293
                            Y.fire('event:ready');
 
2294
                        }
 
2295
 
 
2296
                        // Available elements may not have been detected before the
 
2297
                        // window load event fires. Try to find them now so that the
 
2298
                        // the user is more likely to get the onAvailable notifications
 
2299
                        // before the window load notification
 
2300
                        Y.Event._tryPreloadAttach();
 
2301
 
 
2302
                    }
 
2303
                },
 
2304
 
 
2305
                /**
 
2306
                 * Polling function that runs before the onload event fires, 
 
2307
                 * attempting to attach to DOM Nodes as soon as they are 
 
2308
                 * available
 
2309
                 * @method _tryPreloadAttach
 
2310
                 * @static
 
2311
                 * @private
 
2312
                 */
 
2313
                _tryPreloadAttach: function() {
 
2314
 
 
2315
                    if (this.locked) {
 
2316
                        return;
 
2317
                    }
 
2318
 
 
2319
                    if (Y.UA.ie && !YUI.Env.DOMReady) {
 
2320
                        // Hold off if DOMReady has not fired and check current
 
2321
                        // readyState to protect against the IE operation aborted
 
2322
                        // issue.
 
2323
                        this.startInterval();
 
2324
                        return;
 
2325
                    }
 
2326
 
 
2327
                    this.locked = true;
 
2328
 
 
2329
 
 
2330
                    // keep trying until after the page is loaded.  We need to 
 
2331
                    // check the page load state prior to trying to bind the 
 
2332
                    // elements so that we can be certain all elements have been 
 
2333
                    // tested appropriately
 
2334
                    var tryAgain = !loadComplete;
 
2335
                    if (!tryAgain) {
 
2336
                        tryAgain = (_retryCount > 0);
 
2337
                    }
 
2338
 
 
2339
                    // onAvailable
 
2340
                    var notAvail = [];
 
2341
 
 
2342
                    var executeItem = function (el, item) {
 
2343
                        var context;
 
2344
                        if (item.override) {
 
2345
                            if (item.override === true) {
 
2346
                                context = item.obj;
 
2347
                            } else {
 
2348
                                context = item.override;
 
2349
                            }
 
2350
                        } else {
 
2351
                            context = Y.get(el);
 
2352
                        }
 
2353
                        item.fn.call(context, item.obj);
 
2354
                    };
 
2355
 
 
2356
                    var i,len,item,el;
 
2357
 
 
2358
                    // onAvailable
 
2359
                    for (i=0,len=_avail.length; i<len; ++i) {
 
2360
                        item = _avail[i];
 
2361
                        if (item && !item.checkReady) {
 
2362
                            el = Y.get(item.id);
 
2363
                            if (el) {
 
2364
                                executeItem(el, item);
 
2365
                                _avail[i] = null;
 
2366
                            } else {
 
2367
                                notAvail.push(item);
 
2368
                            }
 
2369
                        }
 
2370
                    }
 
2371
 
 
2372
                    // onContentReady
 
2373
                    for (i=0,len=_avail.length; i<len; ++i) {
 
2374
                        item = _avail[i];
 
2375
                        if (item && item.checkReady) {
 
2376
                            el = Y.get(item.id);
 
2377
 
 
2378
                            if (el) {
 
2379
                                // The element is available, but not necessarily ready
 
2380
                                // @todo should we test parentNode.nextSibling?
 
2381
                                if (loadComplete || el.get('nextSibling')) {
 
2382
                                    executeItem(el, item);
 
2383
                                    _avail[i] = null;
 
2384
                                }
 
2385
                            } else {
 
2386
                                notAvail.push(item);
 
2387
                            }
 
2388
                        }
 
2389
                    }
 
2390
 
 
2391
                    _retryCount = (notAvail.length === 0) ? 0 : _retryCount - 1;
 
2392
 
 
2393
                    if (tryAgain) {
 
2394
                        // we may need to strip the nulled out items here
 
2395
                        this.startInterval();
 
2396
                    } else {
 
2397
                        clearInterval(this._interval);
 
2398
                        this._interval = null;
 
2399
                    }
 
2400
 
 
2401
                    this.locked = false;
 
2402
 
 
2403
                    return;
 
2404
 
 
2405
                },
 
2406
 
 
2407
                /**
 
2408
                 * Removes all listeners attached to the given element via addListener.
 
2409
                 * Optionally, the node's children can also be purged.
 
2410
                 * Optionally, you can specify a specific type of event to remove.
 
2411
                 * @method purgeElement
 
2412
                 * @param {HTMLElement} el the element to purge
 
2413
                 * @param {boolean} recurse recursively purge this element's children
 
2414
                 * as well.  Use with caution.
 
2415
                 * @param {string} type optional type of listener to purge. If
 
2416
                 * left out, all listeners will be removed
 
2417
                 * @static
 
2418
                 */
 
2419
                purgeElement: function(el, recurse, type) {
 
2420
                    var oEl = (Y.Lang.isString(el)) ? Y.get(el) : el,
 
2421
                        id = Y.stamp(oEl);
 
2422
                    var lis = this.getListeners(oEl, type), i, len;
 
2423
                    if (lis) {
 
2424
                        for (i=0,len=lis.length; i<len ; ++i) {
 
2425
                            lis[i].unsubscribeAll();
 
2426
                        }
 
2427
                    }
 
2428
 
 
2429
                    if (recurse && oEl && oEl.childNodes) {
 
2430
                        for (i=0,len=oEl.childNodes.length; i<len ; ++i) {
 
2431
                            this.purgeElement(oEl.childNodes[i], recurse, type);
 
2432
                        }
 
2433
                    }
 
2434
                },
 
2435
 
 
2436
                /**
 
2437
                 * Returns all listeners attached to the given element via addListener.
 
2438
                 * Optionally, you can specify a specific type of event to return.
 
2439
                 * @method getListeners
 
2440
                 * @param el {HTMLElement|string} the element or element id to inspect 
 
2441
                 * @param type {string} optional type of listener to return. If
 
2442
                 * left out, all listeners will be returned
 
2443
                 * @return {Y.Custom.Event} the custom event wrapper for the DOM event(s)
 
2444
                 * @static
 
2445
                 */           
 
2446
                getListeners: function(el, type) {
 
2447
                    var results=[], ek = Y.stamp(el), key = (type) ? 'event:' + type : null,
 
2448
                        evts = _el_events[ek];
 
2449
 
 
2450
                    if (key) {
 
2451
                        if (evts[key]) {
 
2452
                            results.push(evts[key]);
 
2453
                        }
 
2454
                    } else {
 
2455
                        for (var i in evts) {
 
2456
                            results.push(evts[i]);
 
2457
                        }
 
2458
                    }
 
2459
 
 
2460
                    return (results.length) ? results : null;
 
2461
                },
 
2462
 
 
2463
                /**
 
2464
                 * Removes all listeners registered by pe.event.  Called 
 
2465
                 * automatically during the unload event.
 
2466
                 * @method _unload
 
2467
                 * @static
 
2468
                 * @private
 
2469
                 */
 
2470
                _unload: function(e) {
 
2471
 
 
2472
                    var E = Y.Event, i, w;
 
2473
 
 
2474
                    for (i in _wrappers) {
 
2475
                        w = _wrappers[i];
 
2476
                        w.unsubscribeAll();
 
2477
                        E.nativeRemove(w.el, w.type, w.fn);
 
2478
                        delete _wrappers[i];
 
2479
                    }
 
2480
 
 
2481
                    E.nativeRemove(window, "unload", E._unload);
 
2482
                },
 
2483
 
 
2484
                
 
2485
                /**
 
2486
                 * Adds a DOM event directly without the caching, cleanup, context adj, etc
 
2487
                 *
 
2488
                 * @method nativeAdd
 
2489
                 * @param {HTMLElement} el      the element to bind the handler to
 
2490
                 * @param {string}      type   the type of event handler
 
2491
                 * @param {function}    fn      the callback to invoke
 
2492
                 * @param {boolen}      capture capture or bubble phase
 
2493
                 * @static
 
2494
                 * @private
 
2495
                 */
 
2496
                nativeAdd: add,
 
2497
 
 
2498
                /**
 
2499
                 * Basic remove listener
 
2500
                 *
 
2501
                 * @method nativeRemove
 
2502
                 * @param {HTMLElement} el      the element to bind the handler to
 
2503
                 * @param {string}      type   the type of event handler
 
2504
                 * @param {function}    fn      the callback to invoke
 
2505
                 * @param {boolen}      capture capture or bubble phase
 
2506
                 * @static
 
2507
                 * @private
 
2508
                 */
 
2509
                nativeRemove: remove
 
2510
            };
 
2511
 
 
2512
        }();
 
2513
 
 
2514
        var E = Y.Event;
 
2515
 
 
2516
        // Process onAvailable/onContentReady items when when the DOM is ready in IE
 
2517
        if (Y.UA.ie && Y.on) {
 
2518
            Y.on('event:ready', E._tryPreloadAttach, E, true);
 
2519
        }
 
2520
 
 
2521
        E.Custom = Y.CustomEvent;
 
2522
        E.Subscriber = Y.Subscriber;
 
2523
        E.Target = Y.EventTarget;
 
2524
 
 
2525
        /**
 
2526
         * Y.Event.on is an alias for addListener
 
2527
         * @method on
 
2528
         * @see addListener
 
2529
         * @static
 
2530
         */
 
2531
        E.attach = function(type, fn, el, data, context) {
 
2532
            var a = Y.Array(arguments, 0, true),
 
2533
                oEl = a.splice(2, 1);
 
2534
            a.unshift(oEl[0]);
 
2535
            return E.addListener.apply(E, a);
 
2536
        };
 
2537
 
 
2538
        E.detach = function(type, fn, el, data, context) {
 
2539
            return E.removeListener(el, type, fn, data, context);
 
2540
        };
 
2541
 
 
2542
        E.attach("load", E._load, window, E);
 
2543
        E.nativeAdd(window, "unload", E._unload);
 
2544
 
 
2545
        E._tryPreloadAttach();
 
2546
 
 
2547
}, "3.0.0");
 
2548
 
 
2549
})();
 
2550
/*
 
2551
 * A wrapper for DOM events and Custom Events
 
2552
 * @submodule event-facade
 
2553
 * @module event
 
2554
 */
 
2555
YUI.add("event-facade", function(Y) {
 
2556
 
 
2557
 
 
2558
    var whitelist = {
 
2559
        "altKey"          : 1,
 
2560
        // "button"          : 1, // we supply
 
2561
        // "bubbles"         : 1, // needed?
 
2562
        // "cancelable"      : 1, // needed? 
 
2563
        // "charCode"        : 1, // we supply
 
2564
        "cancelBubble"    : 1,
 
2565
        // "currentTarget"   : 1, // we supply
 
2566
        "ctrlKey"         : 1,
 
2567
        "clientX"         : 1, // needed?
 
2568
        "clientY"         : 1, // needed?
 
2569
        "detail"          : 1, // not fully implemented
 
2570
        // "fromElement"     : 1,
 
2571
        "keyCode"         : 1,
 
2572
        // "height"          : 1, // needed?
 
2573
        // "initEvent"       : 1, // need the init events?
 
2574
        // "initMouseEvent"  : 1,
 
2575
        // "initUIEvent"     : 1,
 
2576
        // "layerX"          : 1, // needed?
 
2577
        // "layerY"          : 1, // needed?
 
2578
        "metaKey"         : 1,
 
2579
        // "modifiers"       : 1, // needed?
 
2580
        // "offsetX"         : 1, // needed?
 
2581
        // "offsetY"         : 1, // needed?
 
2582
        // "preventDefault"  : 1, // we supply
 
2583
        // "reason"          : 1, // IE proprietary
 
2584
        // "relatedTarget"   : 1,
 
2585
        // "returnValue"     : 1, // needed?
 
2586
        "shiftKey"        : 1,
 
2587
        // "srcUrn"          : 1, // IE proprietary
 
2588
        // "srcElement"      : 1,
 
2589
        // "srcFilter"       : 1, IE proprietary
 
2590
        // "stopPropagation" : 1, // we supply
 
2591
        // "target"          : 1,
 
2592
        // "timeStamp"       : 1, // needed?
 
2593
        // "toElement"       : 1,
 
2594
        "type"            : 1,
 
2595
        // "view"            : 1,
 
2596
        // "which"           : 1, // we supply
 
2597
        // "width"           : 1, // needed?
 
2598
        "x"               : 1,
 
2599
        "y"               : 1
 
2600
    };
 
2601
 
 
2602
    var ua = Y.UA,
 
2603
 
 
2604
        /**
 
2605
         * webkit key remapping required for Safari < 3.1
 
2606
         * @property webkitKeymap
 
2607
         * @private
 
2608
         */
 
2609
        webkitKeymap = {
 
2610
            63232: 38, // up
 
2611
            63233: 40, // down
 
2612
            63234: 37, // left
 
2613
            63235: 39, // right
 
2614
            63276: 33, // page up
 
2615
            63277: 34, // page down
 
2616
            25: 9      // SHIFT-TAB (Safari provides a different key code in
 
2617
                       // this case, even though the shiftKey modifier is set)
 
2618
        },
 
2619
 
 
2620
        /**
 
2621
         * Returns a wrapped node.  Intended to be used on event targets,
 
2622
         * so it will return the node's parent if the target is a text
 
2623
         * node
 
2624
         * @method resolve
 
2625
         * @private
 
2626
         */
 
2627
        resolve = function(n) {
 
2628
 
 
2629
            if (!n) {
 
2630
                return null;
 
2631
            }
 
2632
 
 
2633
            try {
 
2634
                if (ua.webkit && 3 == n.nodeType) {
 
2635
                    n = n.parentNode;
 
2636
                } 
 
2637
            } catch(ex) { }
 
2638
 
 
2639
            return Y.Node.get(n);
 
2640
        };
 
2641
 
 
2642
 
 
2643
    // provide a single event with browser abstractions resolved
 
2644
    //
 
2645
    // include all properties for both browers?
 
2646
    // include only DOM2 spec properties?
 
2647
    // provide browser-specific facade?
 
2648
 
 
2649
    /**
 
2650
     * Wraps a DOM event, properties requiring browser abstraction are
 
2651
     * fixed here.  Provids a security layer when required.
 
2652
     * @class Event.Facade
 
2653
     * @param ev {Event} the DOM event
 
2654
     * @param currentTarget {HTMLElement} the element the listener was attached to
 
2655
     * @param wrapper {Event.Custom} the custom event wrapper for this DOM event
 
2656
     */
 
2657
    Y.Event.Facade = function(ev, currentTarget, wrapper, details) {
 
2658
 
 
2659
        // @TODO the document should be the target's owner document
 
2660
 
 
2661
        var e = ev, ot = currentTarget, d = Y.config.doc, b = d.body,
 
2662
            x = e.pageX, y = e.pageY, isCE = (ev._YUI_EVENT);
 
2663
 
 
2664
        // copy all primitives ... this is slow in FF
 
2665
        // for (var i in e) {
 
2666
        for (var i in whitelist) {
 
2667
            // if (!Y.Lang.isObject(e[i])) {
 
2668
            if (whitelist.hasOwnProperty(i)) {
 
2669
                this[i] = e[i];
 
2670
            }
 
2671
        }
 
2672
 
 
2673
        //////////////////////////////////////////////////////
 
2674
 
 
2675
        if (!x && 0 !== x) {
 
2676
            x = e.clientX || 0;
 
2677
            y = e.clientY || 0;
 
2678
 
 
2679
            if (ua.ie) {
 
2680
                x += Math.max(d.documentElement.scrollLeft, b.scrollLeft);
 
2681
                y += Math.max(d.documentElement.scrollTop, b.scrollTop);
 
2682
            }
 
2683
        }
 
2684
 
 
2685
        this._yuifacade = true;
 
2686
 
 
2687
        /**
 
2688
         * The X location of the event on the page (including scroll)
 
2689
         * @property pageX
 
2690
         * @type int
 
2691
         */
 
2692
        this.pageX = x;
 
2693
 
 
2694
        /**
 
2695
         * The Y location of the event on the page (including scroll)
 
2696
         * @property pageY
 
2697
         * @type int
 
2698
         */
 
2699
        this.pageY = y;
 
2700
 
 
2701
        //////////////////////////////////////////////////////
 
2702
 
 
2703
        /**
 
2704
         * The keyCode for key events.  Uses charCode if keyCode is not available
 
2705
         * @property keyCode
 
2706
         * @type int
 
2707
         */
 
2708
        var c = e.keyCode || e.charCode || 0;
 
2709
 
 
2710
        if (ua.webkit && (c in webkitKeymap)) {
 
2711
            c = webkitKeymap[c];
 
2712
        }
 
2713
 
 
2714
        /**
 
2715
         * The keyCode for key events.  Uses charCode if keyCode is not available
 
2716
         * @property keyCode
 
2717
         * @type int
 
2718
         */
 
2719
        this.keyCode = c;
 
2720
 
 
2721
        /**
 
2722
         * The charCode for key events.  Same as keyCode
 
2723
         * @property charCode
 
2724
         * @type int
 
2725
         */
 
2726
        this.charCode = c;
 
2727
 
 
2728
        //////////////////////////////////////////////////////
 
2729
 
 
2730
        /**
 
2731
         * The button that was pushed.
 
2732
         * @property button
 
2733
         * @type int
 
2734
         */
 
2735
        this.button = e.which || e.button;
 
2736
 
 
2737
        /**
 
2738
         * The button that was pushed.  Same as button.
 
2739
         * @property which
 
2740
         * @type int
 
2741
         */
 
2742
        this.which = this.button;
 
2743
 
 
2744
        /**
 
2745
         * The event details.  Currently supported for Custom
 
2746
         * Events only, where it contains the arguments that
 
2747
         * were passed to fire().
 
2748
         * @property details
 
2749
         * @type Array
 
2750
         */
 
2751
        this.details = details;
 
2752
 
 
2753
        //////////////////////////////////////////////////////
 
2754
 
 
2755
        /**
 
2756
         * Timestamp for the event
 
2757
         * @property time
 
2758
         * @type Date
 
2759
         */
 
2760
        this.time = e.time || new Date().getTime();
 
2761
 
 
2762
        //////////////////////////////////////////////////////
 
2763
        
 
2764
        /**
 
2765
         * Node reference for the targeted element
 
2766
         * @propery target
 
2767
         * @type Node
 
2768
         */
 
2769
        this.target = (isCE) ? e.target : resolve(e.target || e.srcElement);
 
2770
 
 
2771
        /**
 
2772
         * Node reference for the element that the listener was attached to.
 
2773
         * @propery currentTarget
 
2774
         * @type Node
 
2775
         */
 
2776
        this.currentTarget = (isCE) ? ot :  resolve(ot);
 
2777
 
 
2778
        var t = e.relatedTarget;
 
2779
        if (!t) {
 
2780
            if (e.type == "mouseout") {
 
2781
                t = e.toElement;
 
2782
            } else if (e.type == "mouseover") {
 
2783
                t = e.fromElement;
 
2784
            }
 
2785
        }
 
2786
 
 
2787
        /**
 
2788
         * Node reference to the relatedTarget
 
2789
         * @propery relatedTarget
 
2790
         * @type Node
 
2791
         */
 
2792
        this.relatedTarget = (isCE) ? t : resolve(t);
 
2793
        
 
2794
        //////////////////////////////////////////////////////
 
2795
        // methods
 
2796
 
 
2797
        /**
 
2798
         * Stops the propagation to the next bubble target
 
2799
         * @method stopPropagation
 
2800
         */
 
2801
        this.stopPropagation = function() {
 
2802
            if (e.stopPropagation) {
 
2803
                e.stopPropagation();
 
2804
            } else {
 
2805
                e.cancelBubble = true;
 
2806
            }
 
2807
            if (wrapper) {
 
2808
                wrapper.stopPropagation();
 
2809
            }
 
2810
        };
 
2811
 
 
2812
        /**
 
2813
         * Stops the propagation to the next bubble target and
 
2814
         * prevents any additional listeners from being exectued
 
2815
         * on the current target.
 
2816
         * @method stopImmediatePropagation
 
2817
         */
 
2818
        this.stopImmediatePropagation = function() {
 
2819
 
 
2820
            if (e.stopImmediatePropagation) {
 
2821
                e.stopImmediatePropagation();
 
2822
            } else {
 
2823
                this.stopPropagation();
 
2824
            }
 
2825
 
 
2826
            if (wrapper) {
 
2827
                wrapper.stopImmediatePropagation();
 
2828
            }
 
2829
 
 
2830
        };
 
2831
 
 
2832
        /**
 
2833
         * Prevents the event's default behavior
 
2834
         * @method preventDefault
 
2835
         */
 
2836
        this.preventDefault = function() {
 
2837
            if (e.preventDefault) {
 
2838
                e.preventDefault();
 
2839
            } else {
 
2840
                e.returnValue = false;
 
2841
            }
 
2842
            if (wrapper) {
 
2843
                wrapper.preventDefault();
 
2844
            }
 
2845
        };
 
2846
 
 
2847
        /**
 
2848
         * Stops the event propagation and prevents the default
 
2849
         * event behavior.
 
2850
         * @method halt
 
2851
         * @param immediate {boolean} if true additional listeners
 
2852
         * on the current target will not be executed
 
2853
         */
 
2854
        this.halt = function(immediate) {
 
2855
            if (immediate) {
 
2856
                this.stopImmediatePropagation();
 
2857
            } else {
 
2858
                this.stopPropagation();
 
2859
            }
 
2860
            this.preventDefault();
 
2861
        };
 
2862
 
 
2863
    };
 
2864
 
 
2865
}, "3.0.0");