Fixed the document.ready addEventListener issue.
[jquery.git] / event / event.js
1 // We're overriding the old toggle function, so
2 // remember it for later
3 jQuery.prototype._toggle = jQuery.prototype.toggle;
4
5 /**
6  * Toggle between two function calls every other click.
7  */
8 jQuery.prototype.toggle = function(a,b) {
9         // If two functions are passed in, we're
10         // toggling on a click
11         return a && b ? this.click(function(e){
12                 // Figure out which function to execute
13                 this.last = this.last == a ? b : a;
14                 
15                 // Make sure that clicks stop
16                 e.preventDefault();
17                 
18                 // and execute the function
19                 return this.last.apply( this, [e] ) || false;
20         }) :
21         
22         // Otherwise, execute the old toggle function
23         this._toggle();
24 };
25
26 /**
27  * Toggle between two function calls on mouse over/out.
28  */
29 jQuery.prototype.hover = function(f,g) {
30         
31         // A private function for haandling mouse 'hovering'
32         function handleHover(e) {
33                 // Check if mouse(over|out) are still within the same parent element
34                 var p = e.fromElement || e.toElement || e.relatedTarget;
35                 while ( p && p != this ) p = p.parentNode;
36                 
37                 // If we actually just moused on to a sub-element, ignore it
38                 if ( p == this ) return false;
39                 
40                 // Execute the right function
41                 return (e.type == "mouseover" ? f : g).apply(this, [e]);
42         }
43         
44         // Bind the function to the two event listeners
45         return this.mouseover(handleHover).mouseout(handleHover);
46 };
47
48 /**
49  * Bind a function to fire when the DOM is ready.
50  */
51 jQuery.prototype.ready = function(f) {
52         // If the DOM is already ready
53         if ( jQuery.isReady )
54                 // Execute the function immediately
55                 f.apply( document );
56                 
57         // Otherwise, remember the function for later
58         else {
59                 // Add the function to the wait list
60                 jQuery.readyList.push( f );
61         }
62
63         return this;
64 };
65
66 (function(){
67         /*
68          * Bind a number of event-handling functions, dynamically
69          */
70         var e = ("blur,focus,contextmenu,load,resize,scroll,unload,click,dblclick," +
71                 "mousedown,mouseup,mouseenter,mouseleave,mousemove,mouseover,mouseout," +
72                 "change,reset,select,submit,keydown,keypress,keyup").split(",");
73
74         // Go through all the event names, but make sure that
75         // it is enclosed properly
76         for ( var i = 0; i < e.length; i++ ) {(function(){
77                         
78                 var o = e[i];
79                 
80                 // Handle event binding
81                 jQuery.prototype[o] = function(f){ return this.bind(o, f); };
82                 
83                 // Handle event unbinding
84                 jQuery.prototype["un"+o] = function(f){ return this.unbind(o, f); };
85                 
86                 // Handle event triggering
87                 jQuery.prototype["do"+o] = function(){ return this.trigger(o); };
88                 
89                 // Finally, handle events that only fire once
90                 jQuery.prototype["one"+o] = function(f){
91                         // Attach the event listener
92                         return this.bind(o, function(e){
93                                 // TODO: Remove the event listener, instead of this hack
94                                 
95                                 // If this function has already been executed, stop
96                                 if ( this[o+f] !== null )
97                                         return true;
98                                 
99                                 // Otherwise, mark as having been executed
100                                 this[o+f]++;
101                                 
102                                 // And execute the bound function
103                                 return f.apply(this, [e]);
104                         });
105                 };
106                         
107         })();}
108                 
109         /*
110          * All the code that makes DOM Ready work nicely.
111          */
112          
113         jQuery.isReady = false;
114         jQuery.readyList = [];
115         
116         // Handle when the DOM is ready
117         jQuery.ready = function() {
118                 // Make sure that the DOM is not already loaded
119                 if ( !jQuery.isReady ) {
120                         // Remember that the DOM is ready
121                         jQuery.isReady = true;
122                         
123                         // If there are functions bound, to execute
124                         if ( jQuery.readyList ) {
125                                 // Execute all of them
126                                 for ( var i = 0; i < jQuery.readyList.length; i++ )
127                                         jQuery.readyList[i].apply( document );
128                                 
129                                 // Reset the list of functions
130                                 jQuery.readyList = null;
131                         }
132                 }
133         };
134         
135         // If Mozilla is used
136         if ( jQuery.browser == "mozilla" || jQuery.browser == "opera" ) {
137                 // Use the handy event callback
138                 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
139         
140         // If IE is used, use the excellent hack by Matthias Miller
141         // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
142         } else if ( jQuery.browser == "msie" ) {
143         
144                 // Only works if you document.write() it
145                 document.write("<scr" + "ipt id=__ie_init defer=true " + 
146                         "src=https:///><\/script>");
147         
148                 // Use the defer script hack
149                 var script = document.getElementById("__ie_init");
150                 script.onreadystatechange = function() {
151                         if ( this.readyState == "complete" )
152                                 jQuery.ready();
153                 };
154         
155                 // Clear from memory
156                 script = null;
157         
158         // If Safari  is used
159         } else if ( jQuery.browser == "safari" ) {
160                 // Continually check to see if the document.readyState is valid
161                 jQuery.safariTimer = setInterval(function(){
162                         // loaded and complete are both valid states
163                         if ( document.readyState == "loaded" || 
164                                 document.readyState == "complete" ) {
165         
166                                 // If either one are found, remove the timer
167                                 clearInterval( jQuery.safariTimer );
168                                 jQuery.safariTimer = null;
169         
170                                 // and execute any waiting functions
171                                 jQuery.ready();
172                         }
173                 }, 10);
174         }
175         
176         // A fallback to window.onload, that will always work
177         jQuery.event.add( window, "load", jQuery.ready );
178         
179 })();