VirtualBox

source: vbox/trunk/src/libs/dita-ot-1.8.5/doc/event.js@ 99005

Last change on this file since 99005 was 98584, checked in by vboxsync, 2 years ago

Docs: bugref:10302. Setting svn properties of DITA-OT library.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.1 KB
Line 
1/*
2This file is part of the DITA Open Toolkit project hosted on
3Sourceforge.net. See the accompanying license.txt file for
4applicable licenses.
5
6Copyright (c) 2006, Yahoo! Inc. All rights reserved.
7Code licensed under the BSD License:
8http://developer.yahoo.net/yui/license.txt
9version: 0.10.0
10*/
11
12/**
13 * The CustomEvent class lets you define events for your application
14 * that can be subscribed to by one or more independent component.
15 *
16 * @param {String} type The type of event, which is passed to the callback
17 * when the event fires
18 * @param {Object} oScope The context the event will fire from. "this" will
19 * refer to this object in the callback. Default value:
20 * the window object. The listener can override this.
21 * @constructor
22 */
23YAHOO.util.CustomEvent = function(type, oScope) {
24 /**
25 * The type of event, returned to subscribers when the event fires
26 * @type string
27 */
28 this.type = type;
29
30 /**
31 * The scope the the event will fire from by default. Defaults to the window
32 * obj
33 * @type object
34 */
35 this.scope = oScope || window;
36
37 /**
38 * The subscribers to this event
39 * @type Subscriber[]
40 */
41 this.subscribers = [];
42
43 // Register with the event utility for automatic cleanup. Made optional
44 // so that CustomEvent can be used independently of pe.event
45 if (YAHOO.util.Event) {
46 YAHOO.util.Event.regCE(this);
47 }
48};
49
50YAHOO.util.CustomEvent.prototype = {
51 /**
52 * Subscribes the caller to this event
53 * @param {Function} fn The function to execute
54 * @param {Object} obj An object to be passed along when the event fires
55 * @param {boolean} bOverride If true, the obj passed in becomes the execution
56 * scope of the listener
57 */
58 subscribe: function(fn, obj, bOverride) {
59 this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );
60 },
61
62 /**
63 * Unsubscribes the caller from this event
64 * @param {Function} fn The function to execute
65 * @param {Object} obj An object to be passed along when the event fires
66 * @return {boolean} True if the subscriber was found and detached.
67 */
68 unsubscribe: function(fn, obj) {
69 var found = false;
70 for (var i=0, len=this.subscribers.length; i<len; ++i) {
71 var s = this.subscribers[i];
72 if (s && s.contains(fn, obj)) {
73 this._delete(i);
74 found = true;
75 }
76 }
77
78 return found;
79 },
80
81 /**
82 * Notifies the subscribers. The callback functions will be executed
83 * from the scope specified when the event was created, and with the following
84 * parameters:
85 * <pre>
86 * - The type of event
87 * - All of the arguments fire() was executed with as an array
88 * - The custom object (if any) that was passed into the subscribe() method
89 * </pre>
90 *
91 * @param {Array} an arbitrary set of parameters to pass to the handler
92 */
93 fire: function() {
94 for (var i=0, len=this.subscribers.length; i<len; ++i) {
95 var s = this.subscribers[i];
96 if (s) {
97 var scope = (s.override) ? s.obj : this.scope;
98 s.fn.call(scope, this.type, arguments, s.obj);
99 }
100 }
101 },
102
103 /**
104 * Removes all listeners
105 */
106 unsubscribeAll: function() {
107 for (var i=0, len=this.subscribers.length; i<len; ++i) {
108 this._delete(i);
109 }
110 },
111
112 /**
113 * @private
114 */
115 _delete: function(index) {
116 var s = this.subscribers[index];
117 if (s) {
118 delete s.fn;
119 delete s.obj;
120 }
121
122 delete this.subscribers[index];
123 }
124};
125
126/////////////////////////////////////////////////////////////////////
127
128/**
129 * @class Stores the subscriber information to be used when the event fires.
130 * @param {Function} fn The function to execute
131 * @param {Object} obj An object to be passed along when the event fires
132 * @param {boolean} bOverride If true, the obj passed in becomes the execution
133 * scope of the listener
134 * @constructor
135 */
136YAHOO.util.Subscriber = function(fn, obj, bOverride) {
137 /**
138 * The callback that will be execute when the event fires
139 * @type function
140 */
141 this.fn = fn;
142
143 /**
144 * An optional custom object that will passed to the callback when
145 * the event fires
146 * @type object
147 */
148 this.obj = obj || null;
149
150 /**
151 * The default execution scope for the event listener is defined when the
152 * event is created (usually the object which contains the event).
153 * By setting override to true, the execution scope becomes the custom
154 * object passed in by the subscriber
155 * @type boolean
156 */
157 this.override = (bOverride);
158};
159
160/**
161 * Returns true if the fn and obj match this objects properties.
162 * Used by the unsubscribe method to match the right subscriber.
163 *
164 * @param {Function} fn the function to execute
165 * @param {Object} obj an object to be passed along when the event fires
166 * @return {boolean} true if the supplied arguments match this
167 * subscriber's signature.
168 */
169YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
170 return (this.fn == fn && this.obj == obj);
171};
172
173/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
174
175// Only load this library once. If it is loaded a second time, existing
176// events cannot be detached.
177if (!YAHOO.util.Event) {
178
179/**
180 * @class
181 * The event utility provides functions to add and remove event listeners,
182 * event cleansing. It also tries to automatically remove listeners it
183 * registers during the unload event.
184 * @constructor
185 */
186 YAHOO.util.Event = function() {
187
188 /**
189 * True after the onload event has fired
190 * @type boolean
191 * @private
192 */
193 var loadComplete = false;
194
195 /**
196 * Cache of wrapped listeners
197 * @type array
198 * @private
199 */
200 var listeners = [];
201
202 /**
203 * Listeners that will be attached during the onload event
204 * @type array
205 * @private
206 */
207 var delayedListeners = [];
208
209 /**
210 * User-defined unload function that will be fired before all events
211 * are detached
212 * @type array
213 * @private
214 */
215 var unloadListeners = [];
216
217 /**
218 * Cache of the custom events that have been defined. Used for
219 * automatic cleanup
220 * @type array
221 * @private
222 */
223 var customEvents = [];
224
225 /**
226 * Cache of DOM0 event handlers to work around issues with DOM2 events
227 * in Safari
228 * @private
229 */
230 var legacyEvents = [];
231
232 /**
233 * Listener stack for DOM0 events
234 * @private
235 */
236 var legacyHandlers = [];
237
238 /**
239 * The number of times to poll after window.onload. This number is
240 * increased if additional late-bound handlers are requested after
241 * the page load.
242 * @private
243 */
244 var retryCount = 0;
245
246 /**
247 * onAvailable listeners
248 * @private
249 */
250 var onAvailStack = [];
251
252 /**
253 * Lookup table for legacy events
254 * @private
255 */
256 var legacyMap = [];
257
258 /**
259 * Counter for auto id generation
260 * @private
261 */
262 var counter = 0;
263
264 return { // PREPROCESS
265
266 /**
267 * The number of times we should look for elements that are not
268 * in the DOM at the time the event is requested after the document
269 * has been loaded. The default is 200@50 ms, so it will poll
270 * for 10 seconds or until all outstanding handlers are bound
271 * (whichever comes first).
272 * @type int
273 */
274 POLL_RETRYS: 200,
275
276 /**
277 * The poll interval in milliseconds
278 * @type int
279 */
280 POLL_INTERVAL: 50,
281
282 /**
283 * Element to bind, int constant
284 * @type int
285 */
286 EL: 0,
287
288 /**
289 * Type of event, int constant
290 * @type int
291 */
292 TYPE: 1,
293
294 /**
295 * Function to execute, int constant
296 * @type int
297 */
298 FN: 2,
299
300 /**
301 * Function wrapped for scope correction and cleanup, int constant
302 * @type int
303 */
304 WFN: 3,
305
306 /**
307 * Object passed in by the user that will be returned as a
308 * parameter to the callback, int constant
309 * @type int
310 */
311 SCOPE: 3,
312
313 /**
314 * Adjusted scope, either the element we are registering the event
315 * on or the custom object passed in by the listener, int constant
316 * @type int
317 */
318 ADJ_SCOPE: 4,
319
320 /**
321 * Safari detection is necessary to work around the preventDefault
322 * bug that makes it so you can't cancel a href click from the
323 * handler. There is not a capabilities check we can use here.
324 * @private
325 */
326 isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),
327
328 /**
329 * IE detection needed to properly calculate pageX and pageY.
330 * capabilities checking didn't seem to work because another
331 * browser that does not provide the properties have the values
332 * calculated in a different manner than IE.
333 * @private
334 */
335 isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) &&
336 navigator.userAgent.match(/msie/gi)),
337
338 /**
339 * @private
340 */
341 addDelayedListener: function(el, sType, fn, oScope, bOverride) {
342 delayedListeners[delayedListeners.length] =
343 [el, sType, fn, oScope, bOverride];
344
345 // If this happens after the inital page load, we need to
346 // reset the poll counter so that we continue to search for
347 // the element for a fixed period of time.
348 if (loadComplete) {
349 retryCount = this.POLL_RETRYS;
350 this.startTimeout(0);
351 // this._tryPreloadAttach();
352 }
353 },
354
355 /**
356 * @private
357 */
358 startTimeout: function(interval) {
359 var i = (interval || interval === 0) ? interval : this.POLL_INTERVAL;
360 var self = this;
361 var callback = function() { self._tryPreloadAttach(); };
362 this.timeout = setTimeout(callback, i);
363 },
364
365 /**
366 * Executes the supplied callback when the item with the supplied
367 * id is found. This is meant to be used to execute behavior as
368 * soon as possible as the page loads. If you use this after the
369 * initial page load it will poll for a fixed time for the element.
370 * The number of times it will poll and the frequency are
371 * configurable. By default it will poll for 10 seconds.
372 * @param {string} p_id the id of the element to look for.
373 * @param {function} p_fn what to execute when the element is found.
374 * @param {object} p_obj an optional object to be passed back as
375 * a parameter to p_fn.
376 * @param {boolean} p_override If set to true, p_fn will execute
377 * in the scope of p_obj
378 *
379 */
380 onAvailable: function(p_id, p_fn, p_obj, p_override) {
381 onAvailStack.push( { id: p_id,
382 fn: p_fn,
383 obj: p_obj,
384 override: p_override } );
385
386 retryCount = this.POLL_RETRYS;
387 this.startTimeout(0);
388 // this._tryPreloadAttach();
389 },
390
391 /**
392 * Appends an event handler
393 *
394 * @param {Object} el The html element to assign the
395 * event to
396 * @param {String} sType The type of event to append
397 * @param {Function} fn The method the event invokes
398 * @param {Object} oScope An arbitrary object that will be
399 * passed as a parameter to the handler
400 * @param {boolean} bOverride If true, the obj passed in becomes
401 * the execution scope of the listener
402 * @return {boolean} True if the action was successful or defered,
403 * false if one or more of the elements
404 * could not have the event bound to it.
405 */
406 addListener: function(el, sType, fn, oScope, bOverride) {
407
408 if (!fn || !fn.call) {
409 return false;
410 }
411
412 // The el argument can be an array of elements or element ids.
413 if ( this._isValidCollection(el)) {
414 var ok = true;
415 for (var i=0,len=el.length; i<len; ++i) {
416 ok = ( this.on(el[i],
417 sType,
418 fn,
419 oScope,
420 bOverride) && ok );
421 }
422 return ok;
423
424 } else if (typeof el == "string") {
425 var oEl = this.getEl(el);
426 // If the el argument is a string, we assume it is
427 // actually the id of the element. If the page is loaded
428 // we convert el to the actual element, otherwise we
429 // defer attaching the event until onload event fires
430
431 // check to see if we need to delay hooking up the event
432 // until after the page loads.
433 if (loadComplete && oEl) {
434 el = oEl;
435 } else {
436 // defer adding the event until onload fires
437 this.addDelayedListener(el,
438 sType,
439 fn,
440 oScope,
441 bOverride);
442
443 return true;
444 }
445 }
446
447 // Element should be an html element or an array if we get
448 // here.
449 if (!el) {
450 return false;
451 }
452
453 // we need to make sure we fire registered unload events
454 // prior to automatically unhooking them. So we hang on to
455 // these instead of attaching them to the window and fire the
456 // handles explicitly during our one unload event.
457 if ("unload" == sType && oScope !== this) {
458 unloadListeners[unloadListeners.length] =
459 [el, sType, fn, oScope, bOverride];
460 return true;
461 }
462
463
464 // if the user chooses to override the scope, we use the custom
465 // object passed in, otherwise the executing scope will be the
466 // HTML element that the event is registered on
467 var scope = (bOverride) ? oScope : el;
468
469 // wrap the function so we can return the oScope object when
470 // the event fires;
471 var wrappedFn = function(e) {
472 return fn.call(scope, YAHOO.util.Event.getEvent(e),
473 oScope);
474 };
475
476 var li = [el, sType, fn, wrappedFn, scope];
477 var index = listeners.length;
478 // cache the listener so we can try to automatically unload
479 listeners[index] = li;
480
481 if (this.useLegacyEvent(el, sType)) {
482 var legacyIndex = this.getLegacyIndex(el, sType);
483 if (legacyIndex == -1) {
484
485 legacyIndex = legacyEvents.length;
486 legacyMap[el.id + sType] = legacyIndex;
487
488 // cache the signature for the DOM0 event, and
489 // include the existing handler for the event, if any
490 legacyEvents[legacyIndex] =
491 [el, sType, el["on" + sType]];
492 legacyHandlers[legacyIndex] = [];
493
494 el["on" + sType] =
495 function(e) {
496 YAHOO.util.Event.fireLegacyEvent(
497 YAHOO.util.Event.getEvent(e), legacyIndex);
498 };
499 }
500
501 // add a reference to the wrapped listener to our custom
502 // stack of events
503 legacyHandlers[legacyIndex].push(index);
504
505 // DOM2 Event model
506 } else if (el.addEventListener) {
507 el.addEventListener(sType, wrappedFn, false);
508 // Internet Explorer abstraction
509 } else if (el.attachEvent) {
510 el.attachEvent("on" + sType, wrappedFn);
511 }
512
513 return true;
514
515 },
516
517 /**
518 * Shorthand for YAHOO.util.Event.addListener
519 * @type function
520 */
521 // on: this.addListener,
522
523 /**
524 * When using legacy events, the handler is routed to this object
525 * so we can fire our custom listener stack.
526 * @private
527 */
528 fireLegacyEvent: function(e, legacyIndex) {
529 var ok = true;
530
531 var le = legacyHandlers[legacyIndex];
532 for (var i=0,len=le.length; i<len; ++i) {
533 var index = le[i];
534 if (index) {
535 var li = listeners[index];
536 if ( li && li[this.WFN] ) {
537 var scope = li[this.ADJ_SCOPE];
538 var ret = li[this.WFN].call(scope, e);
539 ok = (ok && ret);
540 } else {
541 // This listener was removed, so delete it from
542 // the array
543 delete le[i];
544 }
545 }
546 }
547
548 return ok;
549 },
550
551 /**
552 * Returns the legacy event index that matches the supplied
553 * signature
554 * @private
555 */
556 getLegacyIndex: function(el, sType) {
557 /*
558 for (var i=0,len=legacyEvents.length; i<len; ++i) {
559 var le = legacyEvents[i];
560 if (le && le[0] === el && le[1] === sType) {
561 return i;
562 }
563 }
564 return -1;
565 */
566
567 var key = this.generateId(el) + sType;
568 if (typeof legacyMap[key] == "undefined") {
569 return -1;
570 } else {
571 return legacyMap[key];
572 }
573
574 },
575
576 /**
577 * Logic that determines when we should automatically use legacy
578 * events instead of DOM2 events.
579 * @private
580 */
581 useLegacyEvent: function(el, sType) {
582
583 if (!el.addEventListener && !el.attachEvent) {
584 return true;
585 } else if (this.isSafari) {
586 if ("click" == sType || "dblclick" == sType) {
587 return true;
588 }
589 }
590
591 return false;
592 },
593
594 /**
595 * Removes an event handler
596 *
597 * @param {Object} el the html element or the id of the element to
598 * assign the event to.
599 * @param {String} sType the type of event to remove
600 * @param {Function} fn the method the event invokes
601 * @return {boolean} true if the unbind was successful, false
602 * otherwise
603 */
604 removeListener: function(el, sType, fn, index) {
605
606 if (!fn || !fn.call) {
607 return false;
608 }
609
610 // The el argument can be a string
611 if (typeof el == "string") {
612 el = this.getEl(el);
613 // The el argument can be an array of elements or element ids.
614 } else if ( this._isValidCollection(el)) {
615 var ok = true;
616 for (var i=0,len=el.length; i<len; ++i) {
617 ok = ( this.removeListener(el[i], sType, fn) && ok );
618 }
619 return ok;
620 }
621
622 if ("unload" == sType) {
623
624 for (i=0, len=unloadListeners.length; i<len; i++) {
625 var li = unloadListeners[i];
626 if (li &&
627 li[0] == el &&
628 li[1] == sType &&
629 li[2] == fn) {
630 delete unloadListeners[i];
631 return true;
632 }
633 }
634
635 return false;
636 }
637
638 var cacheItem = null;
639
640 if ("undefined" == typeof index) {
641 index = this._getCacheIndex(el, sType, fn);
642 }
643
644 if (index >= 0) {
645 cacheItem = listeners[index];
646 }
647
648 if (!el || !cacheItem) {
649 return false;
650 }
651
652
653 if (el.removeEventListener) {
654 el.removeEventListener(sType, cacheItem[this.WFN], false);
655 } else if (el.detachEvent) {
656 el.detachEvent("on" + sType, cacheItem[this.WFN]);
657 }
658
659 // removed the wrapped handler
660 delete listeners[index][this.WFN];
661 delete listeners[index][this.FN];
662 delete listeners[index];
663
664 return true;
665
666 },
667
668 /**
669 * Returns the event's target element
670 * @param {Event} ev the event
671 * @param {boolean} resolveTextNode when set to true the target's
672 * parent will be returned if the target is a
673 * text node
674 * @return {HTMLElement} the event's target
675 */
676 getTarget: function(ev, resolveTextNode) {
677 var t = ev.target || ev.srcElement;
678
679 if (resolveTextNode && t && "#text" == t.nodeName) {
680 return t.parentNode;
681 } else {
682 return t;
683 }
684 },
685
686 /**
687 * Returns the event's pageX
688 * @param {Event} ev the event
689 * @return {int} the event's pageX
690 */
691 getPageX: function(ev) {
692 var x = ev.pageX;
693 if (!x && 0 !== x) {
694 x = ev.clientX || 0;
695
696 if ( this.isIE ) {
697 x += this._getScrollLeft();
698 }
699 }
700
701 return x;
702 },
703
704 /**
705 * Returns the event's pageY
706 * @param {Event} ev the event
707 * @return {int} the event's pageY
708 */
709 getPageY: function(ev) {
710 var y = ev.pageY;
711 if (!y && 0 !== y) {
712 y = ev.clientY || 0;
713
714 if ( this.isIE ) {
715 y += this._getScrollTop();
716 }
717 }
718
719 return y;
720 },
721
722 /**
723 * Returns the pageX and pageY properties as an indexed array.
724 * @type int[]
725 */
726 getXY: function(ev) {
727 return [this.getPageX(ev), this.getPageY(ev)];
728 },
729
730 /**
731 * Returns the event's related target
732 * @param {Event} ev the event
733 * @return {HTMLElement} the event's relatedTarget
734 */
735 getRelatedTarget: function(ev) {
736 var t = ev.relatedTarget;
737 if (!t) {
738 if (ev.type == "mouseout") {
739 t = ev.toElement;
740 } else if (ev.type == "mouseover") {
741 t = ev.fromElement;
742 }
743 }
744
745 return t;
746 },
747
748 /**
749 * Returns the time of the event. If the time is not included, the
750 * event is modified using the current time.
751 * @param {Event} ev the event
752 * @return {Date} the time of the event
753 */
754 getTime: function(ev) {
755 if (!ev.time) {
756 var t = new Date().getTime();
757 try {
758 ev.time = t;
759 } catch(e) {
760 // can't set the time property
761 return t;
762 }
763 }
764
765 return ev.time;
766 },
767
768 /**
769 * Convenience method for stopPropagation + preventDefault
770 * @param {Event} ev the event
771 */
772 stopEvent: function(ev) {
773 this.stopPropagation(ev);
774 this.preventDefault(ev);
775 },
776
777 /**
778 * Stops event propagation
779 * @param {Event} ev the event
780 */
781 stopPropagation: function(ev) {
782 if (ev.stopPropagation) {
783 ev.stopPropagation();
784 } else {
785 ev.cancelBubble = true;
786 }
787 },
788
789 /**
790 * Prevents the default behavior of the event
791 * @param {Event} ev the event
792 */
793 preventDefault: function(ev) {
794 if (ev.preventDefault) {
795 ev.preventDefault();
796 } else {
797 ev.returnValue = false;
798 }
799 },
800
801 /**
802 * Finds the event in the window object, the caller's arguments, or
803 * in the arguments of another method in the callstack. This is
804 * executed automatically for events registered through the event
805 * manager, so the implementer should not normally need to execute
806 * this function at all.
807 * @param {Event} the event parameter from the handler
808 * @return {Event} the event
809 */
810 getEvent: function(e) {
811 var ev = e || window.event;
812
813 if (!ev) {
814 var c = this.getEvent.caller;
815 while (c) {
816 ev = c.arguments[0];
817 if (ev && Event == ev.constructor) {
818 break;
819 }
820 c = c.caller;
821 }
822 }
823
824 return ev;
825 },
826
827 /**
828 * Returns the charcode for an event
829 * @param {Event} ev the event
830 * @return {int} the event's charCode
831 */
832 getCharCode: function(ev) {
833 return ev.charCode || ((ev.type == "keypress") ? ev.keyCode : 0);
834 },
835
836 /**
837 * @private
838 * Locating the saved event handler data by function ref
839 */
840 _getCacheIndex: function(el, sType, fn) {
841 for (var i=0,len=listeners.length; i<len; ++i) {
842 var li = listeners[i];
843 if ( li &&
844 li[this.FN] == fn &&
845 li[this.EL] == el &&
846 li[this.TYPE] == sType ) {
847 return i;
848 }
849 }
850
851 return -1;
852 },
853
854 /**
855 * Generates an unique ID for the element if it does not already
856 * have one.
857 * @param el the element
858 * @return {string} the id of the element
859 */
860 generateId: function(el) {
861 var id = el.id;
862
863 if (!id) {
864 id = "yuievtautoid-" + (counter++);
865 el.id = id;
866 }
867
868 return id;
869 },
870
871 /**
872 * We want to be able to use getElementsByTagName as a collection
873 * to attach a group of events to. Unfortunately, different
874 * browsers return different types of collections. This function
875 * tests to determine if the object is array-like. It will also
876 * fail if the object is an array, but is empty.
877 * @param o the object to test
878 * @return {boolean} true if the object is array-like and populated
879 * @private
880 */
881 _isValidCollection: function(o) {
882
883 return ( o && // o is something
884 o.length && // o is indexed
885 typeof o != "string" && // o is not a string
886 !o.tagName && // o is not an HTML element
887 !o.alert && // o is not a window
888 typeof o[0] != "undefined" );
889
890 },
891
892 /**
893 * @private
894 * DOM element cache
895 */
896 elCache: {},
897
898 /**
899 * We cache elements bound by id because when the unload event
900 * fires, we can no longer use document.getElementById
901 * @private
902 */
903 getEl: function(id) {
904 return document.getElementById(id);
905 },
906
907 /**
908 * Clears the element cache
909 * @deprecated
910 * @private
911 */
912 clearCache: function() { },
913
914 /**
915 * Called by CustomEvent instances to provide a handle to the
916 * event * that can be removed later on. Should be package
917 * protected.
918 * @private
919 */
920 regCE: function(ce) {
921 customEvents.push(ce);
922 },
923
924 /**
925 * @private
926 * hook up any deferred listeners
927 */
928 _load: function(e) {
929 loadComplete = true;
930 },
931
932 /**
933 * Polling function that runs before the onload event fires,
934 * attempting * to attach to DOM Nodes as soon as they are
935 * available
936 * @private
937 */
938 _tryPreloadAttach: function() {
939
940 if (this.locked) {
941 return false;
942 }
943
944 this.locked = true;
945
946
947 // keep trying until after the page is loaded. We need to
948 // check the page load state prior to trying to bind the
949 // elements so that we can be certain all elements have been
950 // tested appropriately
951 var tryAgain = !loadComplete;
952 if (!tryAgain) {
953 tryAgain = (retryCount > 0);
954 }
955
956 // Delayed listeners
957 var stillDelayed = [];
958
959 for (var i=0,len=delayedListeners.length; i<len; ++i) {
960 var d = delayedListeners[i];
961 // There may be a race condition here, so we need to
962 // verify the array element is usable.
963 if (d) {
964
965 // el will be null if document.getElementById did not
966 // work
967 var el = this.getEl(d[this.EL]);
968
969 if (el) {
970 this.on(el, d[this.TYPE], d[this.FN],
971 d[this.SCOPE], d[this.ADJ_SCOPE]);
972 delete delayedListeners[i];
973 } else {
974 stillDelayed.push(d);
975 }
976 }
977 }
978
979 delayedListeners = stillDelayed;
980
981 // onAvailable
982 notAvail = [];
983 for (i=0,len=onAvailStack.length; i<len ; ++i) {
984 var item = onAvailStack[i];
985 if (item) {
986 el = this.getEl(item.id);
987
988 if (el) {
989 var scope = (item.override) ? item.obj : el;
990 item.fn.call(scope, item.obj);
991 delete onAvailStack[i];
992 } else {
993 notAvail.push(item);
994 }
995 }
996 }
997
998 retryCount = (stillDelayed.length === 0 &&
999 notAvail.length === 0) ? 0 : retryCount - 1;
1000
1001 if (tryAgain) {
1002 this.startTimeout();
1003 }
1004
1005 this.locked = false;
1006
1007 },
1008
1009 /**
1010 * Removes all listeners registered by pe.event. Called
1011 * automatically during the unload event.
1012 * @private
1013 */
1014 _unload: function(e, me) {
1015 for (var i=0,len=unloadListeners.length; i<len; ++i) {
1016 var l = unloadListeners[i];
1017 if (l) {
1018 var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window;
1019 l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] );
1020 }
1021 }
1022
1023 if (listeners && listeners.length > 0) {
1024 for (i=0,len=listeners.length; i<len ; ++i) {
1025 l = listeners[i];
1026 if (l) {
1027 this.removeListener(l[this.EL], l[this.TYPE],
1028 l[this.FN], i);
1029 }
1030 }
1031
1032 this.clearCache();
1033 }
1034
1035 for (i=0,len=customEvents.length; i<len; ++i) {
1036 customEvents[i].unsubscribeAll();
1037 delete customEvents[i];
1038 }
1039
1040 for (i=0,len=legacyEvents.length; i<len; ++i) {
1041 // dereference the element
1042 delete legacyEvents[i][0];
1043 // delete the array item
1044 delete legacyEvents[i];
1045 }
1046 },
1047
1048 /**
1049 * Returns scrollLeft
1050 * @private
1051 */
1052 _getScrollLeft: function() {
1053 return this._getScroll()[1];
1054 },
1055
1056 /**
1057 * Returns scrollTop
1058 * @private
1059 */
1060 _getScrollTop: function() {
1061 return this._getScroll()[0];
1062 },
1063
1064 /**
1065 * Returns the scrollTop and scrollLeft. Used to calculate the
1066 * pageX and pageY in Internet Explorer
1067 * @private
1068 */
1069 _getScroll: function() {
1070 var dd = document.documentElement; db = document.body;
1071 if (dd && dd.scrollTop) {
1072 return [dd.scrollTop, dd.scrollLeft];
1073 } else if (db) {
1074 return [db.scrollTop, db.scrollLeft];
1075 } else {
1076 return [0, 0];
1077 }
1078 }
1079 };
1080 } ();
1081
1082 /**
1083 * @private
1084 */
1085 YAHOO.util.Event.on = YAHOO.util.Event.addListener;
1086
1087 if (document && document.body) {
1088 YAHOO.util.Event._load();
1089 } else {
1090 YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load,
1091 YAHOO.util.Event, true);
1092 }
1093
1094 YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload,
1095 YAHOO.util.Event, true);
1096
1097 YAHOO.util.Event._tryPreloadAttach();
1098
1099}
1100
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette