Project

General

Profile

« Previous | Next » 

Revision 1263

Added by Dietmar over 14 years ago

updated YUI 2.4.1 to 2.8.0r4

View differences:

event-debug.js
1 1
/*
2
Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 3
Code licensed under the BSD License:
4 4
http://developer.yahoo.net/yui/license.txt
5
version: 2.4.1
5
version: 2.8.0r4
6 6
*/
7 7

  
8 8
/**
......
11 11
 *
12 12
 * @param {String}  type The type of event, which is passed to the callback
13 13
 *                  when the event fires
14
 * @param {Object}  oScope The context the event will fire from.  "this" will
14
 * @param {Object}  context The context the event will fire from.  "this" will
15 15
 *                  refer to this object in the callback.  Default value: 
16 16
 *                  the window object.  The listener can override this.
17 17
 * @param {boolean} silent pass true to prevent the event from writing to
......
20 20
 *                  will receive. YAHOO.util.CustomEvent.LIST or 
21 21
 *                  YAHOO.util.CustomEvent.FLAT.  The default is
22 22
 *                  YAHOO.util.CustomEvent.LIST.
23
 * @param fireOnce {boolean} If configured to fire once, the custom event 
24
 * will only notify subscribers a single time regardless of how many times 
25
 * the event is fired.  In addition, new subscribers will be notified 
26
 * immediately if the event has already been fired.
23 27
 * @namespace YAHOO.util
24 28
 * @class CustomEvent
25 29
 * @constructor
26 30
 */
