Fix for #849
[jquery.git] / src / event / event.js
1 /*
2  * A number of helper functions used for managing events.
3  * Many of the ideas behind this code orignated from 
4  * Dean Edwards' addEvent library.
5  */
6 jQuery.event = {
7
8         // Bind an event to an element
9         // Original by Dean Edwards
10         add: function(element, type, handler, data) {
11                 // For whatever reason, IE has trouble passing the window object
12                 // around, causing it to be cloned in the process
13                 if ( jQuery.browser.msie && element.setInterval != undefined )
14                         element = window;
15
16                 // if data is passed, bind to handler
17                 if( data ) 
18                         handler.data = data;
19
20                 // Make sure that the function being executed has a unique ID
21                 if ( !handler.guid )
22                         handler.guid = this.guid++;
23
24                 // Init the element's event structure
25                 if (!element.events)
26                         element.events = {};
27
28                 // Get the current list of functions bound to this event
29                 var handlers = element.events[type];
30
31                 // If it hasn't been initialized yet
32                 if (!handlers) {
33                         // Init the event handler queue
34                         handlers = element.events[type] = {};
35
36                         // Remember an existing handler, if it's already there
37                         if (element["on" + type])
38                                 handlers[0] = element["on" + type];
39                 }
40
41                 // Add the function to the element's handler list
42                 handlers[handler.guid] = handler;
43
44                 // And bind the global event handler to the element
45                 element["on" + type] = this.handle;
46
47                 // Remember the function in a global list (for triggering)
48                 if (!this.global[type])
49                         this.global[type] = [];
50                 this.global[type].push( element );
51         },
52
53         guid: 1,
54         global: {},
55
56         // Detach an event or set of events from an element
57         remove: function(element, type, handler) {
58                 if (element.events)
59                         if ( type && type.type )
60                                 delete element.events[ type.type ][ type.handler.guid ];
61                         else if (type && element.events[type])
62                                 if ( handler )
63                                         delete element.events[type][handler.guid];
64                                 else
65                                         for ( var i in element.events[type] )
66                                                 delete element.events[type][i];
67                         else
68                                 for ( var j in element.events )
69                                         this.remove( element, j );
70         },
71
72         trigger: function(type, data, element) {
73                 // Clone the incoming data, if any
74                 data = jQuery.makeArray(data || []);
75
76                 // Handle a global trigger
77                 if ( !element )
78                         jQuery.each( this.global[type] || [], function(){
79                                 jQuery.event.trigger( type, data, this );
80                         });
81
82                 // Handle triggering a single element
83                 else {
84                         var handler = element["on" + type ], val,
85                                 fn = jQuery.isFunction( element[ type ] );
86
87                         if ( handler ) {
88                                 // Pass along a fake event
89                                 data.unshift( this.fix({ type: type, target: element }) );
90         
91                                 // Trigger the event
92                                 if ( (val = handler.apply( element, data )) !== false )
93                                         this.triggered = true;
94                         }
95
96                         if ( fn && val !== false )
97                                 element[ type ]();
98
99                         this.triggered = false;
100                 }
101         },
102
103         handle: function(event) {
104                 // Handle the second event of a trigger and when
105                 // an event is called after a page has unloaded
106                 if ( typeof jQuery == "undefined" || jQuery.event.triggered ) return;
107
108                 // Empty object is for triggered events with no data
109                 event = jQuery.event.fix( event || window.event || {} ); 
110
111                 // returned undefined or false
112                 var returnValue;
113
114                 var c = this.events[event.type];
115
116                 var args = [].slice.call( arguments, 1 );
117                 args.unshift( event );
118
119                 for ( var j in c ) {
120                         // Pass in a reference to the handler function itself
121                         // So that we can later remove it
122                         args[0].handler = c[j];
123                         args[0].data = c[j].data;
124
125                         if ( c[j].apply( this, args ) === false ) {
126                                 event.preventDefault();
127                                 event.stopPropagation();
128                                 returnValue = false;
129                         }
130                 }
131
132                 // Clean up added properties in IE to prevent memory leak
133                 if (jQuery.browser.msie) event.target = event.preventDefault = event.stopPropagation = event.handler = event.data = null;
134
135                 return returnValue;
136         },
137
138         fix: function(event) {
139                 // Fix target property, if necessary
140                 if ( !event.target && event.srcElement )
141                         event.target = event.srcElement;
142
143                 // Calculate pageX/Y if missing and clientX/Y available
144                 if ( event.pageX == undefined && event.clientX != undefined ) {
145                         var e = document.documentElement, b = document.body;
146                         event.pageX = event.clientX + (e.scrollLeft || b.scrollLeft);
147                         event.pageY = event.clientY + (e.scrollTop || b.scrollTop);
148                 }
149                                 
150                 // check if target is a textnode (safari)
151                 if (jQuery.browser.safari && event.target.nodeType == 3) {
152                         // store a copy of the original event object 
153                         // and clone because target is read only
154                         var originalEvent = event;
155                         event = jQuery.extend({}, originalEvent);
156                         
157                         // get parentnode from textnode
158                         event.target = originalEvent.target.parentNode;
159                         
160                         // add preventDefault and stopPropagation since 
161                         // they will not work on the clone
162                         event.preventDefault = function() {
163                                 return originalEvent.preventDefault();
164                         };
165                         event.stopPropagation = function() {
166                                 return originalEvent.stopPropagation();
167                         };
168                 }
169                 
170                 // fix preventDefault and stopPropagation
171                 if (!event.preventDefault)
172                         event.preventDefault = function() {
173                                 this.returnValue = false;
174                         };
175                         
176                 if (!event.stopPropagation)
177                         event.stopPropagation = function() {
178                                 this.cancelBubble = true;
179                         };
180                         
181                 return event;
182         }
183 };
184
185 jQuery.fn.extend({
186
187         /**
188          * Binds a handler to a particular event (like click) for each matched element.
189          * The event handler is passed an event object that you can use to prevent
190          * default behaviour. To stop both default action and event bubbling, your handler
191          * has to return false.
192          *
193          * In most cases, you can define your event handlers as anonymous functions
194          * (see first example). In cases where that is not possible, you can pass additional
195          * data as the second paramter (and the handler function as the third), see 
196          * second example.
197          *
198          * @example $("p").bind("click", function(){
199          *   alert( $(this).text() );
200          * });
201          * @before <p>Hello</p>
202          * @result alert("Hello")
203          *
204          * @example function handler(event) {
205          *   alert(event.data.foo);
206          * }
207          * $("p").bind("click", {foo: "bar"}, handler)
208          * @result alert("bar")
209          * @desc Pass some additional data to the event handler.
210          *
211          * @example $("form").bind("submit", function() { return false; })
212          * @desc Cancel a default action and prevent it from bubbling by returning false
213          * from your function.
214          *
215          * @example $("form").bind("submit", function(event){
216          *   event.preventDefault();
217          * });
218          * @desc Cancel only the default action by using the preventDefault method.
219          *
220          *
221          * @example $("form").bind("submit", function(event){
222          *   event.stopPropagation();
223          * });
224          * @desc Stop only an event from bubbling by using the stopPropagation method.
225          *
226          * @name bind
227          * @type jQuery
228          * @param String type An event type
229          * @param Object data (optional) Additional data passed to the event handler as event.data
230          * @param Function fn A function to bind to the event on each of the set of matched elements
231          * @cat Events
232          */
233         bind: function( type, data, fn ) {
234                 return this.each(function(){
235                         jQuery.event.add( this, type, fn || data, data );
236                 });
237         },
238         
239         /**
240          * Binds a handler to a particular event (like click) for each matched element.
241          * The handler is executed only once for each element. Otherwise, the same rules
242          * as described in bind() apply.
243          The event handler is passed an event object that you can use to prevent
244          * default behaviour. To stop both default action and event bubbling, your handler
245          * has to return false.
246          *
247          * In most cases, you can define your event handlers as anonymous functions
248          * (see first example). In cases where that is not possible, you can pass additional
249          * data as the second paramter (and the handler function as the third), see 
250          * second example.
251          *
252          * @example $("p").one("click", function(){
253          *   alert( $(this).text() );
254          * });
255          * @before <p>Hello</p>
256          * @result alert("Hello")
257          *
258          * @name one
259          * @type jQuery
260          * @param String type An event type
261          * @param Object data (optional) Additional data passed to the event handler as event.data
262          * @param Function fn A function to bind to the event on each of the set of matched elements
263          * @cat Events
264          */
265         one: function( type, data, fn ) {
266                 return this.each(function(){
267                         jQuery.event.add( this, type, function(event) {
268                                 jQuery(this).unbind(event);
269                                 return (fn || data).apply( this, arguments);
270                         }, data);
271                 });
272         },
273
274         /**
275          * The opposite of bind, removes a bound event from each of the matched
276          * elements.
277          *
278          * Without any arguments, all bound events are removed.
279          *
280          * If the type is provided, all bound events of that type are removed.
281          *
282          * If the function that was passed to bind is provided as the second argument,
283          * only that specific event handler is removed.
284          *
285          * @example $("p").unbind()
286          * @before <p onclick="alert('Hello');">Hello</p>
287          * @result [ <p>Hello</p> ]
288          *
289          * @example $("p").unbind( "click" )
290          * @before <p onclick="alert('Hello');">Hello</p>
291          * @result [ <p>Hello</p> ]
292          *
293          * @example $("p").unbind( "click", function() { alert("Hello"); } )
294          * @before <p onclick="alert('Hello');">Hello</p>
295          * @result [ <p>Hello</p> ]
296          *
297          * @name unbind
298          * @type jQuery
299          * @param String type (optional) An event type
300          * @param Function fn (optional) A function to unbind from the event on each of the set of matched elements
301          * @cat Events
302          */
303         unbind: function( type, fn ) {
304                 return this.each(function(){
305                         jQuery.event.remove( this, type, fn );
306                 });
307         },
308
309         /**
310          * Trigger a type of event on every matched element.
311          *
312          * @example $("p").trigger("click")
313          * @before <p click="alert('hello')">Hello</p>
314          * @result alert('hello')
315          *
316          * @example $("p").click(function(event, a, b) {
317          *   // when a normal click fires, a and b are undefined
318          *   // for a trigger like below a refers too "foo" and b refers to "bar"
319          * }).trigger("click", ["foo", "bar"]);
320          * @desc Example of how to pass arbitrary to an event
321          * 
322          * @before <p click="alert('hello')">Hello</p>
323          * @result alert('hello')
324          *
325          * @name trigger
326          * @type jQuery
327          * @param String type An event type to trigger.
328          * @param Array data (optional) Additional data to pass as arguments (after the event object) to the event handler
329          * @cat Events
330          */
331         trigger: function( type, data ) {
332                 return this.each(function(){
333                         jQuery.event.trigger( type, data, this );
334                 });
335         },
336
337         /**
338          * Toggle between two function calls every other click.
339          * Whenever a matched element is clicked, the first specified function 
340          * is fired, when clicked again, the second is fired. All subsequent 
341          * clicks continue to rotate through the two functions.
342          *
343          * Use unbind("click") to remove.
344          *
345          * @example $("p").toggle(function(){
346          *   $(this).addClass("selected");
347          * },function(){
348          *   $(this).removeClass("selected");
349          * });
350          * 
351          * @name toggle
352          * @type jQuery
353          * @param Function even The function to execute on every even click.
354          * @param Function odd The function to execute on every odd click.
355          * @cat Events
356          */
357         toggle: function() {
358                 // Save reference to arguments for access in closure
359                 var a = arguments;
360
361                 return this.click(function(e) {
362                         // Figure out which function to execute
363                         this.lastToggle = this.lastToggle == 0 ? 1 : 0;
364                         
365                         // Make sure that clicks stop
366                         e.preventDefault();
367                         
368                         // and execute the function
369                         return a[this.lastToggle].apply( this, [e] ) || false;
370                 });
371         },
372         
373         /**
374          * A method for simulating hovering (moving the mouse on, and off,
375          * an object). This is a custom method which provides an 'in' to a 
376          * frequent task.
377          *
378          * Whenever the mouse cursor is moved over a matched 
379          * element, the first specified function is fired. Whenever the mouse 
380          * moves off of the element, the second specified function fires. 
381          * Additionally, checks are in place to see if the mouse is still within 
382          * the specified element itself (for example, an image inside of a div), 
383          * and if it is, it will continue to 'hover', and not move out 
384          * (a common error in using a mouseout event handler).
385          *
386          * @example $("p").hover(function(){
387          *   $(this).addClass("over");
388          * },function(){
389          *   $(this).addClass("out");
390          * });
391          *
392          * @name hover
393          * @type jQuery
394          * @param Function over The function to fire whenever the mouse is moved over a matched element.
395          * @param Function out The function to fire whenever the mouse is moved off of a matched element.
396          * @cat Events
397          */
398         hover: function(f,g) {
399                 
400                 // A private function for handling mouse 'hovering'
401                 function handleHover(e) {
402                         // Check if mouse(over|out) are still within the same parent element
403                         var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
404         
405                         // Traverse up the tree
406                         while ( p && p != this ) try { p = p.parentNode } catch(e) { p = this; };
407                         
408                         // If we actually just moused on to a sub-element, ignore it
409                         if ( p == this ) return false;
410                         
411                         // Execute the right function
412                         return (e.type == "mouseover" ? f : g).apply(this, [e]);
413                 }
414                 
415                 // Bind the function to the two event listeners
416                 return this.mouseover(handleHover).mouseout(handleHover);
417         },
418         
419         /**
420          * Bind a function to be executed whenever the DOM is ready to be
421          * traversed and manipulated. This is probably the most important 
422          * function included in the event module, as it can greatly improve
423          * the response times of your web applications.
424          *
425          * In a nutshell, this is a solid replacement for using window.onload, 
426          * and attaching a function to that. By using this method, your bound Function 
427          * will be called the instant the DOM is ready to be read and manipulated, 
428          * which is exactly what 99.99% of all Javascript code needs to run.
429          *
430          * There is one argument passed to the ready event handler: A reference to
431          * the jQuery function. You can name that argument whatever you like, and
432          * can therefore stick with the $ alias without risk of naming collisions.
433          * 
434          * Please ensure you have no code in your &lt;body&gt; onload event handler, 
435          * otherwise $(document).ready() may not fire.
436          *
437          * You can have as many $(document).ready events on your page as you like.
438          * The functions are then executed in the order they were added.
439          *
440          * @example $(document).ready(function(){ Your code here... });
441          *
442          * @example jQuery(function($) {
443          *   // Your code using failsafe $ alias here...
444          * });
445          * @desc Uses both the shortcut for $(document).ready() and the argument
446          * to write failsafe jQuery code using the $ alias, without relying on the
447          * global alias.
448          *
449          * @name ready
450          * @type jQuery
451          * @param Function fn The function to be executed when the DOM is ready.
452          * @cat Events
453          * @see $.noConflict()
454          * @see $(Function)
455          */
456         ready: function(f) {
457                 // If the DOM is already ready
458                 if ( jQuery.isReady )
459                         // Execute the function immediately
460                         f.apply( document, [jQuery] );
461                         
462                 // Otherwise, remember the function for later
463                 else {
464                         // Add the function to the wait list
465                         jQuery.readyList.push( function() { return f.apply(this, [jQuery]) } );
466                 }
467         
468                 return this;
469         }
470 });
471
472 jQuery.extend({
473         /*
474          * All the code that makes DOM Ready work nicely.
475          */
476         isReady: false,
477         readyList: [],
478         
479         // Handle when the DOM is ready
480         ready: function() {
481                 // Make sure that the DOM is not already loaded
482                 if ( !jQuery.isReady ) {
483                         // Remember that the DOM is ready
484                         jQuery.isReady = true;
485                         
486                         // If there are functions bound, to execute
487                         if ( jQuery.readyList ) {
488                                 // Execute all of them
489                                 jQuery.each( jQuery.readyList, function(){
490                                         this.apply( document );
491                                 });
492                                 
493                                 // Reset the list of functions
494                                 jQuery.readyList = null;
495                         }
496                         // Remove event lisenter to avoid memory leak
497                         if ( jQuery.browser.mozilla || jQuery.browser.opera )
498                                 document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
499                 }
500         }
501 });
502
503 new function(){
504
505         /**
506          * Bind a function to the scroll event of each matched element.
507          *
508          * @example $("p").scroll( function() { alert("Hello"); } );
509          * @before <p>Hello</p>
510          * @result <p onscroll="alert('Hello');">Hello</p>
511          *
512          * @name scroll
513          * @type jQuery
514          * @param Function fn A function to bind to the scroll event on each of the matched elements.
515          * @cat Events
516          */
517
518         /**
519          * Bind a function to the submit event of each matched element.
520          *
521          * @example $("#myform").submit( function() {
522          *   return $("input", this).val().length > 0;
523          * } );
524          * @before <form id="myform"><input /></form>
525          * @desc Prevents the form submission when the input has no value entered.
526          *
527          * @name submit
528          * @type jQuery
529          * @param Function fn A function to bind to the submit event on each of the matched elements.
530          * @cat Events
531          */
532
533         /**
534          * Trigger the submit event of each matched element. This causes all of the functions
535          * that have been bound to thet submit event to be executed.
536          *
537          * Note: This does not execute the submit method of the form element! If you need to
538          * submit the form via code, you have to use the DOM method, eg. $("form")[0].submit();
539          *
540          * @example $("form").submit();
541          * @desc Triggers all submit events registered for forms, but does not submit the form
542          *
543          * @name submit
544          * @type jQuery
545          * @cat Events
546          */
547
548         /**
549          * Bind a function to the focus event of each matched element.
550          *
551          * @example $("p").focus( function() { alert("Hello"); } );
552          * @before <p>Hello</p>
553          * @result <p onfocus="alert('Hello');">Hello</p>
554          *
555          * @name focus
556          * @type jQuery
557          * @param Function fn A function to bind to the focus event on each of the matched elements.
558          * @cat Events
559          */
560
561         /**
562          * Trigger the focus event of each matched element. This causes all of the functions
563          * that have been bound to thet focus event to be executed.
564          *
565          * Note: This does not execute the focus method of the underlying elements! If you need to
566          * focus an element via code, you have to use the DOM method, eg. $("#myinput")[0].focus();
567          *
568          * @example $("p").focus();
569          * @before <p onfocus="alert('Hello');">Hello</p>
570          * @result alert('Hello');
571          *
572          * @name focus
573          * @type jQuery
574          * @cat Events
575          */
576
577         /**
578          * Bind a function to the keydown event of each matched element.
579          *
580          * @example $("p").keydown( function() { alert("Hello"); } );
581          * @before <p>Hello</p>
582          * @result <p onkeydown="alert('Hello');">Hello</p>
583          *
584          * @name keydown
585          * @type jQuery
586          * @param Function fn A function to bind to the keydown event on each of the matched elements.
587          * @cat Events
588          */
589
590         /**
591          * Bind a function to the dblclick event of each matched element.
592          *
593          * @example $("p").dblclick( function() { alert("Hello"); } );
594          * @before <p>Hello</p>
595          * @result <p ondblclick="alert('Hello');">Hello</p>
596          *
597          * @name dblclick
598          * @type jQuery
599          * @param Function fn A function to bind to the dblclick event on each of the matched elements.
600          * @cat Events
601          */
602
603         /**
604          * Bind a function to the keypress event of each matched element.
605          *
606          * @example $("p").keypress( function() { alert("Hello"); } );
607          * @before <p>Hello</p>
608          * @result <p onkeypress="alert('Hello');">Hello</p>
609          *
610          * @name keypress
611          * @type jQuery
612          * @param Function fn A function to bind to the keypress event on each of the matched elements.
613          * @cat Events
614          */
615
616         /**
617          * Bind a function to the error event of each matched element.
618          *
619          * @example $("p").error( function() { alert("Hello"); } );
620          * @before <p>Hello</p>
621          * @result <p onerror="alert('Hello');">Hello</p>
622          *
623          * @name error
624          * @type jQuery
625          * @param Function fn A function to bind to the error event on each of the matched elements.
626          * @cat Events
627          */
628
629         /**
630          * Bind a function to the blur event of each matched element.
631          *
632          * @example $("p").blur( function() { alert("Hello"); } );
633          * @before <p>Hello</p>
634          * @result <p onblur="alert('Hello');">Hello</p>
635          *
636          * @name blur
637          * @type jQuery
638          * @param Function fn A function to bind to the blur event on each of the matched elements.
639          * @cat Events
640          */
641
642         /**
643          * Trigger the blur event of each matched element. This causes all of the functions
644          * that have been bound to thet blur event to be executed.
645          *
646          * Note: This does not execute the blur method of the underlying elements! If you need to
647          * blur an element via code, you have to use the DOM method, eg. $("#myinput")[0].blur();
648          *
649          * @example $("p").blur();
650          * @before <p onblur="alert('Hello');">Hello</p>
651          * @result alert('Hello');
652          *
653          * @name blur
654          * @type jQuery
655          * @cat Events
656          */
657
658         /**
659          * Bind a function to the load event of each matched element.
660          *
661          * @example $("p").load( function() { alert("Hello"); } );
662          * @before <p>Hello</p>
663          * @result <p onload="alert('Hello');">Hello</p>
664          *
665          * @name load
666          * @type jQuery
667          * @param Function fn A function to bind to the load event on each of the matched elements.
668          * @cat Events
669          */
670
671         /**
672          * Bind a function to the select event of each matched element.
673          *
674          * @example $("p").select( function() { alert("Hello"); } );
675          * @before <p>Hello</p>
676          * @result <p onselect="alert('Hello');">Hello</p>
677          *
678          * @name select
679          * @type jQuery
680          * @param Function fn A function to bind to the select event on each of the matched elements.
681          * @cat Events
682          */
683
684         /**
685          * Trigger the select event of each matched element. This causes all of the functions
686          * that have been bound to thet select event to be executed.
687          *
688          * @example $("p").select();
689          * @before <p onselect="alert('Hello');">Hello</p>
690          * @result alert('Hello');
691          *
692          * @name select
693          * @type jQuery
694          * @cat Events
695          */
696
697         /**
698          * Bind a function to the mouseup event of each matched element.
699          *
700          * @example $("p").mouseup( function() { alert("Hello"); } );
701          * @before <p>Hello</p>
702          * @result <p onmouseup="alert('Hello');">Hello</p>
703          *
704          * @name mouseup
705          * @type jQuery
706          * @param Function fn A function to bind to the mouseup event on each of the matched elements.
707          * @cat Events
708          */
709
710         /**
711          * Bind a function to the unload event of each matched element.
712          *
713          * @example $("p").unload( function() { alert("Hello"); } );
714          * @before <p>Hello</p>
715          * @result <p onunload="alert('Hello');">Hello</p>
716          *
717          * @name unload
718          * @type jQuery
719          * @param Function fn A function to bind to the unload event on each of the matched elements.
720          * @cat Events
721          */
722
723         /**
724          * Bind a function to the change event of each matched element.
725          *
726          * @example $("p").change( function() { alert("Hello"); } );
727          * @before <p>Hello</p>
728          * @result <p onchange="alert('Hello');">Hello</p>
729          *
730          * @name change
731          * @type jQuery
732          * @param Function fn A function to bind to the change event on each of the matched elements.
733          * @cat Events
734          */
735
736         /**
737          * Bind a function to the mouseout event of each matched element.
738          *
739          * @example $("p").mouseout( function() { alert("Hello"); } );
740          * @before <p>Hello</p>
741          * @result <p onmouseout="alert('Hello');">Hello</p>
742          *
743          * @name mouseout
744          * @type jQuery
745          * @param Function fn A function to bind to the mouseout event on each of the matched elements.
746          * @cat Events
747          */
748
749         /**
750          * Bind a function to the keyup event of each matched element.
751          *
752          * @example $("p").keyup( function() { alert("Hello"); } );
753          * @before <p>Hello</p>
754          * @result <p onkeyup="alert('Hello');">Hello</p>
755          *
756          * @name keyup
757          * @type jQuery
758          * @param Function fn A function to bind to the keyup event on each of the matched elements.
759          * @cat Events
760          */
761
762         /**
763          * Bind a function to the click event of each matched element.
764          *
765          * @example $("p").click( function() { alert("Hello"); } );
766          * @before <p>Hello</p>
767          * @result <p onclick="alert('Hello');">Hello</p>
768          *
769          * @name click
770          * @type jQuery
771          * @param Function fn A function to bind to the click event on each of the matched elements.
772          * @cat Events
773          */
774
775         /**
776          * Trigger the click event of each matched element. This causes all of the functions
777          * that have been bound to thet click event to be executed.
778          *
779          * @example $("p").click();
780          * @before <p onclick="alert('Hello');">Hello</p>
781          * @result alert('Hello');
782          *
783          * @name click
784          * @type jQuery
785          * @cat Events
786          */
787
788         /**
789          * Bind a function to the resize event of each matched element.
790          *
791          * @example $("p").resize( function() { alert("Hello"); } );
792          * @before <p>Hello</p>
793          * @result <p onresize="alert('Hello');">Hello</p>
794          *
795          * @name resize
796          * @type jQuery
797          * @param Function fn A function to bind to the resize event on each of the matched elements.
798          * @cat Events
799          */
800
801         /**
802          * Bind a function to the mousemove event of each matched element.
803          *
804          * @example $("p").mousemove( function() { alert("Hello"); } );
805          * @before <p>Hello</p>
806          * @result <p onmousemove="alert('Hello');">Hello</p>
807          *
808          * @name mousemove
809          * @type jQuery
810          * @param Function fn A function to bind to the mousemove event on each of the matched elements.
811          * @cat Events
812          */
813
814         /**
815          * Bind a function to the mousedown event of each matched element.
816          *
817          * @example $("p").mousedown( function() { alert("Hello"); } );
818          * @before <p>Hello</p>
819          * @result <p onmousedown="alert('Hello');">Hello</p>
820          *
821          * @name mousedown
822          * @type jQuery
823          * @param Function fn A function to bind to the mousedown event on each of the matched elements.
824          * @cat Events
825          */
826          
827         /**
828          * Bind a function to the mouseover event of each matched element.
829          *
830          * @example $("p").mouseover( function() { alert("Hello"); } );
831          * @before <p>Hello</p>
832          * @result <p onmouseover="alert('Hello');">Hello</p>
833          *
834          * @name mouseover
835          * @type jQuery
836          * @param Function fn A function to bind to the mousedown event on each of the matched elements.
837          * @cat Events
838          */
839         jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
840                 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
841                 "submit,keydown,keypress,keyup,error").split(","), function(i,o){
842                 
843                 // Handle event binding
844                 jQuery.fn[o] = function(f){
845                         return f ? this.bind(o, f) : this.trigger(o);
846                 };
847                         
848         });
849         
850         // If Mozilla is used
851         if ( jQuery.browser.mozilla || jQuery.browser.opera )
852                 // Use the handy event callback
853                 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
854         
855         // If IE is used, use the excellent hack by Matthias Miller
856         // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
857         else if ( jQuery.browser.msie ) {
858         
859                 // Only works if you document.write() it
860                 document.write("<scr" + "ipt id=__ie_init defer=true " + 
861                         "src=//:><\/script>");
862         
863                 // Use the defer script hack
864                 var script = document.getElementById("__ie_init");
865                 
866                 // script does not exist if jQuery is loaded dynamically
867                 if ( script ) 
868                         script.onreadystatechange = function() {
869                                 if ( this.readyState != "complete" ) return;
870                                 this.parentNode.removeChild( this );
871                                 jQuery.ready();
872                         };
873         
874                 // Clear from memory
875                 script = null;
876         
877         // If Safari  is used
878         } else if ( jQuery.browser.safari )
879                 // Continually check to see if the document.readyState is valid
880                 jQuery.safariTimer = setInterval(function(){
881                         // loaded and complete are both valid states
882                         if ( document.readyState == "loaded" || 
883                                 document.readyState == "complete" ) {
884         
885                                 // If either one are found, remove the timer
886                                 clearInterval( jQuery.safariTimer );
887                                 jQuery.safariTimer = null;
888         
889                                 // and execute any waiting functions
890                                 jQuery.ready();
891                         }
892                 }, 10); 
893
894         // A fallback to window.onload, that will always work
895         jQuery.event.add( window, "load", jQuery.ready );
896         
897 };
898
899 // Clean up after IE to avoid memory leaks
900 if (jQuery.browser.msie)
901         jQuery(window).one("unload", function() {
902                 var global = jQuery.event.global;
903                 for ( var type in global ) {
904                         var els = global[type], i = els.length;
905                         if ( i && type != 'unload' )
906                                 do
907                                         jQuery.event.remove(els[i-1], type);
908                                 while (--i);
909                 }
910         });