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