27
YAHOO.util.CustomEvent = function(type, oScope, silent, signature) {
31
YAHOO.util.CustomEvent = function(type, context, silent, signature, fireOnce) {
28 32

  
29 33
    /**
30 34
     * The type of event, returned to subscribers when the event fires
......
34 38
    this.type = type;
35 39

  
36 40
    /**
37
     * The scope the the event will fire from by default.  Defaults to the window 
38
     * obj
41
     * The context the event will fire from by default. Defaults to the window obj.
39 42
     * @property scope
40 43
     * @type object
41 44
     */
42
    this.scope = oScope || window;
45
    this.scope = context || window;
43 46

  
44 47
    /**
45
     * By default all custom events are logged in the debug build, set silent
46
     * to true to disable debug outpu for this event.
48
     * By default all custom events are logged in the debug build. Set silent to true 
49
     * to disable debug output for this event.
47 50
     * @property silent
48 51
     * @type boolean
49 52
     */
50 53
    this.silent = silent;
51 54

  
52 55
    /**
56
     * If configured to fire once, the custom event will only notify subscribers
57
     * a single time regardless of how many times the event is fired.  In addition,
58
     * new subscribers will be notified immediately if the event has already been
59
     * fired.
60
     * @property fireOnce
61
     * @type boolean
62
     * @default false
63
     */
64
    this.fireOnce = fireOnce;
65

  
66
    /**
67
     * Indicates whether or not this event has ever been fired.
68
     * @property fired
69
     * @type boolean
70
     * @default false
71
     */
72
    this.fired = false;
73

  
74
    /**
75
     * For fireOnce events the arguments the event was fired with are stored
76
     * so that new subscribers get the proper payload.
77
     * @property firedWith
78
     * @type Array
79
     */
80
    this.firedWith = null;
81

  
82
    /**
53 83
     * Custom events support two styles of arguments provided to the event
54 84
     * subscribers.  
55 85
     * <ul>
......
98 128
         *
99 129
         * @event subscribeEvent
100 130
         * @type YAHOO.util.CustomEvent
101
         * @param {Function} fn The function to execute
102
         * @param {Object}   obj An object to be passed along when the event 
103
         *                       fires
104
         * @param {boolean|Object}  override If true, the obj passed in becomes 
105
         *                                   the execution scope of the listener.
106
         *                                   if an object, that object becomes the
107
         *                                   the execution scope.
131
         * @param fn {Function} The function to execute
132
         * @param obj <Object> An object to be passed along when the event fires. 
133
         * Defaults to the custom event.
134
         * @param override <boolean|Object> If true, the obj passed in becomes the 
135
         * execution context of the listener. If an object, that object becomes 
136
         * the execution context. Defaults to the custom event.
108 137
         */
109 138
        this.subscribeEvent = 
110 139
                new YAHOO.util.CustomEvent(onsubscribeType, this, true);
......
148 177
     * Subscribes the caller to this event
149 178
     * @method subscribe
150 179
     * @param {Function} fn        The function to execute
151
     * @param {Object}   obj       An object to be passed along when the event 
152
     *                             fires
153
     * @param {boolean|Object}  override If true, the obj passed in becomes 
154
     *                                   the execution scope of the listener.
155
     *                                   if an object, that object becomes the
156
     *                                   the execution scope.
180
     * @param {Object}   obj       An object to be passed along when the event fires.
181
     * overrideContext <boolean|Object> If true, the obj passed in becomes the execution 
182
     * context of the listener. If an object, that object becomes the execution context.
157 183
     */
158
    subscribe: function(fn, obj, override) {
184
    subscribe: function(fn, obj, overrideContext) {
159 185

  
160 186
        if (!fn) {
161 187
throw new Error("Invalid callback for subscriber to '" + this.type + "'");
162 188
        }
163 189

  
164 190
        if (this.subscribeEvent) {
165
            this.subscribeEvent.fire(fn, obj, override);
191
            this.subscribeEvent.fire(fn, obj, overrideContext);
166 192
        }
167 193

  
168
        this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, override) );
194
        var s = new YAHOO.util.Subscriber(fn, obj, overrideContext);
195

  
196
        if (this.fireOnce && this.fired) {
197
            this.notify(s, this.firedWith);
198
        } else {
199
            this.subscribers.push(s);
200
        }
169 201
    },
170 202

  
171 203
    /**
......
200 232

  
201 233
    /**
202 234
     * Notifies the subscribers.  The callback functions will be executed
203
     * from the scope specified when the event was created, and with the 
235
     * from the context specified when the event was created, and with the 
204 236
     * following parameters:
205 237
     *   <ul>
206 238
     *   <li>The type of event</li>
......
215 247
     *                   true otherwise
216 248
     */
217 249
    fire: function() {
218
        var len=this.subscribers.length;
219
        if (!len && this.silent) {
220
            return true;
250

  
251
        this.lastError = null;
252

  
253
        var errors = [],
254
            len=this.subscribers.length;
255

  
256

  
257
        var args=[].slice.call(arguments, 0), ret=true, i, rebuild=false;
258

  
259
        if (this.fireOnce) {
260
            if (this.fired) {
261
                YAHOO.log('fireOnce event has already fired: ' + this.type);
262
                return true;
263
            } else {
264
                this.firedWith = args;
265
            }
221 266
        }
222 267

  
223
        var args=[], ret=true, i, rebuild=false;
268
        this.fired = true;
224 269

  
225
        for (i=0; i<arguments.length; ++i) {
226
            args.push(arguments[i]);
270
        if (!len && this.silent) {
271
            //YAHOO.log('DEBUG no subscribers');
272
            return true;
227 273
        }
228 274

  
229 275
        if (!this.silent) {
......
233 279
                       "info", "Event"                  );
234 280
        }
235 281

  
282
        // make a copy of the subscribers so that there are
283
        // no index problems if one subscriber removes another.
284
        var subs = this.subscribers.slice();
285

  
236 286
        for (i=0; i<len; ++i) {
237
            var s = this.subscribers[i];
287
            var s = subs[i];
238 288
            if (!s) {
239 289
                rebuild=true;
240 290
            } else {
241
                if (!this.silent) {
242
                    YAHOO.log( this.type + "->" + (i+1) + ": " +  s, 
243
                                "info", "Event" );
244
                }
245 291

  
246
                var scope = s.getScope(this.scope);
292
                ret = this.notify(s, args);
247 293

  
248
                if (this.signature == YAHOO.util.CustomEvent.FLAT) {
249
                    var param = null;
250
                    if (args.length > 0) {
251
                        param = args[0];
252
                    }
253

  
254
                    try {
255
                        ret = s.fn.call(scope, param, s.obj);
256
                    } catch(e) {
257
                        this.lastError = e;
258
                        YAHOO.log(this + " subscriber exception: " + e,
259
                                  "error", "Event");
260
                    }
261
                } else {
262
                    try {
263
                        ret = s.fn.call(scope, this.type, args, s.obj);
264
                    } catch(ex) {
265
                        this.lastError = ex;
266
                        YAHOO.log(this + " subscriber exception: " + ex,
267
                                  "error", "Event");
268
                    }
269
                }
270 294
                if (false === ret) {
271 295
                    if (!this.silent) {
272
                        YAHOO.log("Event cancelled, subscriber " + i + 
273
                                  " of " + len, "info", "Event");
296
                        YAHOO.log("Event stopped, sub " + i + " of " + len, "info", "Event");
274 297
                    }
275 298

  
276
                    //break;
277
                    return false;
299
                    break;
278 300
                }
279 301
            }
280 302
        }
281 303

  
282
        if (rebuild) {
283
            var newlist=[],subs=this.subscribers;
284
            for (i=0,len=subs.length; i<len; i=i+1) {
285
                newlist.push(subs[i]);
304
        return (ret !== false);
305
    },
306

  
307
    notify: function(s, args) {
308

  
309
        var ret, param=null, scope = s.getScope(this.scope),
310
                 throwErrors = YAHOO.util.Event.throwErrors;
311

  
312
        if (!this.silent) {
313
            YAHOO.log( this.type + "-> " + s, "info", "Event" );
314
        }
315

  
316
        if (this.signature == YAHOO.util.CustomEvent.FLAT) {
317

  
318
            if (args.length > 0) {
319
                param = args[0];
286 320
            }
287 321

  
288
            this.subscribers=newlist;
322
            try {
323
                ret = s.fn.call(scope, param, s.obj);
324
            } catch(e) {
325
                this.lastError = e;
326
                // errors.push(e);
327
                YAHOO.log(this + " subscriber exception: " + e, "error", "Event");
328
                if (throwErrors) {
329
                    throw e;
330
                }
331
            }
332
        } else {
333
            try {
334
                ret = s.fn.call(scope, this.type, args, s.obj);
335
            } catch(ex) {
336
                this.lastError = ex;
337
                YAHOO.log(this + " subscriber exception: " + ex, "error", "Event");
338
                if (throwErrors) {
339
                    throw ex;
340
                }
341
            }
289 342
        }
290 343

  
291
        return true;
344
        return ret;
292 345
    },
293 346

  
294 347
    /**
......
297 350
     * @return {int} The number of listeners unsubscribed
298 351
     */
299 352
    unsubscribeAll: function() {
300
        for (var i=0, len=this.subscribers.length; i<len; ++i) {
301
            this._delete(len - 1 - i);
353
        var l = this.subscribers.length, i;
354
        for (i=l-1; i>-1; i--) {
355
            this._delete(i);
302 356
        }
303 357

  
304 358
        this.subscribers=[];
305 359

  
306
        return i;
360
        return l;
307 361
    },
308 362

  
309 363
    /**
......
317 371
            delete s.obj;
318 372
        }
319 373

  
320
        this.subscribers[index]=null;
374
        // this.subscribers[index]=null;
375
        this.subscribers.splice(index, 1);
321 376
    },
322 377

  
323 378
    /**
......
325 380
     */
326 381
    toString: function() {
327 382
         return "CustomEvent: " + "'" + this.type  + "', " + 
328
             "scope: " + this.scope;
383
             "context: " + this.scope;
329 384

  
330 385
    }
331 386
};
......
336 391
 * Stores the subscriber information to be used when the event fires.
337 392
 * @param {Function} fn       The function to execute
338 393
 * @param {Object}   obj      An object to be passed along when the event fires
339
 * @param {boolean}  override If true, the obj passed in becomes the execution
340
 *                            scope of the listener
394
 * @param {boolean}  overrideContext If true, the obj passed in becomes the execution
395
 *                            context of the listener
341 396
 * @class Subscriber
342 397
 * @constructor
343 398
 */
344
YAHOO.util.Subscriber = function(fn, obj, override) {
399
YAHOO.util.Subscriber = function(fn, obj, overrideContext) {
345 400

  
346 401
    /**
347 402
     * The callback that will be execute when the event fires
......
359 414
    this.obj = YAHOO.lang.isUndefined(obj) ? null : obj;
360 415

  
361 416
    /**
362
     * The default execution scope for the event listener is defined when the
417
     * The default execution context for the event listener is defined when the
363 418
     * event is created (usually the object which contains the event).
364
     * By setting override to true, the execution scope becomes the custom
365
     * object passed in by the subscriber.  If override is an object, that 
366
     * object becomes the scope.
367
     * @property override
419
     * By setting overrideContext to true, the execution context becomes the custom
420
     * object passed in by the subscriber.  If overrideContext is an object, that 
421
     * object becomes the context.
422
     * @property overrideContext
368 423
     * @type boolean|object
369 424
     */
370
    this.override = override;
425
    this.overrideContext = overrideContext;
371 426

  
372 427
};
373 428

  
374 429
/**
375
 * Returns the execution scope for this listener.  If override was set to true
376
 * the custom obj will be the scope.  If override is an object, that is the
377
 * scope, otherwise the default scope will be used.
430
 * Returns the execution context for this listener.  If overrideContext was set to true
431
 * the custom obj will be the context.  If overrideContext is an object, that is the
432
 * context, otherwise the default context will be used.
378 433
 * @method getScope
379
 * @param {Object} defaultScope the scope to use if this listener does not
434
 * @param {Object} defaultScope the context to use if this listener does not
380 435
 *                              override it.
381 436
 */
382 437
YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) {
383
    if (this.override) {
384
        if (this.override === true) {
438
    if (this.overrideContext) {
439
        if (this.overrideContext === true) {
385 440
            return this.obj;
386 441
        } else {
387
            return this.override;
442
            return this.overrideContext;
388 443
        }
389 444
    }
390 445
    return defaultScope;
......
413 468
 */
414 469
YAHOO.util.Subscriber.prototype.toString = function() {
415 470
    return "Subscriber { obj: " + this.obj  + 
416
           ", override: " +  (this.override || "no") + " }";
471
           ", overrideContext: " +  (this.overrideContext || "no") + " }";
417 472
};
418 473

  
419 474
/**
......
449 504
         * @static
450 505
         * @private
451 506
         */
452
        var loadComplete =  false;
507
        var loadComplete =  false,
453 508

  
454 509
        /**
455 510
         * Cache of wrapped listeners
......
458 513
         * @static
459 514
         * @private
460 515
         */
461
        var listeners = [];
516
        listeners = [],
462 517

  
518

  
463 519
        /**
464 520
         * User-defined unload function that will be fired before all events
465 521
         * are detached
......
468 524
         * @static
469 525
         * @private
470 526
         */
471
        var unloadListeners = [];
527
        unloadListeners = [],
472 528

  
473 529
        /**
474
         * Cache of DOM0 event handlers to work around issues with DOM2 events
475
         * in Safari
476
         * @property legacyEvents
477
         * @static
478
         * @private
479
         */
480
        var legacyEvents = [];
481

  
482
        /**
483
         * Listener stack for DOM0 events
484
         * @property legacyHandlers
485
         * @static
486
         * @private
487
         */
488
        var legacyHandlers = [];
489

  
490
        /**
491 530
         * The number of times to poll after window.onload.  This number is
492 531
         * increased if additional late-bound handlers are requested after
493 532
         * the page load.
......
495 534
         * @static
496 535
         * @private
497 536
         */
498
        var retryCount = 0;
537
        retryCount = 0,
499 538

  
500 539
        /**
501 540
         * onAvailable listeners
......
503 542
         * @static
504 543
         * @private
505 544
         */
506
        var onAvailStack = [];
545
        onAvailStack = [],
507 546

  
508 547
        /**
509
         * Lookup table for legacy events
510
         * @property legacyMap
511
         * @static
512
         * @private
513
         */
514
        var legacyMap = [];
515

  
516
        /**
517 548
         * Counter for auto id generation
518 549
         * @property counter
519 550
         * @static
520 551
         * @private
521 552
         */
522
        var counter = 0;
553
        counter = 0,
523 554
        
524 555
        /**
525 556
         * Normalized keycodes for webkit/safari
......
529 560
         * @static
530 561
         * @final
531 562
         */
532
        var webkitKeymap = {
563
         webkitKeymap = {
533 564
            63232: 38, // up
534 565
            63233: 40, // down
535 566
            63234: 37, // left
......
538 569
            63277: 34, // page down
539 570
            25: 9      // SHIFT-TAB (Safari provides a different key code in
540 571
                       // this case, even though the shiftKey modifier is set)
541
        };
572
        },
542 573

  
574
		isIE = YAHOO.env.ua.ie,
575

  
576
        // String constants used by the addFocusListener and removeFocusListener methods
577
		
578
       	FOCUSIN = "focusin",
579
       	FOCUSOUT = "focusout";
580

  
543 581
        return {
544 582

  
545 583
            /**
546 584
             * The number of times we should look for elements that are not
547 585
             * in the DOM at the time the event is requested after the document
548
             * has been loaded.  The default is 4000@amp;10 ms, so it will poll
549
             * for 40 seconds or until all outstanding handlers are bound
586
             * has been loaded.  The default is 500@amp;40 ms, so it will poll
587
             * for 20 seconds or until all outstanding handlers are bound
550 588
             * (whichever comes first).
551 589
             * @property POLL_RETRYS
552 590
             * @type int
553 591
             * @static
554 592
             * @final
555 593
             */
556
            POLL_RETRYS: 4000,
594
            POLL_RETRYS: 500,
557 595

  
558 596
            /**
559 597
             * The poll interval in milliseconds
......
562 600
             * @static
563 601
             * @final
564 602
             */
565
            POLL_INTERVAL: 10,
603
            POLL_INTERVAL: 40,
566 604

  
567 605
            /**
568 606
             * Element to bind, int constant
......
592 630
            FN: 2,
593 631

  
594 632
            /**
595
             * Function wrapped for scope correction and cleanup, int constant
633
             * Function wrapped for context correction and cleanup, int constant
596 634
             * @property WFN
597 635
             * @type int
598 636
             * @static
......
612 650
            UNLOAD_OBJ: 3,
613 651

  
614 652
            /**
615
             * Adjusted scope, either the element we are registering the event
653
             * Adjusted context, either the element we are registering the event
616 654
             * on or the custom object passed in by the listener, int constant
617 655
             * @property ADJ_SCOPE
618 656
             * @type int
......
631 669
            OBJ: 5,
632 670

  
633 671
            /**
634
             * The original scope parameter passed into addListener
672
             * The original context parameter passed into addListener
635 673
             * @property OVERRIDE
636 674
             * @type int
637 675
             * @static
......
640 678
            OVERRIDE: 6,
641 679

  
642 680
            /**
681
             * The original capture parameter passed into addListener
682
             * @property CAPTURE
683
             * @type int
684
             * @static
685
             * @final
686
             */
687
			CAPTURE: 7,
688

  
689
            /**
643 690
             * addListener/removeListener can throw errors in unexpected scenarios.
644 691
             * These errors are suppressed, the method returns false, and this property
645 692
             * is set
......
675 722
             * @static
676 723
             * @deprecated use YAHOO.env.ua.ie
677 724
             */
678
            isIE: YAHOO.env.ua.ie,
725
            isIE: isIE,
679 726

  
680 727
            /**
681 728
             * poll handle
......
693 740
             */
694 741
             _dri: null,
695 742

  
743

  
696 744
            /**
745
             * Map of special event types
746
             * @property _specialTypes
747
             * @static
748
             * @private
749
             */
750
			_specialTypes: {
751
				focusin: (isIE ? "focusin" : "focus"),
752
				focusout: (isIE ? "focusout" : "blur")
753
			},
754

  
755

  
756
            /**
697 757
             * True when the document is initially usable
698 758
             * @property DOMReady
699 759
             * @type boolean
......
702 762
            DOMReady: false,
703 763

  
704 764
            /**
765
             * Errors thrown by subscribers of custom events are caught
766
             * and the error message is written to the debug console.  If
767
             * this property is set to true, it will also re-throw the
768
             * error.
769
             * @property throwErrors
770
             * @type boolean
771
             * @default false
772
             */
773
            throwErrors: false,
774

  
775

  
776
            /**
705 777
             * @method startInterval
706 778
             * @static
707 779
             * @private
708 780
             */
709 781
            startInterval: function() {
710 782
                if (!this._interval) {
711
                    var self = this;
712
                    var callback = function() { self._tryPreloadAttach(); };
713
                    this._interval = setInterval(callback, this.POLL_INTERVAL);
783
                    // var self = this;
784
                    // var callback = function() { self._tryPreloadAttach(); };
785
                    // this._interval = setInterval(callback, this.POLL_INTERVAL);
786
                    this._interval = YAHOO.lang.later(this.POLL_INTERVAL, this, this._tryPreloadAttach, null, true);
714 787
                }
715 788
            },
716 789

  
......
727 800
             *
728 801
             * @method onAvailable
729 802
             *
730
             * @param {string||string[]}   p_id the id of the element, or an array
803
             * @param {string||string[]}   id the id of the element, or an array
731 804
             * of ids to look for.
732
             * @param {function} p_fn what to execute when the element is found.
733
             * @param {object}   p_obj an optional object to be passed back as
734
             *                   a parameter to p_fn.
735
             * @param {boolean|object}  p_override If set to true, p_fn will execute
736
             *                   in the scope of p_obj, if set to an object it
737
             *                   will execute in the scope of that object
805
             * @param {function} fn what to execute when the element is found.
806
             * @param {object}   obj an optional object to be passed back as
807
             *                   a parameter to fn.
808
             * @param {boolean|object}  overrideContext If set to true, fn will execute
809
             *                   in the context of obj, if set to an object it
810
             *                   will execute in the context of that object
738 811
             * @param checkContent {boolean} check child node readiness (onContentReady)
739 812
             * @static
740 813
             */
741
            onAvailable: function(p_id, p_fn, p_obj, p_override, checkContent) {
814
            onAvailable: function(id, fn, obj, overrideContext, checkContent) {
742 815

  
743
                var a = (YAHOO.lang.isString(p_id)) ? [p_id] : p_id;
816
                var a = (YAHOO.lang.isString(id)) ? [id] : id;
744 817

  
745 818
                for (var i=0; i<a.length; i=i+1) {
746 819
                    onAvailStack.push({id:         a[i], 
747
                                       fn:         p_fn, 
748
                                       obj:        p_obj, 
749
                                       override:   p_override, 
820
                                       fn:         fn, 
821
                                       obj:        obj, 
822
                                       overrideContext:   overrideContext, 
750 823
                                       checkReady: checkContent });
751 824
                }
825

  
752 826
                retryCount = this.POLL_RETRYS;
827

  
753 828
                this.startInterval();
754 829
            },
755 830

  
......
763 838
             *
764 839
             * @method onContentReady
765 840
             *
766
             * @param {string}   p_id the id of the element to look for.
767
             * @param {function} p_fn what to execute when the element is ready.
768
             * @param {object}   p_obj an optional object to be passed back as
769
             *                   a parameter to p_fn.
770
             * @param {boolean|object}  p_override If set to true, p_fn will execute
771
             *                   in the scope of p_obj.  If an object, p_fn will
772
             *                   exectute in the scope of that object
841
             * @param {string}   id the id of the element to look for.
842
             * @param {function} fn what to execute when the element is ready.
843
             * @param {object}   obj an optional object to be passed back as
844
             *                   a parameter to fn.
845
             * @param {boolean|object}  overrideContext If set to true, fn will execute
846
             *                   in the context of obj.  If an object, fn will
847
             *                   exectute in the context of that object
773 848
             *
774 849
             * @static
775 850
             */
776
            onContentReady: function(p_id, p_fn, p_obj, p_override) {
777
                this.onAvailable(p_id, p_fn, p_obj, p_override, true);
851
            onContentReady: function(id, fn, obj, overrideContext) {
852
                this.onAvailable(id, fn, obj, overrideContext, true);
778 853
            },
779 854

  
780 855
            /**
......
800 875
             *
801 876
             * @method onDOMReady
802 877
             *
803
             * @param {function} p_fn what to execute when the element is found.
804
             * @param {object}   p_obj an optional object to be passed back as
805
             *                   a parameter to p_fn.
806
             * @param {boolean|object}  p_scope If set to true, p_fn will execute
807
             *                   in the scope of p_obj, if set to an object it
808
             *                   will execute in the scope of that object
878
             * @param {function} fn what to execute when the element is found.
879
             * @param {object}   obj an optional object to be passed back as
880
             *                   a parameter to fn.
881
             * @param {boolean|object}  overrideContext If set to true, fn will execute
882
             *                   in the context of obj, if set to an object it
883
             *                   will execute in the context of that object
809 884
             *
810 885
             * @static
811 886
             */
812
            onDOMReady: function(p_fn, p_obj, p_override) {
813
                if (this.DOMReady) {
814
                    setTimeout(function() {
815
                        var s = window;
816
                        if (p_override) {
817
                            if (p_override === true) {
818
                                s = p_obj;
819
                            } else {
820
                                s = p_override;
821
                            }
822
                        }
823
                        p_fn.call(s, "DOMReady", [], p_obj);
824
                    }, 0);
825
                } else {
826
                    this.DOMReadyEvent.subscribe(p_fn, p_obj, p_override);
827
                }
887
            // onDOMReady: function(fn, obj, overrideContext) {
888
            onDOMReady: function() {
889
                this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent, arguments);
828 890
            },
829 891

  
892

  
830 893
            /**
831 894
             * Appends an event handler
832 895
             *
833
             * @method addListener
896
             * @method _addListener
834 897
             *
835 898
             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
836 899
             *  reference, or a collection of ids and/or elements to assign the 
......
839 902
             * @param {Function} fn        The method the event invokes
840 903
             * @param {Object}   obj    An arbitrary object that will be 
841 904
             *                             passed as a parameter to the handler
842
             * @param {Boolean|object}  override  If true, the obj passed in becomes
843
             *                             the execution scope of the listener. If an
905
             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
906
             *                             the execution context of the listener. If an
844 907
             *                             object, this object becomes the execution
845
             *                             scope.
908
             *                             context.
909
             * @param {boolen}      capture capture or bubble phase
846 910
             * @return {Boolean} True if the action was successful or defered,
847 911
             *                        false if one or more of the elements 
848 912
             *                        could not have the listener attached,
849 913
             *                        or if the operation throws an exception.
914
             * @private
850 915
             * @static
851 916
             */
852
            addListener: function(el, sType, fn, obj, override) {
917
            _addListener: function(el, sType, fn, obj, overrideContext, bCapture) {
853 918

  
854 919
                if (!fn || !fn.call) {
855
// throw new TypeError(sType + " addListener call failed, callback undefined");
856
YAHOO.log(sType + " addListener call failed, invalid callback", "error", "Event");
920
                    YAHOO.log(sType + " addListener failed, invalid callback", "error", "Event");
857 921
                    return false;
858 922
                }
859 923

  
......
865 929
                                       sType, 
866 930
                                       fn, 
867 931
                                       obj, 
868
                                       override) && ok;
932
                                       overrideContext) && ok;
869 933
                    }
870 934
                    return ok;
871 935

  
......
883 947
                    } else {
884 948
                        // defer adding the event until the element is available
885 949
                        this.onAvailable(el, function() {
886
                           YAHOO.util.Event.on(el, sType, fn, obj, override);
950
                           YAHOO.util.Event._addListener(el, sType, fn, obj, overrideContext, bCapture);
887 951
                        });
888 952

  
889 953
                        return true;
......
903 967
                // handles explicitly during our one unload event.
904 968
                if ("unload" == sType && obj !== this) {
905 969
                    unloadListeners[unloadListeners.length] =
906
                            [el, sType, fn, obj, override];
970
                            [el, sType, fn, obj, overrideContext];
907 971
                    return true;
908 972
                }
909 973

  
910 974
                // this.logger.debug("Adding handler: " + el + ", " + sType);
911 975

  
912
                // if the user chooses to override the scope, we use the custom
913
                // object passed in, otherwise the executing scope will be the
976
                // if the user chooses to override the context, we use the custom
977
                // object passed in, otherwise the executing context will be the
914 978
                // HTML element that the event is registered on
915
                var scope = el;
916
                if (override) {
917
                    if (override === true) {
918
                        scope = obj;
979
                var context = el;
980
                if (overrideContext) {
981
                    if (overrideContext === true) {
982
                        context = obj;
919 983
                    } else {
920
                        scope = override;
984
                        context = overrideContext;
921 985
                    }
922 986
                }
923 987

  
924 988
                // wrap the function so we can return the obj object when
925 989
                // the event fires;
926 990
                var wrappedFn = function(e) {
927
                        return fn.call(scope, YAHOO.util.Event.getEvent(e, el), 
991
                        return fn.call(context, YAHOO.util.Event.getEvent(e, el), 
928 992
                                obj);
929 993
                    };
930 994

  
931
                var li = [el, sType, fn, wrappedFn, scope, obj, override];
995
                var li = [el, sType, fn, wrappedFn, context, obj, overrideContext, bCapture];
932 996
                var index = listeners.length;
933 997
                // cache the listener so we can try to automatically unload
934 998
                listeners[index] = li;
935 999

  
936
                if (this.useLegacyEvent(el, sType)) {
937
                    var legacyIndex = this.getLegacyIndex(el, sType);
1000
                try {
1001
                    this._simpleAdd(el, sType, wrappedFn, bCapture);
1002
                } catch(ex) {
1003
                    // handle an error trying to attach an event.  If it fails
1004
                    // we need to clean up the cache
1005
                    this.lastError = ex;
1006
                    this.removeListener(el, sType, fn);
1007
                    return false;
1008
                }
938 1009

  
939
                    // Add a new dom0 wrapper if one is not detected for this
940
                    // element
941
                    if ( legacyIndex == -1 || 
942
                                el != legacyEvents[legacyIndex][0] ) {
1010
                return true;
1011
                
1012
            },
943 1013

  
944
                        legacyIndex = legacyEvents.length;
945
                        legacyMap[el.id + sType] = legacyIndex;
1014
            /**
1015
             * Checks to see if the type requested is a special type 
1016
			 * (as defined by the _specialTypes hash), and (if so) returns 
1017
			 * the special type name.
1018
             *
1019
             * @method _getType
1020
             *
1021
             * @param {String}   sType     The type to look up
1022
             * @private
1023
             */
1024
			_getType: function (type) {
1025
			
1026
				return this._specialTypes[type] || type;
1027
				
1028
			},
946 1029

  
947
                        // cache the signature for the DOM0 event, and 
948
                        // include the existing handler for the event, if any
949
                        legacyEvents[legacyIndex] = 
950
                            [el, sType, el["on" + sType]];
951
                        legacyHandlers[legacyIndex] = [];
952 1030

  
953
                        el["on" + sType] = 
954
                            function(e) {
955
                                YAHOO.util.Event.fireLegacyEvent(
956
                                    YAHOO.util.Event.getEvent(e), legacyIndex);
957
                            };
958
                    }
1031
            /**
1032
             * Appends an event handler
1033
             *
1034
             * @method addListener
1035
             *
1036
             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
1037
             *  reference, or a collection of ids and/or elements to assign the 
1038
             *  listener to.
1039
             * @param {String}   sType     The type of event to append
1040
             * @param {Function} fn        The method the event invokes
1041
             * @param {Object}   obj    An arbitrary object that will be 
1042
             *                             passed as a parameter to the handler
1043
             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1044
             *                             the execution context of the listener. If an
1045
             *                             object, this object becomes the execution
1046
             *                             context.
1047
             * @return {Boolean} True if the action was successful or defered,
1048
             *                        false if one or more of the elements 
1049
             *                        could not have the listener attached,
1050
             *                        or if the operation throws an exception.
1051
             * @static
1052
             */
1053
            addListener: function (el, sType, fn, obj, overrideContext) {
959 1054

  
960
                    // add a reference to the wrapped listener to our custom
961
                    // stack of events
962
                    //legacyHandlers[legacyIndex].push(index);
963
                    legacyHandlers[legacyIndex].push(li);
1055
				var capture = ((sType == FOCUSIN || sType == FOCUSOUT) && !YAHOO.env.ua.ie) ? true : false;
964 1056

  
965
                } else {
966
                    try {
967
                        this._simpleAdd(el, sType, wrappedFn, false);
968
                    } catch(ex) {
969
                        // handle an error trying to attach an event.  If it fails
970
                        // we need to clean up the cache
971
                        this.lastError = ex;
972
                        this.removeListener(el, sType, fn);
973
                        return false;
974
                    }
975
                }
1057
                return this._addListener(el, this._getType(sType), fn, obj, overrideContext, capture);
976 1058

  
977
                return true;
978
                
979
            },
1059
        	},
980 1060

  
1061

  
981 1062
            /**
982
             * When using legacy events, the handler is routed to this object
983
             * so we can fire our custom listener stack.
984
             * @method fireLegacyEvent
1063
             * Attaches a focusin event listener to the specified element for 
1064
 			 * the purpose of listening for the focus event on the element's 
1065
             * descendants.
1066
             * @method addFocusListener
1067
             *
1068
             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
1069
             *  reference, or a collection of ids and/or elements to assign the 
1070
             *  listener to.
1071
             * @param {Function} fn        The method the event invokes
1072
             * @param {Object}   obj    An arbitrary object that will be 
1073
             *                             passed as a parameter to the handler
1074
             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1075
             *                             the execution context of the listener. If an
1076
             *                             object, this object becomes the execution
1077
             *                             context.
1078
             * @return {Boolean} True if the action was successful or defered,
1079
             *                        false if one or more of the elements 
1080
             *                        could not have the listener attached,
1081
             *                        or if the operation throws an exception.
985 1082
             * @static
986
             * @private
1083
			* @deprecated use YAHOO.util.Event.on and specify "focusin" as the event type.
987 1084
             */
988
            fireLegacyEvent: function(e, legacyIndex) {
989
                // this.logger.debug("fireLegacyEvent " + legacyIndex);
990
                var ok=true,le,lh,li,scope,ret;
991
                
992
                lh = legacyHandlers[legacyIndex];
993
                for (var i=0,len=lh.length; i<len; ++i) {
994
                    li = lh[i];
995
                    if ( li && li[this.WFN] ) {
996
                        scope = li[this.ADJ_SCOPE];
997
                        ret = li[this.WFN].call(scope, e);
998
                        ok = (ok && ret);
999
                    }
1000
                }
1085
            addFocusListener: function (el, fn, obj, overrideContext) {
1086
                return this.on(el, FOCUSIN, fn, obj, overrideContext);
1087
            },          
1001 1088

  
1002
                // Fire the original handler if we replaced one.  We fire this
1003
                // after the other events to keep stopPropagation/preventDefault
1004
                // that happened in the DOM0 handler from touching our DOM2
1005
                // substitute
1006
                le = legacyEvents[legacyIndex];
1007
                if (le && le[2]) {
1008
                    le[2](e);
1009
                }
1010
                
1011
                return ok;
1012
            },
1013 1089

  
1014 1090
            /**
1015
             * Returns the legacy event index that matches the supplied 
1016
             * signature
1017
             * @method getLegacyIndex
1091
             * Removes a focusin event listener to the specified element for 
1092
			 * the purpose of listening for the focus event on the element's 
1093
             * descendants.
1094
             *
1095
             * @method removeFocusListener
1096
             *
1097
             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
1098
             *  reference, or a collection of ids and/or elements to remove
1099
             *  the listener from.
1100
             * @param {Function} fn the method the event invokes.  If fn is
1101
             *  undefined, then all event handlers for the type of event are 
1102
             *  removed.
1103
             * @return {boolean} true if the unbind was successful, false 
1104
             *  otherwise.
1018 1105
             * @static
1019
             * @private
1106
         	 * @deprecated use YAHOO.util.Event.removeListener and specify "focusin" as the event type.
1020 1107
             */
1021
            getLegacyIndex: function(el, sType) {
1022
                var key = this.generateId(el) + sType;
1023
                if (typeof legacyMap[key] == "undefined") { 
1024
                    return -1;
1025
                } else {
1026
                    return legacyMap[key];
1027
                }
1108
            removeFocusListener: function (el, fn) { 
1109
                return this.removeListener(el, FOCUSIN, fn);
1028 1110
            },
1029 1111

  
1030 1112
            /**
1031
             * Logic that determines when we should automatically use legacy
1032
             * events instead of DOM2 events.  Currently this is limited to old
1033
             * Safari browsers with a broken preventDefault
1034
             * @method useLegacyEvent
1113
             * Attaches a focusout event listener to the specified element for 
1114
			 * the purpose of listening for the blur event on the element's 
1115
			 * descendants.
1116
             *
1117
             * @method addBlurListener
1118
             *
1119
             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
1120
             *  reference, or a collection of ids and/or elements to assign the 
1121
             *  listener to.
1122
             * @param {Function} fn        The method the event invokes
1123
             * @param {Object}   obj    An arbitrary object that will be 
1124
             *                             passed as a parameter to the handler
1125
             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1126
             *                             the execution context of the listener. If an
1127
             *                             object, this object becomes the execution
1128
             *                             context.
1129
             * @return {Boolean} True if the action was successful or defered,
1130
             *                        false if one or more of the elements 
1131
             *                        could not have the listener attached,
1132
             *                        or if the operation throws an exception.
1035 1133
             * @static
1036
             * @private
1134
         	 * @deprecated use YAHOO.util.Event.on and specify "focusout" as the event type.
1037 1135
             */
1038
            useLegacyEvent: function(el, sType) {
1039
                if (this.webkit && ("click"==sType || "dblclick"==sType)) {
1040
                    var v = parseInt(this.webkit, 10);
1041
                    if (!isNaN(v) && v<418) {
1042
                        return true;
1043
                    }
1044
                }
1045
                return false;
1136
            addBlurListener: function (el, fn, obj, overrideContext) {
1137
                return this.on(el, FOCUSOUT, fn, obj, overrideContext);
1138
            },          
1139

  
1140
            /**
1141
             * Removes a focusout event listener to the specified element for 
1142
			 * the purpose of listening for the blur event on the element's 
1143
			 * descendants.
1144
             *
1145
             * @method removeBlurListener
1146
             *
1147
             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
1148
             *  reference, or a collection of ids and/or elements to remove
1149
             *  the listener from.
1150
             * @param {Function} fn the method the event invokes.  If fn is
1151
             *  undefined, then all event handlers for the type of event are 
1152
             *  removed.
1153
             * @return {boolean} true if the unbind was successful, false 
1154
             *  otherwise.
1155
             * @static
1156
         	 * @deprecated use YAHOO.util.Event.removeListener and specify "focusout" as the event type.
1157
             */
1158
            removeBlurListener: function (el, fn) { 
1159
                return this.removeListener(el, FOCUSOUT, fn);
1046 1160
            },
1047
                    
1161

  
1048 1162
            /**
1049 1163
             * Removes an event listener
1050 1164
             *
......
1064 1178
            removeListener: function(el, sType, fn) {
1065 1179
                var i, len, li;
1066 1180

  
1181
				sType = this._getType(sType);
1182

  
1067 1183
                // The el argument can be a string
1068 1184
                if (typeof el == "string") {
1069 1185
                    el = this.getEl(el);
1070 1186
                // The el argument can be an array of elements or element ids.
1071 1187
                } else if ( this._isValidCollection(el)) {
1072 1188
                    var ok = true;
1073
                    for (i=0,len=el.length; i<len; ++i) {
1189
                    for (i=el.length-1; i>-1; i--) {
1074 1190
                        ok = ( this.removeListener(el[i], sType, fn) && ok );
1075 1191
                    }
1076 1192
                    return ok;
......
1084 1200

  
1085 1201
                if ("unload" == sType) {
1086 1202

  
1087
                    for (i=0, len=unloadListeners.length; i<len; i++) {
1203
                    for (i=unloadListeners.length-1; i>-1; i--) {
1088 1204
                        li = unloadListeners[i];
1089 1205
                        if (li && 
1090 1206
                            li[0] == el && 
1091 1207
                            li[1] == sType && 
1092 1208
                            li[2] == fn) {
1093
                                //unloadListeners.splice(i, 1);
1094
                                unloadListeners[i]=null;
1209
                                unloadListeners.splice(i, 1);
1210
                                // unloadListeners[i]=null;
1095 1211
                                return true;
1096 1212
                        }
1097 1213
                    }
......
1107 1223
                var index = arguments[3];
1108 1224
  
1109 1225
                if ("undefined" === typeof index) {
1110
                    index = this._getCacheIndex(el, sType, fn);
1226
                    index = this._getCacheIndex(listeners, el, sType, fn);
1111 1227
                }
1112 1228

  
1113 1229
                if (index >= 0) {
......
1121 1237

  
1122 1238
                // this.logger.debug("Removing handler: " + el + ", " + sType);
1123 1239

  
1124
                if (this.useLegacyEvent(el, sType)) {
1125
                    var legacyIndex = this.getLegacyIndex(el, sType);
1126
                    var llist = legacyHandlers[legacyIndex];
1127
                    if (llist) {
1128
                        for (i=0, len=llist.length; i<len; ++i) {
1129
                            li = llist[i];
1130
                            if (li && 
1131
                                li[this.EL] == el && 
1132
                                li[this.TYPE] == sType && 
1133
                                li[this.FN] == fn) {
1134
                                    //llist.splice(i, 1);
1135
                                    llist[i]=null;
1136
                                    break;
1137
                            }
1138
                        }
1139
                    }
1240
				var bCapture = cacheItem[this.CAPTURE] === true ? true : false;
1140 1241

  
1141
                } else {
1142
                    try {
1143
                        this._simpleRemove(el, sType, cacheItem[this.WFN], false);
1144
                    } catch(ex) {
1145
                        this.lastError = ex;
1146
                        return false;
1147
                    }
1242
                try {
1243
                    this._simpleRemove(el, sType, cacheItem[this.WFN], bCapture);
1244
                } catch(ex) {
1245
                    this.lastError = ex;
1246
                    return false;
1148 1247
                }
1149 1248

  
1150 1249
                // removed the wrapped handler
1151 1250
                delete listeners[index][this.WFN];
1152 1251
                delete listeners[index][this.FN];
1153
                //listeners.splice(index, 1);
1154
                listeners[index]=null;
1252
                listeners.splice(index, 1);
1253
                // listeners[index]=null;
1155 1254

  
1156 1255
                return true;
1157 1256

  
......
1184 1283
             * @return {HTMLElement} the normized node
1185 1284
             * @static
1186 1285
             */
1187
            resolveTextNode: function(node) {
1188
                if (node && 3 == node.nodeType) {
1189
                    return node.parentNode;
1190
                } else {
1191
                    return node;
1192
                }
1286
            resolveTextNode: function(n) {
1287
                try {
1288
                    if (n && 3 == n.nodeType) {
1289
                        return n.parentNode;
1290
                    }
1291
                } catch(e) { }
1292

  
1293
                return n;
1193 1294
            },
1194 1295

  
1195 1296
            /**
......
1351 1452
                    }
1352 1453
                }
1353 1454

  
1354
                // IE events that target non-browser objects (e.g., VML
1355
                // canvas) will sometimes throw errors when you try to
1356
                // inspect the properties of the event target.  We try to
1357
                // detect this condition, and provide a dummy target (the bound
1358
                // element) to eliminate spurious errors.  
1359

  
1360
                // the implementation caused unexpected results in some 
1361
                // implementations, so this has been rolled back for now
1362
                /* 
1363
                if (ev && this.isIE) {
1364

  
1365
                    try {
1366

  
1367
                        var el = ev.srcElement;
1368

  
1369
                    } catch(ex) {
1370

  
1371
                        YAHOO.log("Inspecting the target caused an error, " +
1372
                            "setting the target to the bound element.", "warn");
1373
                         
1374
                        ev.target = boundEl;
1375
                    }
1376

  
1377
                }
1378
                */
1379

  
1380 1455
                return ev;
1381 1456
            },
1382 1457

  
......
1390 1465
            getCharCode: function(ev) {
1391 1466
                var code = ev.keyCode || ev.charCode || 0;
1392 1467

  
1393
                // webkit normalization
1468
                // webkit key normalization
1394 1469
                if (YAHOO.env.ua.webkit && (code in webkitKeymap)) {
1395 1470
                    code = webkitKeymap[code];
1396 1471
                }
......
1404 1479
             * @static
1405 1480
             * @private
1406 1481
             */
1407
            _getCacheIndex: function(el, sType, fn) {
1408
                for (var i=0,len=listeners.length; i<len; ++i) {
1409
                    var li = listeners[i];
1482
            _getCacheIndex: function(a, el, sType, fn) {
1483
                for (var i=0, l=a.length; i<l; i=i+1) {
1484
                    var li = a[i];
1410 1485
                    if ( li                 && 
1411 1486
                         li[this.FN] == fn  && 
1412 1487
                         li[this.EL] == el  && 
......
1460 1535
                             !o.alert              && // o is not a window
1461 1536
                             typeof o[0] !== "undefined" );
1462 1537
                } catch(ex) {
1463
                    YAHOO.log("_isValidCollection error, assuming that " +
1464
                " this is a cross frame problem and not a collection", "warn");
1538
                    YAHOO.log("node access error (xframe?)", "warn");
1465 1539
                    return false;
1466 1540
                }
1467 1541

  
......
1502 1576
             * Custom event the fires when the dom is initially usable
1503 1577
             * @event DOMReadyEvent
1504 1578
             */
1505
            DOMReadyEvent: new YAHOO.util.CustomEvent("DOMReady", this),
1579
            DOMReadyEvent: new YAHOO.util.CustomEvent("DOMReady", YAHOO, 0, 0, 1),
1506 1580

  
1507 1581
            /**
1508 1582
             * hook up any deferred listeners
......
1525 1599
                    // before the window load notification
1526 1600
                    EU._tryPreloadAttach();
1527 1601

  
1528
                    // Remove the listener to assist with the IE memory issue, but not
1529
                    // for other browsers because FF 1.0x does not like it.
1530
                    //if (this.isIE) {
1531
                        //EU._simpleRemove(window, "load", EU._load);
1532
                    //}
1533 1602
                }
1534 1603
            },
1535 1604

  
......
1563 1632
             */
1564 1633
            _tryPreloadAttach: function() {
1565 1634

  
1635
                if (onAvailStack.length === 0) {
1636
                    retryCount = 0;
1637
                    if (this._interval) {
1638
                        // clearInterval(this._interval);
1639
                        this._interval.cancel();
1640
                        this._interval = null;
1641
                    } 
1642
                    return;
1643
                }
1644

  
1566 1645
                if (this.locked) {
1567
                    return false;
1646
                    return;
1568 1647
                }
1569 1648

  
1570 1649
                if (this.isIE) {
1571 1650
                    // Hold off if DOMReady has not fired and check current
1572 1651
                    // readyState to protect against the IE operation aborted
1573 1652
                    // issue.
1574
                    //if (!this.DOMReady || "complete" !== document.readyState) {
1575 1653
                    if (!this.DOMReady) {
1576 1654
                        this.startInterval();
1577
                        return false;
1655
                        return;
1578 1656
                    }
1579 1657
                }
1580 1658

  
......
1588 1666
                // tested appropriately
1589 1667
                var tryAgain = !loadComplete;
1590 1668
                if (!tryAgain) {
1591
                    tryAgain = (retryCount > 0);
1669
                    tryAgain = (retryCount > 0 && onAvailStack.length > 0);
1592 1670
                }
1593 1671

  
1594 1672
                // onAvailable
1595 1673
                var notAvail = [];
1596 1674

  
1597 1675
                var executeItem = function (el, item) {
1598
                    var scope = el;
1599
                    if (item.override) {
1600
                        if (item.override === true) {
1601
                            scope = item.obj;
1676
                    var context = el;
1677
                    if (item.overrideContext) {
1678
                        if (item.overrideContext === true) {
1679
                            context = item.obj;
1602 1680
                        } else {
1603
                            scope = item.override;
1681
                            context = item.overrideContext;
1604 1682
                        }
1605 1683
                    }
1606
                    item.fn.call(scope, item.obj);
1684
                    item.fn.call(context, item.obj);
1607 1685
                };
1608 1686

  
1609
                var i,len,item,el;
1687
                var i, len, item, el, ready=[];
1610 1688

  
1611
                // onAvailable
1612
                for (i=0,len=onAvailStack.length; i<len; ++i) {
1689
                // onAvailable onContentReady
1690
                for (i=0, len=onAvailStack.length; i<len; i=i+1) {
1613 1691
                    item = onAvailStack[i];
1614
                    if (item && !item.checkReady) {
1692
                    if (item) {
1615 1693
                        el = this.getEl(item.id);
1616 1694
                        if (el) {
1617
                            executeItem(el, item);
1618
                            onAvailStack[i] = null;
1619
                        } else {
1620
                            notAvail.push(item);
1621
                        }
1622
                    }
1623
                }
1624

  
1625
                // onContentReady
1626
                for (i=0,len=onAvailStack.length; i<len; ++i) {
1627
                    item = onAvailStack[i];
1628
                    if (item && item.checkReady) {
1629
                        el = this.getEl(item.id);
1630

  
1631
                        if (el) {
1632
                            // The element is available, but not necessarily ready
1633
                            // @todo should we test parentNode.nextSibling?
1634
                            if (loadComplete || el.nextSibling) {
1695
                            if (item.checkReady) {
1696
                                if (loadComplete || el.nextSibling || !tryAgain) {
1697
                                    ready.push(item);
1698
                                    onAvailStack[i] = null;
1699
                                }
1700
                            } else {
1635 1701
                                executeItem(el, item);
1636 1702
                                onAvailStack[i] = null;
1637 1703
                            }
......
1640 1706
                        }
1641 1707
                    }
1642 1708
                }
1709
                
1710
                // make sure onContentReady fires after onAvailable
1711
                for (i=0, len=ready.length; i<len; i=i+1) {
1712
                    item = ready[i];
1713
                    executeItem(this.getEl(item.id), item);
1714
                }
1643 1715

  
1644
                retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
1645 1716

  
1717
                retryCount--;
1718

  
1646 1719
                if (tryAgain) {
1647
                    // we may need to strip the nulled out items here
1720
                    for (i=onAvailStack.length-1; i>-1; i--) {
1721
                        item = onAvailStack[i];
1722
                        if (!item || !item.id) {
1723
                            onAvailStack.splice(i, 1);
1724
                        }
1725
                    }
1726

  
1648 1727
                    this.startInterval();
1649 1728
                } else {
1650
                    clearInterval(this._interval);
1651
                    this._interval = null;
1729
                    if (this._interval) {
1730
                        // clearInterval(this._interval);
1731
                        this._interval.cancel();
1732
                        this._interval = null;
1733
                    }
1652 1734
                }
1653 1735

  
1654 1736
                this.locked = false;
1655 1737

  
1656
                return true;
1657

  
1658 1738
            },
1659 1739

  
1660 1740
            /**
......
1673 1753
                var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el;
1674 1754
                var elListeners = this.getListeners(oEl, sType), i, len;
1675 1755
                if (elListeners) {
1676
                    for (i=0,len=elListeners.length; i<len ; ++i) {
1756
                    for (i=elListeners.length-1; i>-1; i--) {
1677 1757
                        var l = elListeners[i];
1678
                        // can't use the index on the changing collection
1679
                        this.removeListener(oEl, l.type, l.fn, l.index);
1680
                        //this.removeListener(oEl, l.type, l.fn);
1758
                        this.removeListener(oEl, l.type, l.fn);
1681 1759
                    }
1682 1760
                }
1683 1761

  
......
1699 1777
             * &nbsp;&nbsp;type:   (string)   the type of event
1700 1778
             * &nbsp;&nbsp;fn:     (function) the callback supplied to addListener
1701 1779
             * &nbsp;&nbsp;obj:    (object)   the custom object supplied to addListener
1702
             * &nbsp;&nbsp;adjust: (boolean|object)  whether or not to adjust the default scope
1703
             * &nbsp;&nbsp;scope: (boolean)  the derived scope based on the adjust parameter
1780
             * &nbsp;&nbsp;adjust: (boolean|object)  whether or not to adjust the default context
1781
             * &nbsp;&nbsp;scope: (boolean)  the derived context based on the adjust parameter
1704 1782
             * &nbsp;&nbsp;index:  (int)      its position in the Event util listener cache
1705 1783
             * @static
1706 1784
             */           
......
1711 1789
                } else if (sType === "unload") {
1712 1790
                    searchLists = [unloadListeners];
1713 1791
                } else {
1792
					sType = this._getType(sType);
1714 1793
                    searchLists = [listeners];
1715 1794
                }
1716 1795

  
......
1718 1797

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff