Fixes #12736. Move hover event hack to deprecated.js for removal in 1.9. Closes gh...
[jquery.git] / test / unit / event.js
blobd6c24436a3ec82058a28291767a84ad0052a1323
1 module("event", { teardown: moduleTeardown });
3 test("null or undefined handler", function() {
4         expect(2);
5         // Supports Fixes bug #7229
6         try {
7                 jQuery("#firstp").click(null);
8                 ok(true, "Passing a null handler will not throw an exception");
9         } catch (e) {}
11         try {
12                 jQuery("#firstp").click(undefined);
13                 ok(true, "Passing an undefined handler will not throw an exception");
14         } catch (e) {}
15 });
17 test("bind(),live(),delegate() with non-null,defined data", function() {
19         expect(3);
21         var handler = function( event, data ) {
22                 equal( data, 0, "non-null, defined data (zero) is correctly passed" );
23         };
25         jQuery("#foo").bind("foo", handler);
26         jQuery("#foo").live("foo", handler);
27         jQuery("div").delegate("#foo", "foo", handler);
29         jQuery("#foo").trigger("foo", 0);
31         jQuery("#foo").unbind("foo", handler);
32         jQuery("#foo").die("foo", handler);
33         jQuery("div").undelegate("#foo", "foo");
35 });
37 test("Handler changes and .trigger() order", function() {
38         expect(1);
40         var markup = jQuery(
41                 "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
42         ),
43         path = "";
45         markup
46                 .find( "*" ).andSelf().on( "click", function( e ) {
47                         path += this.nodeName.toLowerCase() + " ";
48                 })
49                 .filter( "b" ).on( "click", function( e ) {
50                         // Removing span should not stop propagation to original parents
51                         if ( e.target === this ) {
52                                 jQuery(this).parent().remove();
53                         }
54                 });
56         markup.find( "b" ).trigger( "click" );
58         equal( path, "b p div div ", "Delivered all events" );
60         markup.remove();
61 });
63 test("bind(), with data", function() {
64         expect(4);
65         var handler = function(event) {
66                 ok( event.data, "bind() with data, check passed data exists" );
67                 equal( event.data["foo"], "bar", "bind() with data, Check value of passed data" );
68         };
69         jQuery("#firstp").bind("click", {"foo": "bar"}, handler).click().unbind("click", handler);
71         ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
73         var test = function(){};
74         var handler2 = function(event) {
75                 equal( event.data, test, "bind() with function data, Check value of passed data" );
76         };
77         jQuery("#firstp").bind("click", test, handler2).click().unbind("click", handler2);
78 });
80 test("click(), with data", function() {
81         expect(3);
82         var handler = function(event) {
83                 ok( event.data, "bind() with data, check passed data exists" );
84                 equal( event.data["foo"], "bar", "bind() with data, Check value of passed data" );
85         };
86         jQuery("#firstp").click({"foo": "bar"}, handler).click().unbind("click", handler);
88         ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
89 });
91 test("bind(), with data, trigger with data", function() {
92         expect(4);
93         var handler = function(event, data) {
94                 ok( event.data, "check passed data exists" );
95                 equal( event.data.foo, "bar", "Check value of passed data" );
96                 ok( data, "Check trigger data" );
97                 equal( data.bar, "foo", "Check value of trigger data" );
98         };
99         jQuery("#firstp").bind("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]).unbind("click", handler);
102 test("bind(), multiple events at once", function() {
103         expect(2);
104         var clickCounter = 0,
105                 mouseoverCounter = 0;
106         var handler = function(event) {
107                 if (event.type == "click") {
108                         clickCounter += 1;
109                 }
110                 else if (event.type == "mouseover") {
111                         mouseoverCounter += 1;
112                 }
114         };
115         jQuery("#firstp").bind("click mouseover", handler).trigger("click").trigger("mouseover");
116         equal( clickCounter, 1, "bind() with multiple events at once" );
117         equal( mouseoverCounter, 1, "bind() with multiple events at once" );
120 test("bind(), five events at once", function() {
121         expect(1);
123         var count = 0,
124                 handler = function(event) {
125                         count++;
126                 };
128         jQuery("#firstp").bind("click mouseover foo bar baz", handler)
129         .trigger("click").trigger("mouseover")
130                 .trigger("foo").trigger("bar")
131                 .trigger("baz");
133         equal( count, 5, "bind() five events at once" );
136 test("bind(), multiple events at once and namespaces", function() {
137         expect(7);
139         var cur, obj = {};
141         var div = jQuery("<div/>").bind("focusin.a", function(e) {
142                 equal( e.type, cur, "Verify right single event was fired." );
143         });
145         cur = "focusin";
146         div.trigger("focusin.a");
148         // manually clean up detached elements
149         div.remove();
151         div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
152                 equal( e.type, cur, "Verify right multi event was fired." );
153                 equal( e.data, obj, "Make sure the data came in correctly." );
154         });
156         cur = "click";
157         div.trigger("click");
159         cur = "mouseover";
160         div.trigger("mouseover");
162         // manually clean up detached elements
163         div.remove();
165         div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
166                 equal( e.type, cur, "Verify right multi event was fired." );
167         });
169         cur = "focusin";
170         div.trigger("focusin.a");
172         cur = "focusout";
173         div.trigger("focusout.b");
175         // manually clean up detached elements
176         div.remove();
179 test("bind(), namespace with special add", function() {
180         expect(27);
182         var div = jQuery("<div/>").bind("test", function(e) {
183                 ok( true, "Test event fired." );
184         });
186         var i = 0;
188         jQuery.event.special["test"] = {
189                 _default: function(e, data) {
190                         equal( this, document, "Make sure we're at the top of the chain." );
191                         equal( e.type, "test", "And that we're still dealing with a test event." );
192                         equal( e.target, div[0], "And that the target is correct." );
193                         ok( data !== undefined , "And that trigger data was passed." );
194                 },
195                 setup: function(){},
196                 teardown: function(){
197                         ok(true, "Teardown called.");
198                 },
199                 add: function( handleObj ) {
200                         var handler = handleObj.handler;
201                         handleObj.handler = function(e) {
202                                 e.xyz = ++i;
203                                 handler.apply( this, arguments );
204                         };
205                 },
206                 remove: function() {
207                         ok(true, "Remove called.");
208                 }
209         };
211         div.bind("test.a", {"x": 1}, function(e) {
212                 ok( !!e.xyz, "Make sure that the data is getting passed through." );
213                 equal( e.data["x"], 1, "Make sure data is attached properly." );
214         });
216         div.bind("test.b", {"x": 2}, function(e) {
217                 ok( !!e.xyz, "Make sure that the data is getting passed through." );
218                 equal( e.data["x"], 2, "Make sure data is attached properly." );
219         });
221         // Should trigger 5
222         div.trigger("test", 33.33);
224         // Should trigger 2
225         div.trigger("test.a", "George Harrison");
227         // Should trigger 2
228         div.trigger("test.b", { year: 1982 });
230         // Should trigger 4
231         div.unbind("test");
233         div = jQuery("<div/>").bind("test", function(e) {
234                 ok( true, "Test event fired." );
235         });
237         // Should trigger 2
238         div.appendTo("#qunit-fixture").remove();
240         delete jQuery.event.special["test"];
243 test("bind(), no data", function() {
244         expect(1);
245         var handler = function(event) {
246                 ok ( !event.data, "Check that no data is added to the event object" );
247         };
248         jQuery("#firstp").bind("click", handler).trigger("click");
251 test("bind/one/unbind(Object)", function(){
252         expect(6);
254         var clickCounter = 0, mouseoverCounter = 0;
255         function handler(event) {
256                 if (event.type == "click") {
258                         clickCounter++;
259                 }
260                 else if (event.type == "mouseover") {
261                         mouseoverCounter++;
262                 }
264         }
266         function handlerWithData(event) {
267                 if (event.type == "click") {
268                         clickCounter += event.data;
269                 }
270                 else if (event.type == "mouseover") {
271                         mouseoverCounter += event.data;
272                 }
273         }
275         function trigger(){
276                 $elem.trigger("click").trigger("mouseover");
277         }
279         var $elem = jQuery("#firstp")
280                 // Regular bind
281                 .bind({
282                         "click":handler,
283                         "mouseover":handler
284                 })
285                 // Bind with data
286                 .one({
287                         "click":handlerWithData,
288                         "mouseover":handlerWithData
289                 }, 2 );
291         trigger();
293         equal( clickCounter, 3, "bind(Object)" );
294         equal( mouseoverCounter, 3, "bind(Object)" );
296         trigger();
297         equal( clickCounter, 4, "bind(Object)" );
298         equal( mouseoverCounter, 4, "bind(Object)" );
300         jQuery("#firstp").unbind({
301                 "click":handler,
302                 "mouseover":handler
303         });
305         trigger();
306         equal( clickCounter, 4, "bind(Object)" );
307         equal( mouseoverCounter, 4, "bind(Object)" );
310 test("live/die(Object), delegate/undelegate(String, Object)", function() {
311         expect(6);
313         var clickCounter = 0, mouseoverCounter = 0,
314                 $p = jQuery("#firstp"), $a = $p.find("a:first");
316         var events = {
317                 "click": function( event ) {
318                         clickCounter += ( event.data || 1 );
319                 },
320                 "mouseover": function( event ) {
321                         mouseoverCounter += ( event.data || 1 );
322                 }
323         };
325         function trigger() {
326                 $a.trigger("click").trigger("mouseover");
327         }
329         $a.live( events );
330         $p.delegate( "a", events, 2 );
332         trigger();
333         equal( clickCounter, 3, "live/delegate" );
334         equal( mouseoverCounter, 3, "live/delegate" );
336         $p.undelegate( "a", events );
338         trigger();
339         equal( clickCounter, 4, "undelegate" );
340         equal( mouseoverCounter, 4, "undelegate" );
342         $a.die( events );
344         trigger();
345         equal( clickCounter, 4, "die" );
346         equal( mouseoverCounter, 4, "die" );
349 test("live/delegate immediate propagation", function() {
350         expect(2);
352         var $p = jQuery("#firstp"), $a = $p.find("a:first"), lastClick;
354         lastClick = "";
355         $a.live( "click", function(e) {
356                 lastClick = "click1";
357                 e.stopImmediatePropagation();
358         });
359         $a.live( "click", function(e) {
360                 lastClick = "click2";
361         });
362         $a.trigger( "click" );
363         equal( lastClick, "click1", "live stopImmediatePropagation" );
364         $a.die( "click" );
366         lastClick = "";
367         $p.delegate( "a", "click", function(e) {
368                 lastClick = "click1";
369                 e.stopImmediatePropagation();
370         });
371         $p.delegate( "a", "click", function(e) {
372                 lastClick = "click2";
373         });
374         $a.trigger( "click" );
375         equal( lastClick, "click1", "delegate stopImmediatePropagation" );
376         $p.undelegate( "click" );
379 test("bind/delegate bubbling, isDefaultPrevented", function() {
380         expect(2);
381         var $anchor2 = jQuery( "#anchor2" ),
382                 $main = jQuery( "#qunit-fixture" ),
383                 fakeClick = function($jq) {
384                         // Use a native click so we don't get jQuery simulated bubbling
385                         if ( document.createEvent ) {
386                                 var e = document.createEvent( "MouseEvents" );
387                                 e.initEvent( "click", true, true );
388                                 $jq[0].dispatchEvent(e);
389                         }
390                         else if ( $jq[0].click ) {
391                                 $jq[0].click(); // IE
392                         }
393                 };
394         $anchor2.click(function(e) {
395                 e.preventDefault();
396         });
397         $main.delegate("#foo", "click", function(e) {
398                 var orig = e.originalEvent;
400                 if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig["getPreventDefault"] ) {
401                         equal( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
403                 } else {
404                         // Opera < 11 doesn't implement any interface we can use, so give it a pass
405                         ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
406                 }
407         });
408         fakeClick( $anchor2 );
409         $anchor2.unbind( "click" );
410         $main.undelegate( "click" );
411         $anchor2.click(function(e) {
412                 // Let the default action occur
413         });
414         $main.delegate("#foo", "click", function(e) {
415                 equal( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
416         });
417         fakeClick( $anchor2 );
418         $anchor2.unbind( "click" );
419         $main.undelegate( "click" );
422 test("bind(), iframes", function() {
423         expect( 1 );
425         // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
426         var doc = jQuery("#loadediframe").contents();
428         jQuery("div", doc).bind("click", function() {
429                 ok( true, "Binding to element inside iframe" );
430         }).click().unbind("click");
433 test("bind(), trigger change on select", function() {
434         expect(5);
435         var counter = 0;
436         function selectOnChange(event) {
437                 equal( event.data, counter++, "Event.data is not a global event object" );
438         }
439         jQuery("#form select").each(function(i){
440                 jQuery(this).bind("change", i, selectOnChange);
441         }).trigger("change");
444 test("bind(), namespaced events, cloned events", 18, function() {
445         var firstp = jQuery( "#firstp" );
447         firstp.bind("custom.test",function(e){
448                 ok(false, "Custom event triggered");
449         });
451         firstp.bind("click",function(e){
452                 ok(true, "Normal click triggered");
453                 equal( e.type + e.namespace, "click", "Check that only click events trigger this fn" );
454         });
456         firstp.bind("click.test",function(e){
457                 var check = "click";
458                 ok( true, "Namespaced click triggered" );
459                 if ( e.namespace ) {
460                         check += "test";
461                 }
462                 equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
463         });
465         //clone(true) element to verify events are cloned correctly
466         firstp = firstp.add( firstp.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp ) );
468         // Trigger both bound fn (8)
469         firstp.trigger("click");
471         // Trigger one bound fn (4)
472         firstp.trigger("click.test");
474         // Remove only the one fn
475         firstp.unbind("click.test");
477         // Trigger the remaining fn (4)
478         firstp.trigger("click");
480         // Remove the remaining namespaced fn
481         firstp.unbind(".test");
483         // Try triggering the custom event (0)
484         firstp.trigger("custom");
486         // using contents will get comments regular, text, and comment nodes
487         jQuery("#nonnodes").contents().bind("tester", function () {
488                 equal(this.nodeType, 1, "Check node,textnode,comment bind just does real nodes" );
489         }).trigger("tester");
491         // Make sure events stick with appendTo'd elements (which are cloned) #2027
492         jQuery("<a href='#fail' class='test'>test</a>").click(function(){ return false; }).appendTo("#qunit-fixture");
493         ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" );
496 test("bind(), multi-namespaced events", function() {
497         expect(6);
499         var order = [
500                 "click.test.abc",
501                 "click.test.abc",
502                 "click.test",
503                 "click.test.abc",
504                 "click.test",
505                 "custom.test2"
506         ];
508         function check(name, msg){
509                 deepEqual(name, order.shift(), msg);
510         }
512         jQuery("#firstp").bind("custom.test",function(e){
513                 check("custom.test", "Custom event triggered");
514         });
516         jQuery("#firstp").bind("custom.test2",function(e){
517                 check("custom.test2", "Custom event triggered");
518         });
520         jQuery("#firstp").bind("click.test",function(e){
521                 check("click.test", "Normal click triggered");
522         });
524         jQuery("#firstp").bind("click.test.abc",function(e){
525                 check("click.test.abc", "Namespaced click triggered");
526         });
528         // Those would not trigger/unbind (#5303)
529         jQuery("#firstp").trigger("click.a.test");
530         jQuery("#firstp").unbind("click.a.test");
532         // Trigger both bound fn (1)
533         jQuery("#firstp").trigger("click.test.abc");
535         // Trigger one bound fn (1)
536         jQuery("#firstp").trigger("click.abc");
538         // Trigger two bound fn (2)
539         jQuery("#firstp").trigger("click.test");
541         // Remove only the one fn
542         jQuery("#firstp").unbind("click.abc");
544         // Trigger the remaining fn (1)
545         jQuery("#firstp").trigger("click");
547         // Remove the remaining fn
548         jQuery("#firstp").unbind(".test");
550         // Trigger the remaining fn (1)
551         jQuery("#firstp").trigger("custom");
554 test("bind(), with same function", function() {
555         expect(2);
557         var count = 0, func = function(){
558                 count++;
559         };
561         jQuery("#liveHandlerOrder").bind("foo.bar", func).bind("foo.zar", func);
562         jQuery("#liveHandlerOrder").trigger("foo.bar");
564         equal(count, 1, "Verify binding function with multiple namespaces." );
566         jQuery("#liveHandlerOrder").unbind("foo.bar", func).unbind("foo.zar", func);
567         jQuery("#liveHandlerOrder").trigger("foo.bar");
569         equal(count, 1, "Verify that removing events still work." );
572 test("bind(), make sure order is maintained", function() {
573         expect(1);
575         var elem = jQuery("#firstp"), log = [], check = [];
577         jQuery.each( new Array(100), function( i ) {
578                 elem.bind( "click", function(){
579                         log.push( i );
580                 });
582                 check.push( i );
584         });
586         elem.trigger("click");
588         equal( log.join(","), check.join(","), "Make sure order was maintained." );
590         elem.unbind("click");
593 test("bind(), with different this object", function() {
594         expect(4);
595         var thisObject = { myThis: true },
596                 data = { myData: true },
597                 handler1 = function( event ) {
598                         equal( this, thisObject, "bind() with different this object" );
599                 },
600                 handler2 = function( event ) {
601                         equal( this, thisObject, "bind() with different this object and data" );
602                         equal( event.data, data, "bind() with different this object and data" );
603                 };
605         jQuery("#firstp")
606                 .bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
607                 .bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2);
609         ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
612 test("bind(name, false), unbind(name, false)", function() {
613         expect(3);
615         var main = 0;
616         jQuery("#qunit-fixture").bind("click", function(e){ main++; });
617         jQuery("#ap").trigger("click");
618         equal( main, 1, "Verify that the trigger happened correctly." );
620         main = 0;
621         jQuery("#ap").bind("click", false);
622         jQuery("#ap").trigger("click");
623         equal( main, 0, "Verify that no bubble happened." );
625         main = 0;
626         jQuery("#ap").unbind("click", false);
627         jQuery("#ap").trigger("click");
628         equal( main, 1, "Verify that the trigger happened correctly." );
630         // manually clean up events from elements outside the fixture
631         jQuery("#qunit-fixture").unbind("click");
634 test("live(name, false), die(name, false)", function() {
635         expect(3);
637         var main = 0;
638         jQuery("#qunit-fixture").live("click", function(e){ main++; });
639         jQuery("#ap").trigger("click");
640         equal( main, 1, "Verify that the trigger happened correctly." );
642         main = 0;
643         jQuery("#ap").live("click", false);
644         jQuery("#ap").trigger("click");
645         equal( main, 0, "Verify that no bubble happened." );
647         main = 0;
648         jQuery("#ap").die("click", false);
649         jQuery("#ap").trigger("click");
650         equal( main, 1, "Verify that the trigger happened correctly." );
651         jQuery("#qunit-fixture").die("click");
654 test("delegate(selector, name, false), undelegate(selector, name, false)", function() {
655         expect(3);
657         var main = 0;
659         jQuery("#qunit-fixture").delegate("#ap", "click", function(e){ main++; });
660         jQuery("#ap").trigger("click");
661         equal( main, 1, "Verify that the trigger happened correctly." );
663         main = 0;
664         jQuery("#ap").delegate("#groups", "click", false);
665         jQuery("#groups").trigger("click");
666         equal( main, 0, "Verify that no bubble happened." );
668         main = 0;
669         jQuery("#ap").undelegate("#groups", "click", false);
670         jQuery("#groups").trigger("click");
671         equal( main, 1, "Verify that the trigger happened correctly." );
672         jQuery("#qunit-fixture").undelegate("#ap", "click");
675 test("bind()/trigger()/unbind() on plain object", function() {
676         expect( 7 );
678         var obj = {};
680         // Make sure it doesn't complain when no events are found
681         jQuery(obj).trigger("test");
683         // Make sure it doesn't complain when no events are found
684         jQuery(obj).unbind("test");
686         jQuery(obj).bind({
687                 "test": function() {
688                         ok( true, "Custom event run." );
689                 },
690                 "submit": function() {
691                         ok( true, "Custom submit event run." );
692                 }
693         });
695         var events = jQuery._data(obj, "events");
696         ok( events, "Object has events bound." );
697         equal( obj["events"], undefined, "Events object on plain objects is not events" );
698         equal( obj["test"], undefined, "Make sure that test event is not on the plain object." );
699         equal( obj["handle"], undefined, "Make sure that the event handler is not on the plain object." );
701         // Should trigger 1
702         jQuery(obj).trigger("test");
703         jQuery(obj).trigger("submit");
705         jQuery(obj).unbind("test");
706         jQuery(obj).unbind("submit");
708         // Should trigger 0
709         jQuery(obj).trigger("test");
711         // Make sure it doesn't complain when no events are found
712         jQuery(obj).unbind("test");
714         equal( obj && obj[ jQuery.expando ] &&
715                         obj[ jQuery.expando ][ jQuery.expando ] &&
716                         obj[ jQuery.expando ][ jQuery.expando ]["events"], undefined, "Make sure events object is removed" );
719 test("unbind(type)", function() {
720         expect( 1 );
722         var $elem = jQuery("#firstp"),
723                 message;
725         function error(){
726                 ok( false, message );
727         }
729         message = "unbind passing function";
730         $elem.bind("error1", error).unbind("error1", error).triggerHandler("error1");
732         message = "unbind all from event";
733         $elem.bind("error1", error).unbind("error1").triggerHandler("error1");
735         message = "unbind all";
736         $elem.bind("error1", error).unbind().triggerHandler("error1");
738         message = "unbind many with function";
739         $elem.bind("error1 error2",error)
740                 .unbind("error1 error2", error )
741                 .trigger("error1").triggerHandler("error2");
743         message = "unbind many"; // #3538
744         $elem.bind("error1 error2", error)
745                 .unbind("error1 error2")
746                 .trigger("error1").triggerHandler("error2");
748         message = "unbind without a type or handler";
749         $elem.bind("error1 error2.test",error)
750                 .unbind()
751                 .trigger("error1").triggerHandler("error2");
753         // Should only unbind the specified function
754         jQuery( document ).bind( "click", function(){
755                 ok( true, "called handler after selective removal");
756         });
757         var func = function(){ };
758         jQuery( document )
759                 .bind( "click", func )
760                 .unbind( "click", func )
761                 .click()
762                 .unbind( "click" );
765 test("unbind(eventObject)", function() {
766         expect(4);
768         var $elem = jQuery("#firstp"),
769                 num;
771         function assert( expected ){
772                 num = 0;
773                 $elem.trigger("foo").triggerHandler("bar");
774                 equal( num, expected, "Check the right handlers are triggered" );
775         }
777         $elem
778                 // This handler shouldn't be unbound
779                 .bind("foo", function(){
780                         num += 1;
781                 })
782                 .bind("foo", function(e){
783                         $elem.unbind( e );
784                         num += 2;
785                 })
786                 // Neither this one
787                 .bind("bar", function(){
788                         num += 4;
789                 });
791         assert( 7 );
792         assert( 5 );
794         $elem.unbind("bar");
795         assert( 1 );
797         $elem.unbind();
798         assert( 0 );
801 test("hover() mouseenter mouseleave", function() {
802         expect(1);
804         var times = 0,
805                 handler1 = function( event ) { ++times; },
806                 handler2 = function( event ) { ++times; };
808         jQuery("#firstp")
809                 .hover(handler1, handler2)
810                 .mouseenter().mouseleave()
811                 .unbind("mouseenter", handler1)
812                 .unbind("mouseleave", handler2)
813                 .hover(handler1)
814                 .mouseenter().mouseleave()
815                 .unbind("mouseenter mouseleave", handler1)
816                 .mouseenter().mouseleave();
818         equal( times, 4, "hover handlers fired" );
822 test("mouseover triggers mouseenter", function() {
823         expect(1);
825         var count = 0,
826                 elem = jQuery("<a />");
827         elem.mouseenter(function () {
828                 count++;
829         });
830         elem.trigger("mouseover");
831         equal(count, 1, "make sure mouseover triggers a mouseenter" );
833         elem.remove();
836 test("withinElement implemented with jQuery.contains()", function() {
838         expect(1);
840         jQuery("#qunit-fixture").append("<div id='jc-outer'><div id='jc-inner'></div></div>");
842         jQuery("#jc-outer").bind("mouseenter mouseleave", function( event ) {
844                 equal( this.id, "jc-outer", this.id + " " + event.type );
846         }).trigger("mouseenter");
848         jQuery("#jc-inner").trigger("mousenter");
850         jQuery("#jc-outer").unbind("mouseenter mouseleave").remove();
851         jQuery("#jc-inner").remove();
855 test("mouseenter, mouseleave don't catch exceptions", function() {
856         expect(2);
858         var elem = jQuery("#firstp").hover(function() { throw "an Exception"; });
860         try {
861                 elem.mouseenter();
862         } catch (e) {
863                 equal( e, "an Exception", "mouseenter doesn't catch exceptions" );
864         }
866         try {
867                 elem.mouseleave();
868         } catch (e) {
869                 equal( e, "an Exception", "mouseleave doesn't catch exceptions" );
870         }
873 test("trigger() shortcuts", function() {
874         expect(6);
876         var elem = jQuery("<li><a href='#'>Change location</a></li>").prependTo("#firstUL");
877         elem.find("a").bind("click", function() {
878                 var close = jQuery("spanx", this); // same with jQuery(this).find("span");
879                 equal( close.length, 0, "Context element does not exist, length must be zero" );
880                 ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
881                 return false;
882         }).click();
884         // manually clean up detached elements
885         elem.remove();
887         jQuery("#check1").click(function() {
888                 ok( true, "click event handler for checkbox gets fired twice, see #815" );
889         }).click();
891         var counter = 0;
892         jQuery("#firstp")[0].onclick = function(event) {
893                 counter++;
894         };
895         jQuery("#firstp").click();
896         equal( counter, 1, "Check that click, triggers onclick event handler also" );
898         var clickCounter = 0;
899         jQuery("#simon1")[0].onclick = function(event) {
900                 clickCounter++;
901         };
902         jQuery("#simon1").click();
903         equal( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
905         elem = jQuery("<img />").load(function(){
906                 ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
907         }).load();
909         // manually clean up detached elements
910         elem.remove();
912         // test that special handlers do not blow up with VML elements (#7071)
913         jQuery("<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />").appendTo("head");
914         jQuery("<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>").appendTo("#form");
915         jQuery("#oval").click().keydown();
918 test("trigger() bubbling", function() {
919         expect(18);
921         var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
923         jQuery(window).bind("click", function(e){ win++; });
924         jQuery(document).bind("click", function(e){ if ( e.target !== document) { doc++; } });
925         jQuery("html").bind("click", function(e){ html++; });
926         jQuery("body").bind("click", function(e){ body++; });
927         jQuery("#qunit-fixture").bind("click", function(e){ main++; });
928         jQuery("#ap").bind("click", function(){ ap++; return false; });
930         jQuery("html").trigger("click");
931         equal( win, 1, "HTML bubble" );
932         equal( doc, 1, "HTML bubble" );
933         equal( html, 1, "HTML bubble" );
935         jQuery("body").trigger("click");
936         equal( win, 2, "Body bubble" );
937         equal( doc, 2, "Body bubble" );
938         equal( html, 2, "Body bubble" );
939         equal( body, 1, "Body bubble" );
941         jQuery("#qunit-fixture").trigger("click");
942         equal( win, 3, "Main bubble" );
943         equal( doc, 3, "Main bubble" );
944         equal( html, 3, "Main bubble" );
945         equal( body, 2, "Main bubble" );
946         equal( main, 1, "Main bubble" );
948         jQuery("#ap").trigger("click");
949         equal( doc, 3, "ap bubble" );
950         equal( html, 3, "ap bubble" );
951         equal( body, 2, "ap bubble" );
952         equal( main, 1, "ap bubble" );
953         equal( ap, 1, "ap bubble" );
955         jQuery( document ).trigger("click");
956         equal( win, 4, "doc bubble" );
958         // manually clean up events from elements outside the fixture
959         jQuery(document).unbind("click");
960         jQuery("html, body, #qunit-fixture").unbind("click");
963 test("trigger(type, [data], [fn])", function() {
964         expect(16);
966         var handler = function(event, a, b, c) {
967                 equal( event.type, "click", "check passed data" );
968                 equal( a, 1, "check passed data" );
969                 equal( b, "2", "check passed data" );
970                 equal( c, "abc", "check passed data" );
971                 return "test";
972         };
974         var $elem = jQuery("#firstp");
976         // Simulate a "native" click
977         $elem[0].click = function(){
978                 ok( true, "Native call was triggered" );
979         };
982         $elem.live("mouseenter", function(){
983                 ok( true, "Trigger mouseenter bound by live" );
984         });
986         $elem.live("mouseleave", function(){
987                 ok( true, "Trigger mouseleave bound by live" );
988         });
990         $elem.trigger("mouseenter");
992         $elem.trigger("mouseleave");
994         $elem.die("mouseenter");
996         $elem.die("mouseleave");
998         // Triggers handlrs and native
999         // Trigger 5
1000         $elem.bind("click", handler).trigger("click", [1, "2", "abc"]);
1002         // Simulate a "native" click
1003         $elem[0].click = function(){
1004                 ok( false, "Native call was triggered" );
1005         };
1007         // Trigger only the handlers (no native)
1008         // Triggers 5
1009         equal( $elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
1011         var pass = true, elem2;
1012         try {
1013                 elem2 = jQuery("#form input:first");
1014                 elem2.get(0).style.display = "none";
1015                 elem2.trigger("focus");
1016         } catch(e) {
1017                 pass = false;
1018         }
1019         ok( pass, "Trigger focus on hidden element" );
1021         pass = true;
1022         try {
1023                 jQuery("#qunit-fixture table:first").bind("test:test", function(){}).trigger("test:test");
1024         } catch (e) {
1025                 pass = false;
1026         }
1027         ok( pass, "Trigger on a table with a colon in the even type, see #3533" );
1029         var form = jQuery("<form action=''></form>").appendTo("body");
1031         // Make sure it can be prevented locally
1032         form.submit(function(){
1033                 ok( true, "Local bind still works." );
1034                 return false;
1035         });
1037         // Trigger 1
1038         form.trigger("submit");
1040         form.unbind("submit");
1042         jQuery(document).submit(function(){
1043                 ok( true, "Make sure bubble works up to document." );
1044                 return false;
1045         });
1047         // Trigger 1
1048         form.trigger("submit");
1050         jQuery(document).unbind("submit");
1052         form.remove();
1055 test( "submit event bubbles on copied forms (#11649)", function(){
1056         expect( 3 );
1058         var $formByClone, $formByHTML,
1059                 $testForm = jQuery("#testForm"),
1060                 $fixture = jQuery("#qunit-fixture"),
1061                 $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
1063         function noSubmit( e ) {
1064                 e.preventDefault();
1065         }
1066         function delegatedSubmit() {
1067                 ok( true, "Make sure submit event bubbles up." );
1068                 return false;
1069         }
1071         // Attach a delegated submit handler to the parent element
1072         $fixture.on( "submit", "form", delegatedSubmit );
1074         // Trigger form submission to introduce the _submit_attached property
1075         $testForm.on( "submit", noSubmit ).find("input[name=sub1]").click();
1077         // Copy the form via .clone() and .html()
1078         $formByClone = $testForm.clone( true, true ).removeAttr("id");
1079         $formByHTML = jQuery( $fixture.html() ).filter("#testForm").removeAttr("id");
1080         $wrapperDiv.append( $formByClone, $formByHTML );
1082         // Check submit bubbling on the copied forms
1083         $wrapperDiv.find("form").on( "submit", noSubmit ).find("input[name=sub1]").click();
1085         // Clean up
1086         $wrapperDiv.remove();
1087         $fixture.off( "submit", "form", delegatedSubmit );
1088         $testForm.off( "submit", noSubmit );
1091 test( "change event bubbles on copied forms (#11796)", function(){
1092         expect( 3 );
1094         var $formByClone, $formByHTML,
1095                 $form = jQuery("#form"),
1096                 $fixture = jQuery("#qunit-fixture"),
1097                 $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
1099         function delegatedChange() {
1100                 ok( true, "Make sure change event bubbles up." );
1101                 return false;
1102         }
1104         // Attach a delegated change handler to the form
1105         $fixture.on( "change", "form", delegatedChange );
1107         // Trigger change event to introduce the _change_attached property
1108         $form.find("select[name=select1]").val("1").change();
1110         // Copy the form via .clone() and .html()
1111         $formByClone = $form.clone( true, true ).removeAttr("id");
1112         $formByHTML = jQuery( $fixture.html() ).filter("#form").removeAttr("id");
1113         $wrapperDiv.append( $formByClone, $formByHTML );
1115         // Check change bubbling on the copied forms
1116         $wrapperDiv.find("form select[name=select1]").val("2").change();
1118         // Clean up
1119         $wrapperDiv.remove();
1120         $fixture.off( "change", "form", delegatedChange );
1123 test("trigger(eventObject, [data], [fn])", function() {
1124         expect(28);
1126         var $parent = jQuery("<div id='par' />").appendTo("body"),
1127                 $child = jQuery("<p id='child'>foo</p>").appendTo( $parent );
1129         $parent.get( 0 ).style.display = "none";
1131         var event = jQuery.Event("noNew");
1132         ok( event != window, "Instantiate jQuery.Event without the 'new' keyword" );
1133         equal( event.type, "noNew", "Verify its type" );
1135         equal( event.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1136         equal( event.isPropagationStopped(), false, "Verify isPropagationStopped" );
1137         equal( event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1139         event.preventDefault();
1140         equal( event.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
1141         event.stopPropagation();
1142         equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
1144         event.isPropagationStopped = function(){ return false; };
1145         event.stopImmediatePropagation();
1146         equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
1147         equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
1149         $parent.bind("foo",function(e){
1150                 // Tries bubbling
1151                 equal( e.type, "foo", "Verify event type when passed passing an event object" );
1152                 equal( e.target.id, "child", "Verify event.target when passed passing an event object" );
1153                 equal( e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object" );
1154                 equal( e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object" );
1155         });
1157         // test with an event object
1158         event = new jQuery.Event("foo");
1159         event.secret = "boo!";
1160         $child.trigger(event);
1162         // test with a literal object
1163         $child.trigger({"type": "foo", "secret": "boo!"});
1165         $parent.unbind();
1167         function error(){
1168                 ok( false, "This assertion shouldn't be reached");
1169         }
1171         $parent.bind("foo", error );
1173         $child.bind("foo",function(e, a, b, c ){
1174                 equal( arguments.length, 4, "Check arguments length");
1175                 equal( a, 1, "Check first custom argument");
1176                 equal( b, 2, "Check second custom argument");
1177                 equal( c, 3, "Check third custom argument");
1179                 equal( e.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1180                 equal( e.isPropagationStopped(), false, "Verify isPropagationStopped" );
1181                 equal( e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1183                 // Skips both errors
1184                 e.stopImmediatePropagation();
1186                 return "result";
1187         });
1189         // We should add this back in when we want to test the order
1190         // in which event handlers are iterated.
1191         //$child.bind("foo", error );
1193         event = new jQuery.Event("foo");
1194         $child.trigger( event, [1,2,3] ).unbind();
1195         equal( event.result, "result", "Check event.result attribute");
1197         // Will error if it bubbles
1198         $child.triggerHandler("foo");
1200         $child.unbind();
1201         $parent.unbind().remove();
1203         // Ensure triggerHandler doesn't molest its event object (#xxx)
1204         event = jQuery.Event( "zowie" );
1205         jQuery( document ).triggerHandler( event );
1206         equal( event.type, "zowie", "Verify its type" );
1207         equal( event.isPropagationStopped(), false, "propagation not stopped" );
1208         equal( event.isDefaultPrevented(), false, "default not prevented" );
1211 test(".trigger() bubbling on disconnected elements (#10489)", function() {
1212         expect(2);
1214         jQuery( window ).on( "click", function(){
1215                 ok( false, "click fired on window" );
1216         });
1218         jQuery( "<div><p>hi</p></div>" )
1219                 .on( "click", function() {
1220                         ok( true, "click fired on div" );
1221                 })
1222                 .find( "p" )
1223                         .on( "click", function() {
1224                                 ok( true, "click fired on p" );
1225                         })
1226                         .click()
1227                         .off( "click" )
1228                 .end()
1229                 .off( "click" )
1230                 .remove();
1232         jQuery( window ).off( "click" );
1235 test(".trigger() doesn't bubble load event (#10717)", function() {
1236         expect(1);
1238         jQuery( window ).on( "load", function(){
1239                 ok( false, "load fired on window" );
1240         });
1242         // It's not an image, but as long as it fires load...
1243         jQuery("<img src='index.html' />")
1244                 .appendTo( "body" )
1245                 .on( "load", function() {
1246                         ok( true, "load fired on img" );
1247                 })
1248                 .trigger( "load" )
1249                 .remove();
1251         jQuery( window ).off( "load" );
1254 test("Delegated events in SVG (#10791)", function() {
1255         expect(2);
1257         var svg = jQuery(
1258                         "<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>" +
1259                         "<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1260                         "<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1261                         "</svg>"
1262                 ).appendTo( "body" );
1264         jQuery( "body" )
1265                 .on( "click", "#svg-by-id", function() {
1266                         ok( true, "delegated id selector" );
1267                 })
1268                 .on( "click", "[class~='svg-by-class']", function() {
1269                         ok( true, "delegated class selector" );
1270                 })
1271                 .find( "#svg-by-id, [class~='svg-by-class']" )
1272                         .trigger( "click" )
1273                 .end()
1274                 .off( "click" );
1276         svg.remove();
1279 test("Delegated events in forms (#10844; #11145; #8165; #11382, #11764)", function() {
1280         expect(5);
1282         // Alias names like "id" cause havoc
1283         var form = jQuery(
1284                         "<form id='myform'>" +
1285                                 "<input type='text' name='id' value='secret agent man' />" +
1286                         "</form>"
1287                 )
1288                 .on( "submit", function( event ) {
1289                         event.preventDefault();
1290                 })
1291                 .appendTo("body");
1293         jQuery("body")
1294                 .on( "submit", "#myform", function() {
1295                         ok( true, "delegated id selector with aliased id" );
1296                 })
1297                 .find("#myform")
1298                         .trigger("submit")
1299                 .end()
1300                 .off("submit");
1302         form.append("<input type='text' name='disabled' value='differently abled' />");
1303         jQuery("body")
1304                 .on( "submit", "#myform", function() {
1305                         ok( true, "delegated id selector with aliased disabled" );
1306                 })
1307                 .find("#myform")
1308                         .trigger("submit")
1309                 .end()
1310                 .off("submit");
1312         form
1313                 .append( "<button id='nestyDisabledBtn'><span>Zing</span></button>" )
1314                 .on( "click", "#nestyDisabledBtn", function() {
1315                         ok( true, "click on enabled/disabled button with nesty elements" );
1316                 })
1317                 .on( "mouseover", "#nestyDisabledBtn", function() {
1318                         ok( true, "mouse on enabled/disabled button with nesty elements" );
1319                 })
1320                 .find( "span" )
1321                         .trigger( "click" )             // yep
1322                         .trigger( "mouseover" ) // yep
1323                 .end()
1324                 .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
1325                 .find( "span" )
1326                         .trigger( "click" )             // nope
1327                         .trigger( "mouseover" ) // yep
1328                 .end()
1329                 .off( "click" );
1331         form.remove();
1334 test("Submit event can be stopped (#11049)", function() {
1335         expect(1);
1337         // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
1338         var form = jQuery(
1339                         "<form id='myform'>" +
1340                                 "<input type='text' name='sue' value='bawls' />" +
1341                                 "<input type='submit' />" +
1342                         "</form>"
1343                 )
1344                 .appendTo("body");
1346         jQuery( "body" )
1347                 .on( "submit", function() {
1348                         ok( true, "submit bubbled on first handler" );
1349                         return false;
1350                 })
1351                 .find( "#myform input[type=submit]" )
1352                         .each( function(){ this.click(); } )
1353                 .end()
1354                 .on( "submit", function() {
1355                         ok( false, "submit bubbled on second handler" );
1356                         return false;
1357                 })
1358                 .find( "#myform input[type=submit]" )
1359                         .each( function(){
1360                                 jQuery( this.form ).on( "submit", function( e ) {
1361                                         e.preventDefault();
1362                                         e.stopPropagation();
1363                                 });
1364                                 this.click();
1365                         })
1366                 .end()
1367                 .off( "submit" );
1369         form.remove();
1372 test("on(beforeunload) creates/deletes window property instead of adding/removing event listener", function() {
1373         expect(3);
1375         equal( window.onbeforeunload, null, "window property is null/undefined up until now" );
1377         var handle = function () {};
1378         jQuery(window).on( "beforeunload", handle );
1380         equal( typeof window.onbeforeunload, "function", "window property is set to a function");
1382         jQuery(window).off( "beforeunload", handle );
1384         equal( window.onbeforeunload, null, "window property has been unset to null/undefined" );
1387 test("jQuery.Event( type, props )", function() {
1389         expect(5);
1391         var event = jQuery.Event( "keydown", { keyCode: 64 }),
1392                         handler = function( event ) {
1393                                 ok( "keyCode" in event, "Special property 'keyCode' exists" );
1394                                 equal( event.keyCode, 64, "event.keyCode has explicit value '64'" );
1395                         };
1397         // Supports jQuery.Event implementation
1398         equal( event.type, "keydown", "Verify type" );
1400         // ensure "type" in props won't clobber the one set by constructor
1401         equal( jQuery.inArray("type", jQuery.event.props), -1, "'type' property not in props (#10375)" );
1403         ok( "keyCode" in event, "Special 'keyCode' property exists" );
1405         jQuery("body").bind( "keydown", handler ).trigger( event );
1407         jQuery("body").unbind( "keydown" );
1411 test("jQuery.Event.currentTarget", function(){
1412         expect(2);
1414         jQuery("<div><p><button>shiny</button></p></div>")
1415                 .on( "click", "p", function( e ){
1416                                 equal( e.currentTarget, this, "Check delegated currentTarget on event" );
1417                 })
1418                 .find( "button" )
1419                         .on( "click", function( e ){
1420                                 equal( e.currentTarget, this, "Check currentTarget on event" );
1421                         })
1422                         .click()
1423                         .off( "click" )
1424                 .end()
1425                 .off( "click" );
1428 test(".live()/.die()", function() {
1429         expect(66);
1431         var submit = 0, div = 0, livea = 0, liveb = 0;
1433         jQuery("div").live("submit", function(){ submit++; return false; });
1434         jQuery("div").live("click", function(){ div++; });
1435         jQuery("div#nothiddendiv").live("click", function(){ livea++; });
1436         jQuery("div#nothiddendivchild").live("click", function(){ liveb++; });
1438         // Nothing should trigger on the body
1439         jQuery("body").trigger("click");
1440         equal( submit, 0, "Click on body" );
1441         equal( div, 0, "Click on body" );
1442         equal( livea, 0, "Click on body" );
1443         equal( liveb, 0, "Click on body" );
1445         // This should trigger two events
1446         submit = 0; div = 0; livea = 0; liveb = 0;
1447         jQuery("div#nothiddendiv").trigger("click");
1448         equal( submit, 0, "Click on div" );
1449         equal( div, 1, "Click on div" );
1450         equal( livea, 1, "Click on div" );
1451         equal( liveb, 0, "Click on div" );
1453         // This should trigger three events (w/ bubbling)
1454         submit = 0; div = 0; livea = 0; liveb = 0;
1455         jQuery("div#nothiddendivchild").trigger("click");
1456         equal( submit, 0, "Click on inner div" );
1457         equal( div, 2, "Click on inner div" );
1458         equal( livea, 1, "Click on inner div" );
1459         equal( liveb, 1, "Click on inner div" );
1461         // This should trigger one submit
1462         submit = 0; div = 0; livea = 0; liveb = 0;
1463         jQuery("div#nothiddendivchild").trigger("submit");
1464         equal( submit, 1, "Submit on div" );
1465         equal( div, 0, "Submit on div" );
1466         equal( livea, 0, "Submit on div" );
1467         equal( liveb, 0, "Submit on div" );
1469         // Make sure no other events were removed in the process
1470         submit = 0; div = 0; livea = 0; liveb = 0;
1471         jQuery("div#nothiddendivchild").trigger("click");
1472         equal( submit, 0, "die Click on inner div" );
1473         equal( div, 2, "die Click on inner div" );
1474         equal( livea, 1, "die Click on inner div" );
1475         equal( liveb, 1, "die Click on inner div" );
1477         // Now make sure that the removal works
1478         submit = 0; div = 0; livea = 0; liveb = 0;
1479         jQuery("div#nothiddendivchild").die("click");
1480         jQuery("div#nothiddendivchild").trigger("click");
1481         equal( submit, 0, "die Click on inner div" );
1482         equal( div, 2, "die Click on inner div" );
1483         equal( livea, 1, "die Click on inner div" );
1484         equal( liveb, 0, "die Click on inner div" );
1486         // Make sure that the click wasn't removed too early
1487         submit = 0; div = 0; livea = 0; liveb = 0;
1488         jQuery("div#nothiddendiv").trigger("click");
1489         equal( submit, 0, "die Click on inner div" );
1490         equal( div, 1, "die Click on inner div" );
1491         equal( livea, 1, "die Click on inner div" );
1492         equal( liveb, 0, "die Click on inner div" );
1494         // Make sure that stopPropgation doesn't stop live events
1495         submit = 0; div = 0; livea = 0; liveb = 0;
1496         jQuery("div#nothiddendivchild").live("click", function(e){ liveb++; e.stopPropagation(); });
1497         jQuery("div#nothiddendivchild").trigger("click");
1498         equal( submit, 0, "stopPropagation Click on inner div" );
1499         equal( div, 1, "stopPropagation Click on inner div" );
1500         equal( livea, 0, "stopPropagation Click on inner div" );
1501         equal( liveb, 1, "stopPropagation Click on inner div" );
1503         // Make sure click events only fire with primary click
1504         submit = 0; div = 0; livea = 0; liveb = 0;
1505         var event = jQuery.Event("click");
1506         event.button = 1;
1507         jQuery("div#nothiddendiv").trigger(event);
1509         equal( livea, 0, "live secondary click" );
1511         jQuery("div#nothiddendivchild").die("click");
1512         jQuery("div#nothiddendiv").die("click");
1513         jQuery("div").die("click");
1514         jQuery("div").die("submit");
1516         // Test binding with a different context
1517         var clicked = 0, container = jQuery("#qunit-fixture")[0];
1518         jQuery("#foo", container).live("click", function(e){ clicked++; });
1519         jQuery("div").trigger("click");
1520         jQuery("#foo").trigger("click");
1521         jQuery("#qunit-fixture").trigger("click");
1522         jQuery("body").trigger("click");
1523         equal( clicked, 2, "live with a context" );
1525         // Test unbinding with a different context
1526         jQuery("#foo", container).die("click");
1527         jQuery("#foo").trigger("click");
1528         equal( clicked, 2, "die with a context");
1530         // Test binding with event data
1531         jQuery("#foo").live("click", true, function(e){ equal( e.data, true, "live with event data" ); });
1532         jQuery("#foo").trigger("click").die("click");
1534         // Test binding with trigger data
1535         jQuery("#foo").live("click", function(e, data){ equal( data, true, "live with trigger data" ); });
1536         jQuery("#foo").trigger("click", true).die("click");
1538         // Test binding with different this object
1539         jQuery("#foo").live("click", jQuery.proxy(function(e){ equal( this.foo, "bar", "live with event scope" ); }, { foo: "bar" }));
1540         jQuery("#foo").trigger("click").die("click");
1542         // Test binding with different this object, event data, and trigger data
1543         jQuery("#foo").live("click", true, jQuery.proxy(function(e, data){
1544                 equal( e.data, true, "live with with different this object, event data, and trigger data" );
1545                 equal( this["foo"], "bar", "live with with different this object, event data, and trigger data" );
1546                 equal( data, true, "live with with different this object, event data, and trigger data");
1547         }, { "foo": "bar" }));
1548         jQuery("#foo").trigger("click", true).die("click");
1550         // Verify that return false prevents default action
1551         jQuery("#anchor2").live("click", function(){ return false; });
1552         var hash = window.location.hash;
1553         jQuery("#anchor2").trigger("click");
1554         equal( window.location.hash, hash, "return false worked" );
1555         jQuery("#anchor2").die("click");
1557         // Verify that .preventDefault() prevents default action
1558         jQuery("#anchor2").live("click", function(e){ e.preventDefault(); });
1559         hash = window.location.hash;
1560         jQuery("#anchor2").trigger("click");
1561         equal( window.location.hash, hash, "e.preventDefault() worked" );
1562         jQuery("#anchor2").die("click");
1564         // Test binding the same handler to multiple points
1565         var called = 0;
1566         function callback(){ called++; return false; }
1568         jQuery("#nothiddendiv").live("click", callback);
1569         jQuery("#anchor2").live("click", callback);
1571         jQuery("#nothiddendiv").trigger("click");
1572         equal( called, 1, "Verify that only one click occurred." );
1574         called = 0;
1575         jQuery("#anchor2").trigger("click");
1576         equal( called, 1, "Verify that only one click occurred." );
1578         // Make sure that only one callback is removed
1579         jQuery("#anchor2").die("click", callback);
1581         called = 0;
1582         jQuery("#nothiddendiv").trigger("click");
1583         equal( called, 1, "Verify that only one click occurred." );
1585         called = 0;
1586         jQuery("#anchor2").trigger("click");
1587         equal( called, 0, "Verify that no click occurred." );
1589         // Make sure that it still works if the selector is the same,
1590         // but the event type is different
1591         jQuery("#nothiddendiv").live("foo", callback);
1593         // Cleanup
1594         jQuery("#nothiddendiv").die("click", callback);
1596         called = 0;
1597         jQuery("#nothiddendiv").trigger("click");
1598         equal( called, 0, "Verify that no click occurred." );
1600         called = 0;
1601         jQuery("#nothiddendiv").trigger("foo");
1602         equal( called, 1, "Verify that one foo occurred." );
1604         // Cleanup
1605         jQuery("#nothiddendiv").die("foo", callback);
1607         // Make sure we don't loose the target by DOM modifications
1608         // after the bubble already reached the liveHandler
1609         var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("<span></span>").get(0);
1611         jQuery("#nothiddendivchild").live("click", function(e){ jQuery("#nothiddendivchild").html(""); });
1612         jQuery("#nothiddendivchild").live("click", function(e){ if(e.target) {livec++;} });
1614         jQuery("#nothiddendiv span").click();
1615         equal( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
1616         equal( livec, 1, "Verify that second handler occurred even with nuked target." );
1618         // Cleanup
1619         jQuery("#nothiddendivchild").die("click");
1621         // Verify that .live() ocurs and cancel buble in the same order as
1622         // we would expect .bind() and .click() without delegation
1623         var lived = 0, livee = 0;
1625         // bind one pair in one order
1626         jQuery("span#liveSpan1 a").live("click", function(){ lived++; return false; });
1627         jQuery("span#liveSpan1").live("click", function(){ livee++; });
1629         jQuery("span#liveSpan1 a").click();
1630         equal( lived, 1, "Verify that only one first handler occurred." );
1631         equal( livee, 0, "Verify that second handler doesn't." );
1633         // and one pair in inverse
1634         jQuery("span#liveSpan2").live("click", function(){ livee++; });
1635         jQuery("span#liveSpan2 a").live("click", function(){ lived++; return false; });
1637         lived = 0;
1638         livee = 0;
1639         jQuery("span#liveSpan2 a").click();
1640         equal( lived, 1, "Verify that only one first handler occurred." );
1641         equal( livee, 0, "Verify that second handler doesn't." );
1643         // Cleanup
1644         jQuery("span#liveSpan1 a").die("click");
1645         jQuery("span#liveSpan1").die("click");
1646         jQuery("span#liveSpan2 a").die("click");
1647         jQuery("span#liveSpan2").die("click");
1649         // Test this, target and currentTarget are correct
1650         jQuery("span#liveSpan1").live("click", function(e){
1651                 equal( this.id, "liveSpan1", "Check the this within a live handler" );
1652                 equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a live handler" );
1653                 equal( e.delegateTarget, document, "Check the event.delegateTarget within a live handler" );
1654                 equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a live handler" );
1655         });
1657         jQuery("span#liveSpan1 a").click();
1659         jQuery("span#liveSpan1").die("click");
1661         // Work with deep selectors
1662         livee = 0;
1664         function clickB(){ livee++; }
1666         jQuery("#nothiddendiv div").live("click", function(){ livee++; });
1667         jQuery("#nothiddendiv div").live("click", clickB);
1668         jQuery("#nothiddendiv div").live("mouseover", function(){ livee++; });
1670         equal( livee, 0, "No clicks, deep selector." );
1672         livee = 0;
1673         jQuery("#nothiddendivchild").trigger("click");
1674         equal( livee, 2, "Click, deep selector." );
1676         livee = 0;
1677         jQuery("#nothiddendivchild").trigger("mouseover");
1678         equal( livee, 1, "Mouseover, deep selector." );
1680         jQuery("#nothiddendiv div").die("mouseover");
1682         livee = 0;
1683         jQuery("#nothiddendivchild").trigger("click");
1684         equal( livee, 2, "Click, deep selector." );
1686         livee = 0;
1687         jQuery("#nothiddendivchild").trigger("mouseover");
1688         equal( livee, 0, "Mouseover, deep selector." );
1690         jQuery("#nothiddendiv div").die("click", clickB);
1692         livee = 0;
1693         jQuery("#nothiddendivchild").trigger("click");
1694         equal( livee, 1, "Click, deep selector." );
1696         jQuery("#nothiddendiv div").die("click");
1698         // blur a non-input element, we should force-fire its handlers
1699         // regardless of whether it's burring or not (unlike browsers)
1700         jQuery("#nothiddendiv div")
1701                 .live("blur", function(){
1702                         ok( true, "Live div trigger blur." );
1703                 })
1704                 .trigger("blur")
1705                 .die("blur");
1708 test("die all bound events", function(){
1709         expect(1);
1711         var count = 0;
1712         var div = jQuery("div#nothiddendivchild");
1714         div.live("click submit", function(){ count++; });
1715         div.die();
1717         div.trigger("click");
1718         div.trigger("submit");
1720         equal( count, 0, "Make sure no events were triggered." );
1723 test("live with multiple events", function(){
1724         expect(1);
1726         var count = 0;
1727         var div = jQuery("div#nothiddendivchild");
1729         div.live("click submit", function(){ count++; });
1731         div.trigger("click");
1732         div.trigger("submit");
1734         equal( count, 2, "Make sure both the click and submit were triggered." );
1736         // manually clean up events from elements outside the fixture
1737         div.die();
1740 test("live with namespaces", function(){
1741         expect(15);
1743         var count1 = 0, count2 = 0;
1745         jQuery("#liveSpan1").live("foo.bar", function(e){
1746                 equal( e.namespace, "bar", "namespace is bar" );
1747                 count1++;
1748         });
1750         jQuery("#liveSpan1").live("foo.zed", function(e){
1751                 equal( e.namespace, "zed", "namespace is zed" );
1752                 count2++;
1753         });
1755         jQuery("#liveSpan1").trigger("foo.bar");
1756         equal( count1, 1, "Got live foo.bar" );
1757         equal( count2, 0, "Got live foo.bar" );
1759         count1 = 0; count2 = 0;
1761         jQuery("#liveSpan1").trigger("foo.zed");
1762         equal( count1, 0, "Got live foo.zed" );
1763         equal( count2, 1, "Got live foo.zed" );
1765         //remove one
1766         count1 = 0; count2 = 0;
1768         jQuery("#liveSpan1").die("foo.zed");
1769         jQuery("#liveSpan1").trigger("foo.bar");
1771         equal( count1, 1, "Got live foo.bar after dieing foo.zed" );
1772         equal( count2, 0, "Got live foo.bar after dieing foo.zed" );
1774         count1 = 0; count2 = 0;
1776         jQuery("#liveSpan1").trigger("foo.zed");
1777         equal( count1, 0, "Got live foo.zed" );
1778         equal( count2, 0, "Got live foo.zed" );
1780         //remove the other
1781         jQuery("#liveSpan1").die("foo.bar");
1783         count1 = 0; count2 = 0;
1785         jQuery("#liveSpan1").trigger("foo.bar");
1786         equal( count1, 0, "Did not respond to foo.bar after dieing it" );
1787         equal( count2, 0, "Did not respond to foo.bar after dieing it" );
1789         jQuery("#liveSpan1").trigger("foo.zed");
1790         equal( count1, 0, "Did not trigger foo.zed again" );
1791         equal( count2, 0, "Did not trigger foo.zed again" );
1794 test("live with change", function(){
1795         expect(8);
1797         var selectChange = 0, checkboxChange = 0;
1799         var select = jQuery("select[name='S1']");
1800         select.live("change", function() {
1801                 selectChange++;
1802         });
1804         var checkbox = jQuery("#check2"),
1805                 checkboxFunction = function(){
1806                         checkboxChange++;
1807                 };
1808         checkbox.live("change", checkboxFunction);
1810         // test click on select
1812         // second click that changed it
1813         selectChange = 0;
1814         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1815         select.trigger("change");
1816         equal( selectChange, 1, "Change on click." );
1818         // test keys on select
1819         selectChange = 0;
1820         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1821         select.trigger("change");
1822         equal( selectChange, 1, "Change on keyup." );
1824         // test click on checkbox
1825         checkbox.trigger("change");
1826         equal( checkboxChange, 1, "Change on checkbox." );
1828         // test blur/focus on text
1829         var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
1830         text.live("change", function() {
1831                 textChange++;
1832         });
1834         text.val(oldTextVal+"foo");
1835         text.trigger("change");
1836         equal( textChange, 1, "Change on text input." );
1838         text.val(oldTextVal);
1839         text.die("change");
1841         // test blur/focus on password
1842         var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
1843         password.live("change", function() {
1844                 passwordChange++;
1845         });
1847         password.val(oldPasswordVal + "foo");
1848         password.trigger("change");
1849         equal( passwordChange, 1, "Change on password input." );
1851         password.val(oldPasswordVal);
1852         password.die("change");
1854         // make sure die works
1856         // die all changes
1857         selectChange = 0;
1858         select.die("change");
1859         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1860         select.trigger("change");
1861         equal( selectChange, 0, "Die on click works." );
1863         selectChange = 0;
1864         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1865         select.trigger("change");
1866         equal( selectChange, 0, "Die on keyup works." );
1868         // die specific checkbox
1869         checkbox.die("change", checkboxFunction);
1870         checkbox.trigger("change");
1871         equal( checkboxChange, 1, "Die on checkbox." );
1874 test("live with submit", function() {
1875         expect(7);
1877         var count1 = 0, count2 = 0;
1879         jQuery("#testForm").live("submit", function(ev) {
1880                 count1++;
1881                 ev.preventDefault();
1882         });
1884         jQuery("body").live("submit", function(ev) {
1885                 count2++;
1886                 ev.preventDefault();
1887         });
1889         jQuery("#testForm input[name=sub1]").submit();
1890         equal( count1, 1, "Verify form submit." );
1891         equal( count2, 1, "Verify body submit." );
1893         jQuery("#testForm input[name=sub1]").live("click", function(ev) {
1894                 ok( true, "cancelling submit still calls click handler" );
1895         });
1897         jQuery("#testForm input[name=sub1]")[0].click();
1898         equal( count1, 2, "Verify form submit." );
1899         equal( count2, 2, "Verify body submit." );
1901         jQuery("#testForm button[name=sub4]")[0].click();
1902         equal( count1, 3, "Verify form submit." );
1903         equal( count2, 3, "Verify body submit." );
1905         jQuery("#testForm").die("submit");
1906         jQuery("#testForm input[name=sub1]").die("click");
1907         jQuery("body").die("submit");
1910 test("live with special events", function() {
1911         expect(13);
1913         jQuery.event.special["foo"] = {
1914                 setup: function( data, namespaces, handler ) {
1915                         ok( true, "Setup run." );
1916                 },
1917                 teardown: function( namespaces ) {
1918                         ok( true, "Teardown run." );
1919                 },
1920                 add: function( handleObj ) {
1921                         ok( true, "Add run." );
1922                 },
1923                 remove: function( handleObj ) {
1924                         ok( true, "Remove run." );
1925                 },
1926                 _default: function( event, arg ) {
1927                         ok( event.type === "foo" && arg == 42, "Default run with correct args." );
1928                 }
1929         };
1931         // Run: setup, add
1932         jQuery("#liveSpan1").live("foo.a", function(e){
1933                 ok( true, "Handler 1 run." );
1934         });
1936         // Run: add
1937         jQuery("#liveSpan1").live("foo.b", function(e){
1938                 ok( true, "Handler 2 run." );
1939         });
1941         // Run: Handler 1, Handler 2, Default
1942         jQuery("#liveSpan1").trigger("foo", 42);
1944         // Run: Handler 1, Default
1945         jQuery("#liveSpan1").trigger("foo.a", 42);
1947         // Run: remove
1948         jQuery("#liveSpan1").die("foo.a");
1950         // Run: Handler 2, Default
1951         jQuery("#liveSpan1").trigger("foo", 42);
1953         // Run: remove, teardown
1954         jQuery("#liveSpan1").die("foo");
1956         delete jQuery.event.special["foo"];
1959 test(".delegate()/.undelegate()", function() {
1960         expect(65);
1962         var submit = 0, div = 0, livea = 0, liveb = 0;
1964         jQuery("#body").delegate("div", "submit", function(){ submit++; return false; });
1965         jQuery("#body").delegate("div", "click", function(){ div++; });
1966         jQuery("#body").delegate("div#nothiddendiv", "click", function(){ livea++; });
1967         jQuery("#body").delegate("div#nothiddendivchild", "click", function(){ liveb++; });
1969         // Nothing should trigger on the body
1970         jQuery("body").trigger("click");
1971         equal( submit, 0, "Click on body" );
1972         equal( div, 0, "Click on body" );
1973         equal( livea, 0, "Click on body" );
1974         equal( liveb, 0, "Click on body" );
1976         // This should trigger two events
1977         submit = 0; div = 0; livea = 0; liveb = 0;
1978         jQuery("div#nothiddendiv").trigger("click");
1979         equal( submit, 0, "Click on div" );
1980         equal( div, 1, "Click on div" );
1981         equal( livea, 1, "Click on div" );
1982         equal( liveb, 0, "Click on div" );
1984         // This should trigger three events (w/ bubbling)
1985         submit = 0; div = 0; livea = 0; liveb = 0;
1986         jQuery("div#nothiddendivchild").trigger("click");
1987         equal( submit, 0, "Click on inner div" );
1988         equal( div, 2, "Click on inner div" );
1989         equal( livea, 1, "Click on inner div" );
1990         equal( liveb, 1, "Click on inner div" );
1992         // This should trigger one submit
1993         submit = 0; div = 0; livea = 0; liveb = 0;
1994         jQuery("div#nothiddendivchild").trigger("submit");
1995         equal( submit, 1, "Submit on div" );
1996         equal( div, 0, "Submit on div" );
1997         equal( livea, 0, "Submit on div" );
1998         equal( liveb, 0, "Submit on div" );
2000         // Make sure no other events were removed in the process
2001         submit = 0; div = 0; livea = 0; liveb = 0;
2002         jQuery("div#nothiddendivchild").trigger("click");
2003         equal( submit, 0, "undelegate Click on inner div" );
2004         equal( div, 2, "undelegate Click on inner div" );
2005         equal( livea, 1, "undelegate Click on inner div" );
2006         equal( liveb, 1, "undelegate Click on inner div" );
2008         // Now make sure that the removal works
2009         submit = 0; div = 0; livea = 0; liveb = 0;
2010         jQuery("#body").undelegate("div#nothiddendivchild", "click");
2011         jQuery("div#nothiddendivchild").trigger("click");
2012         equal( submit, 0, "undelegate Click on inner div" );
2013         equal( div, 2, "undelegate Click on inner div" );
2014         equal( livea, 1, "undelegate Click on inner div" );
2015         equal( liveb, 0, "undelegate Click on inner div" );
2017         // Make sure that the click wasn't removed too early
2018         submit = 0; div = 0; livea = 0; liveb = 0;
2019         jQuery("div#nothiddendiv").trigger("click");
2020         equal( submit, 0, "undelegate Click on inner div" );
2021         equal( div, 1, "undelegate Click on inner div" );
2022         equal( livea, 1, "undelegate Click on inner div" );
2023         equal( liveb, 0, "undelegate Click on inner div" );
2025         // Make sure that stopPropgation doesn't stop live events
2026         submit = 0; div = 0; livea = 0; liveb = 0;
2027         jQuery("#body").delegate("div#nothiddendivchild", "click", function(e){ liveb++; e.stopPropagation(); });
2028         jQuery("div#nothiddendivchild").trigger("click");
2029         equal( submit, 0, "stopPropagation Click on inner div" );
2030         equal( div, 1, "stopPropagation Click on inner div" );
2031         equal( livea, 0, "stopPropagation Click on inner div" );
2032         equal( liveb, 1, "stopPropagation Click on inner div" );
2034         // Make sure click events only fire with primary click
2035         submit = 0; div = 0; livea = 0; liveb = 0;
2036         var event = jQuery.Event("click");
2037         event.button = 1;
2038         jQuery("div#nothiddendiv").trigger(event);
2040         equal( livea, 0, "delegate secondary click" );
2042         jQuery("#body").undelegate("div#nothiddendivchild", "click");
2043         jQuery("#body").undelegate("div#nothiddendiv", "click");
2044         jQuery("#body").undelegate("div", "click");
2045         jQuery("#body").undelegate("div", "submit");
2047         // Test binding with a different context
2048         var clicked = 0, container = jQuery("#qunit-fixture")[0];
2049         jQuery("#qunit-fixture").delegate("#foo", "click", function(e){ clicked++; });
2050         jQuery("div").trigger("click");
2051         jQuery("#foo").trigger("click");
2052         jQuery("#qunit-fixture").trigger("click");
2053         jQuery("body").trigger("click");
2054         equal( clicked, 2, "delegate with a context" );
2056         // Test unbinding with a different context
2057         jQuery("#qunit-fixture").undelegate("#foo", "click");
2058         jQuery("#foo").trigger("click");
2059         equal( clicked, 2, "undelegate with a context");
2061         // Test binding with event data
2062         jQuery("#body").delegate("#foo", "click", true, function(e){ equal( e.data, true, "delegate with event data" ); });
2063         jQuery("#foo").trigger("click");
2064         jQuery("#body").undelegate("#foo", "click");
2066         // Test binding with trigger data
2067         jQuery("#body").delegate("#foo", "click", function(e, data){ equal( data, true, "delegate with trigger data" ); });
2068         jQuery("#foo").trigger("click", true);
2069         jQuery("#body").undelegate("#foo", "click");
2071         // Test binding with different this object
2072         jQuery("#body").delegate("#foo", "click", jQuery.proxy(function(e){ equal( this["foo"], "bar", "delegate with event scope" ); }, { "foo": "bar" }));
2073         jQuery("#foo").trigger("click");
2074         jQuery("#body").undelegate("#foo", "click");
2076         // Test binding with different this object, event data, and trigger data
2077         jQuery("#body").delegate("#foo", "click", true, jQuery.proxy(function(e, data){
2078                 equal( e.data, true, "delegate with with different this object, event data, and trigger data" );
2079                 equal( this.foo, "bar", "delegate with with different this object, event data, and trigger data" );
2080                 equal( data, true, "delegate with with different this object, event data, and trigger data");
2081         }, { "foo": "bar" }));
2082         jQuery("#foo").trigger("click", true);
2083         jQuery("#body").undelegate("#foo", "click");
2085         // Verify that return false prevents default action
2086         jQuery("#body").delegate("#anchor2", "click", function(){ return false; });
2087         var hash = window.location.hash;
2088         jQuery("#anchor2").trigger("click");
2089         equal( window.location.hash, hash, "return false worked" );
2090         jQuery("#body").undelegate("#anchor2", "click");
2092         // Verify that .preventDefault() prevents default action
2093         jQuery("#body").delegate("#anchor2", "click", function(e){ e.preventDefault(); });
2094         hash = window.location.hash;
2095         jQuery("#anchor2").trigger("click");
2096         equal( window.location.hash, hash, "e.preventDefault() worked" );
2097         jQuery("#body").undelegate("#anchor2", "click");
2099         // Test binding the same handler to multiple points
2100         var called = 0;
2101         function callback(){ called++; return false; }
2103         jQuery("#body").delegate("#nothiddendiv", "click", callback);
2104         jQuery("#body").delegate("#anchor2", "click", callback);
2106         jQuery("#nothiddendiv").trigger("click");
2107         equal( called, 1, "Verify that only one click occurred." );
2109         called = 0;
2110         jQuery("#anchor2").trigger("click");
2111         equal( called, 1, "Verify that only one click occurred." );
2113         // Make sure that only one callback is removed
2114         jQuery("#body").undelegate("#anchor2", "click", callback);
2116         called = 0;
2117         jQuery("#nothiddendiv").trigger("click");
2118         equal( called, 1, "Verify that only one click occurred." );
2120         called = 0;
2121         jQuery("#anchor2").trigger("click");
2122         equal( called, 0, "Verify that no click occurred." );
2124         // Make sure that it still works if the selector is the same,
2125         // but the event type is different
2126         jQuery("#body").delegate("#nothiddendiv", "foo", callback);
2128         // Cleanup
2129         jQuery("#body").undelegate("#nothiddendiv", "click", callback);
2131         called = 0;
2132         jQuery("#nothiddendiv").trigger("click");
2133         equal( called, 0, "Verify that no click occurred." );
2135         called = 0;
2136         jQuery("#nothiddendiv").trigger("foo");
2137         equal( called, 1, "Verify that one foo occurred." );
2139         // Cleanup
2140         jQuery("#body").undelegate("#nothiddendiv", "foo", callback);
2142         // Make sure we don't loose the target by DOM modifications
2143         // after the bubble already reached the liveHandler
2144         var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("<span></span>").get(0);
2146         jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ jQuery("#nothiddendivchild").html(""); });
2147         jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ if(e.target) {livec++;} });
2149         jQuery("#nothiddendiv span").click();
2150         equal( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
2151         equal( livec, 1, "Verify that second handler occurred even with nuked target." );
2153         // Cleanup
2154         jQuery("#body").undelegate("#nothiddendivchild", "click");
2156         // Verify that .live() ocurs and cancel buble in the same order as
2157         // we would expect .bind() and .click() without delegation
2158         var lived = 0, livee = 0;
2160         // bind one pair in one order
2161         jQuery("#body").delegate("span#liveSpan1 a", "click", function(){ lived++; return false; });
2162         jQuery("#body").delegate("span#liveSpan1", "click", function(){ livee++; });
2164         jQuery("span#liveSpan1 a").click();
2165         equal( lived, 1, "Verify that only one first handler occurred." );
2166         equal( livee, 0, "Verify that second handler doesn't." );
2168         // and one pair in inverse
2169         jQuery("#body").delegate("span#liveSpan2", "click", function(){ livee++; });
2170         jQuery("#body").delegate("span#liveSpan2 a", "click", function(){ lived++; return false; });
2172         lived = 0;
2173         livee = 0;
2174         jQuery("span#liveSpan2 a").click();
2175         equal( lived, 1, "Verify that only one first handler occurred." );
2176         equal( livee, 0, "Verify that second handler doesn't." );
2178         // Cleanup
2179         jQuery("#body").undelegate("click");
2181         // Test this, target and currentTarget are correct
2182         jQuery("#body").delegate("span#liveSpan1", "click", function(e){
2183                 equal( this.id, "liveSpan1", "Check the this within a delegate handler" );
2184                 equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a delegate handler" );
2185                 equal( e.delegateTarget, document.body, "Check the event.delegateTarget within a delegate handler" );
2186                 equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a delegate handler" );
2187         });
2189         jQuery("span#liveSpan1 a").click();
2191         jQuery("#body").undelegate("span#liveSpan1", "click");
2193         // Work with deep selectors
2194         livee = 0;
2196         function clickB(){ livee++; }
2198         jQuery("#body").delegate("#nothiddendiv div", "click", function(){ livee++; });
2199         jQuery("#body").delegate("#nothiddendiv div", "click", clickB);
2200         jQuery("#body").delegate("#nothiddendiv div", "mouseover", function(){ livee++; });
2202         equal( livee, 0, "No clicks, deep selector." );
2204         livee = 0;
2205         jQuery("#nothiddendivchild").trigger("click");
2206         equal( livee, 2, "Click, deep selector." );
2208         livee = 0;
2209         jQuery("#nothiddendivchild").trigger("mouseover");
2210         equal( livee, 1, "Mouseover, deep selector." );
2212         jQuery("#body").undelegate("#nothiddendiv div", "mouseover");
2214         livee = 0;
2215         jQuery("#nothiddendivchild").trigger("click");
2216         equal( livee, 2, "Click, deep selector." );
2218         livee = 0;
2219         jQuery("#nothiddendivchild").trigger("mouseover");
2220         equal( livee, 0, "Mouseover, deep selector." );
2222         jQuery("#body").undelegate("#nothiddendiv div", "click", clickB);
2224         livee = 0;
2225         jQuery("#nothiddendivchild").trigger("click");
2226         equal( livee, 1, "Click, deep selector." );
2228         jQuery("#body").undelegate("#nothiddendiv div", "click");
2231 test("jQuery.off using dispatched jQuery.Event", function() {
2232         expect(1);
2234         var markup = jQuery("<p><a href='#'>target</a></p>"),
2235                 count = 0;
2236         markup
2237                 .on( "click.name", "a", function( event ) {
2238                         equal( ++count, 1, "event called once before removal" );
2239                         jQuery().off( event );
2240                 })
2241                 .find("a").click().click().end()
2242                 .remove();
2245 test( "delegated event with delegateTarget-relative selector", function() {
2246         expect(3);
2247         var markup = jQuery("<ul><li><a id=\"a0\"></a><ul id=\"ul0\"><li class=test><a id=\"a0_0\"></a></li><li><a id=\"a0_1\"></a></li></ul></li></ul>").appendTo("#qunit-fixture");
2249         // Positional selector (#11315)
2250         markup
2251                 .on( "click", ">li>a", function() {
2252                         ok( this.id === "a0", "child li was clicked" );
2253                 })
2254                 .find("#ul0")
2255                         .on( "click", "li:first>a", function() {
2256                                 ok( this.id === "a0_0" , "first li under #u10 was clicked" );
2257                         })
2258                 .end()
2259                 .find("a").click().end()
2260                 .find("#ul0").off();
2262         // Non-positional selector (#12383)
2263         markup = markup.wrap("<div />").parent();
2264         markup
2265                 .find("#ul0")
2266                 .on( "click", "div li a", function() {
2267                         ok( false, "div is ABOVE the delegation point!" );
2268                 })
2269                 .on( "click", "ul a", function() {
2270                         ok( false, "ul is the delegation point!" );
2271                 })
2272                 .on( "click", "li.test a", function() {
2273                         ok( true, "li.test is below the delegation point." );
2274                 })
2275                 .find("#a0_0").click();
2277         markup.remove();
2280 test("stopPropagation() stops directly-bound events on delegated target", function() {
2281         expect(1);
2283         var markup = jQuery("<div><p><a href=\"#\">target</a></p></div>");
2284         markup
2285                 .on( "click", function() {
2286                         ok( false, "directly-bound event on delegate target was called" );
2287                 })
2288                 .on( "click", "a", function( e ) {
2289                         e.stopPropagation();
2290                         ok( true, "delegated handler was called" );
2291                 })
2292                 .find("a").click().end()
2293                 .remove();
2296 test("undelegate all bound events", function(){
2297         expect(2);
2299         var count = 0,
2300                 clicks = 0,
2301                 div = jQuery("#body");
2303         div.delegate( "div#nothiddendivchild", "click submit", function(){ count++; } );
2304         div.bind( "click", function(){ clicks++; } );
2305         div.undelegate();
2307         jQuery("div#nothiddendivchild").trigger("click");
2308         jQuery("div#nothiddendivchild").trigger("submit");
2310         equal( count, 0, "Make sure no events were triggered." );
2312         div.trigger("click");
2313         equal( clicks, 2, "Make sure delegated and directly bound event occurred." );
2314         div.unbind("click");
2317 test("delegate with multiple events", function(){
2318         expect(1);
2320         var count = 0;
2321         var div = jQuery("#body");
2323         div.delegate("div#nothiddendivchild", "click submit", function(){ count++; });
2325         jQuery("div#nothiddendivchild").trigger("click");
2326         jQuery("div#nothiddendivchild").trigger("submit");
2328         equal( count, 2, "Make sure both the click and submit were triggered." );
2330         jQuery("#body").undelegate();
2333 test("delegate with change", function(){
2334         expect(8);
2336         var selectChange = 0, checkboxChange = 0;
2338         var select = jQuery("select[name='S1']");
2339         jQuery("#body").delegate("select[name='S1']", "change", function() {
2340                 selectChange++;
2341         });
2343         var checkbox = jQuery("#check2"),
2344                 checkboxFunction = function(){
2345                         checkboxChange++;
2346                 };
2347         jQuery("#body").delegate("#check2", "change", checkboxFunction);
2349         // test click on select
2351         // second click that changed it
2352         selectChange = 0;
2353         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2354         select.trigger("change");
2355         equal( selectChange, 1, "Change on click." );
2357         // test keys on select
2358         selectChange = 0;
2359         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2360         select.trigger("change");
2361         equal( selectChange, 1, "Change on keyup." );
2363         // test click on checkbox
2364         checkbox.trigger("change");
2365         equal( checkboxChange, 1, "Change on checkbox." );
2367         // test blur/focus on text
2368         var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
2369         jQuery("#body").delegate("#name", "change", function() {
2370                 textChange++;
2371         });
2373         text.val(oldTextVal+"foo");
2374         text.trigger("change");
2375         equal( textChange, 1, "Change on text input." );
2377         text.val(oldTextVal);
2378         jQuery("#body").die("change");
2380         // test blur/focus on password
2381         var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
2382         jQuery("#body").delegate("#name", "change", function() {
2383                 passwordChange++;
2384         });
2386         password.val(oldPasswordVal + "foo");
2387         password.trigger("change");
2388         equal( passwordChange, 1, "Change on password input." );
2390         password.val(oldPasswordVal);
2391         jQuery("#body").undelegate("#name", "change");
2393         // make sure die works
2395         // die all changes
2396         selectChange = 0;
2397         jQuery("#body").undelegate("select[name='S1']", "change");
2398         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2399         select.trigger("change");
2400         equal( selectChange, 0, "Die on click works." );
2402         selectChange = 0;
2403         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2404         select.trigger("change");
2405         equal( selectChange, 0, "Die on keyup works." );
2407         // die specific checkbox
2408         jQuery("#body").undelegate("#check2", "change", checkboxFunction);
2409         checkbox.trigger("change");
2410         equal( checkboxChange, 1, "Die on checkbox." );
2413 test("delegate with submit", function() {
2414         expect( 2 );
2416         var count1 = 0, count2 = 0;
2418         jQuery("#body").delegate("#testForm", "submit", function(ev) {
2419                 count1++;
2420                 ev.preventDefault();
2421         });
2423         jQuery(document).delegate("body", "submit", function(ev) {
2424                 count2++;
2425                 ev.preventDefault();
2426         });
2428         jQuery("#testForm input[name=sub1]").submit();
2429         equal( count1, 1, "Verify form submit." );
2430         equal( count2, 1, "Verify body submit." );
2432         jQuery("#body").undelegate();
2433         jQuery(document).undelegate();
2436 test("undelegate() with only namespaces", function() {
2437         expect(2);
2439         var $delegate = jQuery("#liveHandlerOrder"),
2440                 count = 0;
2442         $delegate.delegate("a", "click.ns", function(e) {
2443                 count++;
2444         });
2446         jQuery("a", $delegate).eq(0).trigger("click.ns");
2448         equal( count, 1, "delegated click.ns");
2450         $delegate.undelegate(".ns");
2452         jQuery("a", $delegate).eq(1).trigger("click.ns");
2454         equal( count, 1, "no more .ns after undelegate");
2457 test("Non DOM element events", function() {
2458         expect(1);
2460         var o = {};
2462         jQuery(o).bind("nonelementobj", function(e) {
2463                 ok( true, "Event on non-DOM object triggered" );
2464         });
2466         jQuery(o).trigger("nonelementobj");
2469 test("inline handler returning false stops default", function() {
2470         expect(1);
2472         var markup = jQuery("<div><a href=\"#\" onclick=\"return false\">x</a></div>");
2473         markup.click(function(e) {
2474                 ok( e.isDefaultPrevented(), "inline handler prevented default");
2475                 return false;
2476         });
2477         markup.find("a").click();
2478         markup.off("click");
2481 test("window resize", function() {
2482         expect(2);
2484         jQuery(window).unbind();
2486         jQuery(window).bind("resize", function(){
2487                 ok( true, "Resize event fired." );
2488         }).resize().unbind("resize");
2490         ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." );
2493 test("focusin bubbles", function() {
2494         expect(2);
2496         var input = jQuery( "<input type='text' />" ).prependTo( "body" ),
2497                 order = 0;
2499         // focus the element so DOM focus won't fire
2500         input[0].focus();
2502         jQuery( "body" ).bind( "focusin.focusinBubblesTest", function(){
2503                 equal( 1, order++, "focusin on the body second" );
2504         });
2506         input.bind( "focusin.focusinBubblesTest", function(){
2507                 equal( 0, order++, "focusin on the element first" );
2508         });
2510 // Removed since DOM focus is unreliable on test swarm
2511         // DOM focus method
2512 //      input[0].focus();
2514         // To make the next focus test work, we need to take focus off the input.
2515         // This will fire another focusin event, so set order to reflect that.
2516 //      order = 1;
2517 //      jQuery("#text1")[0].focus();
2519         // jQuery trigger, which calls DOM focus
2520         order = 0;
2521         input.trigger( "focus" );
2523         input.remove();
2524         jQuery( "body" ).unbind( "focusin.focusinBubblesTest" );
2527 test("custom events with colons (#3533, #8272)", function() {
2528         expect(1);
2530         var tab = jQuery("<table><tr><td>trigger</td></tr></table>").appendTo("body");
2531         try {
2532                 tab.trigger("back:forth");
2533                 ok( true, "colon events don't throw" );
2534         } catch ( e ) {
2535                 ok( false, "colon events die" );
2536         }
2537         tab.remove();
2541 test(".on and .off", function() {
2542         expect(9);
2543         var counter, mixfn;
2545         var $onandoff = jQuery("<div id=\"onandoff\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>").appendTo("body");
2547         // Simple case
2548         jQuery( "#onandoff" )
2549                 .on( "whip", function() {
2550                         ok( true, "whipped it good" );
2551                 })
2552                 .trigger( "whip" )
2553                 .off();
2555         // Direct events only
2556         counter = 0;
2557         jQuery( "#onandoff b" )
2558                 .on( "click", 5, function( e, trig ) {
2559                         counter += e.data + (trig || 9);        // twice, 5+9+5+17=36
2560                 })
2561                 .one( "click", 7, function( e, trig ) {
2562                         counter += e.data + (trig || 11);       // once, 7+11=18
2563                 })
2564                 .click()
2565                 .trigger( "click", 17 )
2566                 .off( "click" );
2567         equal( counter, 54, "direct event bindings with data" );
2569         // Delegated events only
2570         counter = 0;
2571         jQuery( "#onandoff" )
2572                 .on( "click", "em", 5, function( e, trig ) {
2573                         counter += e.data + (trig || 9);        // twice, 5+9+5+17=36
2574                 })
2575                 .one( "click", "em", 7, function( e, trig ) {
2576                         counter += e.data + (trig || 11);       // once, 7+11=18
2577                 })
2578                 .find("em")
2579                         .click()
2580                         .trigger( "click", 17 )
2581                 .end()
2582                 .off( "click", "em" );
2583         equal( counter, 54, "delegated event bindings with data" );
2586         // Mixed event bindings and types
2587         counter = 0;
2588         mixfn = function(e, trig) {
2589                 counter += (e.data || 0) + (trig || 1);
2590         };
2591         jQuery( "#onandoff" )
2592                 .on( "click clack cluck", "em", 2, mixfn )
2593                 .on( "cluck", "b", 7, mixfn )
2594                 .on( "cluck", mixfn )
2595                 .trigger( "what!" )
2596                 .each( function() {
2597                         equal( counter, 0, "nothing triggered yet" );
2598                 })
2599                 .find( "em" )
2600                         .one( "cluck", 3, mixfn )
2601                         .trigger( "cluck", 8 )                  // 3+8 2+8 + 0+8 = 29
2602                         .off()
2603                         .trigger( "cluck", 9 )                  // 2+9 + 0+9 = 20
2604                 .end()
2605                 .each( function() {
2606                         equal( counter, 49, "after triggering em element" );
2607                 })
2608                 .off( "cluck", function(){} )           // shouldn't remove anything
2609                 .trigger( "cluck", 2 )                          // 0+2 = 2
2610                 .each( function() {
2611                         equal( counter, 51, "after triggering #onandoff cluck" );
2612                 })
2613                 .find( "b" )
2614                         .on( "click", 95, mixfn )
2615                         .on( "clack", "p", 97, mixfn )
2616                         .one( "cluck", 3, mixfn )
2617                         .trigger( "quack", 19 )                 // 0
2618                         .off( "click clack cluck" )
2619                 .end()
2620                 .each( function() {
2621                         equal( counter, 51, "after triggering b" );
2622                 })
2623                 .trigger( "cluck", 3 )                          // 0+3 = 3
2624                 .off( "clack", "em", mixfn )
2625                 .find( "em" )
2626                         .trigger( "clack" )                             // 0
2627                 .end()
2628                 .each( function() {
2629                         equal( counter, 54, "final triggers" );
2630                 })
2631                 .off( "click cluck" );
2633         // We should have removed all the event handlers ... kinda hacky way to check this
2634         var data = jQuery.data[ jQuery( "#onandoff" )[0].expando ] || {};
2635         equal( data["events"], undefined, "no events left" );
2637         $onandoff.remove();
2640 test("special bind/delegate name mapping", function() {
2641         expect( 7 );
2643         jQuery.event.special["slap"] = {
2644                 bindType: "click",
2645                 delegateType: "swing",
2646                 handle: function( event ) {
2647                         equal( event.handleObj.origType, "slap", "slapped your mammy, " + event.type );
2648                 }
2649         };
2651         var comeback = function( event ) {
2652                 ok( true, "event " + event.type + " triggered" );
2653         };
2655         jQuery("<div><button id=\"mammy\">Are We Not Men?</button></div>")
2656                 .on( "slap", "button", jQuery.noop )
2657                 .on( "swing", "button", comeback )
2658                 .find( "button" )
2659                         .on( "slap", jQuery.noop )
2660                         .on( "click", comeback )
2661                         .trigger( "click" )             // bindType-slap and click
2662                         .off( "slap" )
2663                         .trigger( "click" )             // click
2664                         .off( "click" )
2665                         .trigger( "swing" )             // delegateType-slap and swing
2666                 .end()
2667                 .off( "slap swing", "button" )
2668                 .find( "button" )                       // everything should be gone
2669                         .trigger( "slap" )
2670                         .trigger( "click" )
2671                         .trigger( "swing" )
2672                 .end()
2673                 .remove();
2674         delete jQuery.event.special["slap"];
2676         jQuery.event.special["gutfeeling"] = {
2677                 bindType: "click",
2678                 delegateType: "click",
2679                 handle: function( event ) {
2680                         equal( event.handleObj.origType, "gutfeeling", "got a gutfeeling" );
2681                         // Need to call the handler since .one() uses it to unbind
2682                         return event.handleObj.handler.call( this , event );
2683                 }
2684         };
2686         // Ensure a special event isn't removed by its mapped type
2687         jQuery( "<p>Gut Feeling</p>" )
2688                 .on( "click", jQuery.noop )
2689                 .on( "gutfeeling", jQuery.noop )
2690                 .off( "click" )
2691                 .trigger( "gutfeeling" )
2692                 .remove();
2694         // Ensure special events are removed when only a namespace is provided
2695         jQuery( "<p>Gut Feeling</p>" )
2696                 .on( "gutfeeling.Devo", jQuery.noop )
2697                 .off( ".Devo" )
2698                 .trigger( "gutfeeling" )
2699                 .remove();
2701         // Ensure .one() events are removed after their maiden voyage
2702         jQuery( "<p>Gut Feeling</p>" )
2703                 .one( "gutfeeling", jQuery.noop )
2704                 .trigger( "gutfeeling" )        // This one should
2705                 .trigger( "gutfeeling" )        // This one should not
2706                 .remove();
2708         delete jQuery.event.special["gutfeeling"];
2711 test(".on and .off, selective mixed removal (#10705)", function() {
2712         expect(7);
2714         var clockout = 0,
2715                 timingx = function( e ) {
2716                         ok( true, "triggered " + e.type );
2717                 };
2719         jQuery( "<p>Strange Pursuit</p>" )
2720                 .on( "click", timingx )
2721                 .on( "click.duty", timingx )
2722                 .on( "click.now", timingx )
2723                 .on( "devo", timingx )
2724                 .on( "future", timingx )
2725                 .trigger( "click" )             // 3
2726                 .trigger( "devo" )              // 1
2727                 .off( ".duty devo " )   // trailing space
2728                 .trigger( "future" )    // 1
2729                 .trigger( "click" )             // 2
2730                 .off( "future click" )
2731                 .trigger( "click" );    // 0
2734 test(".on( event-map, null-selector, data ) #11130", function() {
2736         expect( 1 );
2738         var $p = jQuery("<p>Strange Pursuit</p>"),
2739                 data = "bar",
2740                 map = {
2741                         "foo": function( event ) {
2742                                 equal( event.data, "bar", "event.data correctly relayed with null selector" );
2743                                 $p.remove();
2744                         }
2745                 };
2747         $p.on( map, null, data ).trigger("foo");
2750 test("clone() delegated events (#11076)", function() {
2751         expect(3);
2753         var counter = { "center": 0, "fold": 0, "centerfold": 0 },
2754                 clicked = function( event ) {
2755                         counter[ jQuery(this).text().replace(/\s+/, "") ]++;
2756                 },
2757                 table =
2758                         jQuery( "<table><tr><td>center</td><td>fold</td></tr></table>" )
2759                         .on( "click", "tr", clicked )
2760                         .on( "click", "td:first-child", clicked )
2761                         .on( "click", "td:last-child", clicked ),
2762                 clone = table.clone( true );
2764         clone.find("td").click();
2765         equal( counter["center"], 1, "first child" );
2766         equal( counter["fold"], 1, "last child" );
2767         equal( counter["centerfold"], 2, "all children" );
2769         table.remove();
2770         clone.remove();
2773 test("fixHooks extensions", function() {
2774         expect( 2 );
2776         // IE requires focusable elements to be visible, so append to body
2777         var $fixture = jQuery( "<input type='text' id='hook-fixture' />" ).appendTo( "body" ),
2778                 saved = jQuery.event.fixHooks.click;
2780         // Ensure the property doesn't exist
2781         $fixture.bind( "click", function( event ) {
2782                 ok( !("blurrinessLevel" in event), "event.blurrinessLevel does not exist" );
2783         });
2784         fireNative( $fixture[0], "click" );
2785         $fixture.unbind( "click" );
2787         jQuery.event.fixHooks.click = {
2788                 filter: function( event, originalEvent ) {
2789                         event.blurrinessLevel = 42;
2790                         return event;
2791                 }
2792         };
2794         // Trigger a native click and ensure the property is set
2795         $fixture.bind( "click", function( event ) {
2796                 equal( event.blurrinessLevel, 42, "event.blurrinessLevel was set" );
2797         });
2798         fireNative( $fixture[0], "click" );
2800         delete jQuery.event.fixHooks.click;
2801         $fixture.unbind( "click" ).remove();
2802         jQuery.event.fixHooks.click = saved;
2805 testIframeWithCallback( "jQuery.ready promise", "event/promiseReady.html", function( isOk ) {
2806         expect(1);
2807         ok( isOk, "$.when( $.ready ) works" );
2810 // need PHP here to make the incepted IFRAME hang
2811 if ( hasPHP ) {
2812         testIframeWithCallback( "jQuery.ready synchronous load with long loading subresources", "event/syncReady.html", function( isOk ) {
2813                 expect(1);
2814                 ok( isOk, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
2815         });
2818 (function(){
2819         // This code must be run before DOM ready!
2820         var notYetReady, noEarlyExecution,
2821                 order = [],
2822                 args = {};
2824         notYetReady = !jQuery.isReady;
2826         test("jQuery.isReady", function() {
2827                 expect(2);
2829                 equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready");
2830                 equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready");
2831         });
2833         // Create an event handler.
2834         function makeHandler( testId ) {
2835                 // When returned function is executed, push testId onto `order` array
2836                 // to ensure execution order. Also, store event handler arg to ensure
2837                 // the correct arg is being passed into the event handler.
2838                 return function( arg ) {
2839                         order.push(testId);
2840                         args[testId] = arg;
2841                 };
2842         }
2844         // Bind to the ready event in every possible way.
2845         jQuery(makeHandler("a"));
2846         jQuery(document).ready(makeHandler("b"));
2847         jQuery(document).bind("ready.readytest", makeHandler("c"));
2849         // Do it twice, just to be sure.
2850         jQuery(makeHandler("d"));
2851         jQuery(document).ready(makeHandler("e"));
2852         jQuery(document).bind("ready.readytest", makeHandler("f"));
2854         noEarlyExecution = order.length === 0;
2856         // This assumes that QUnit tests are run on DOM ready!
2857         test("jQuery ready", function() {
2858                 expect(10);
2860                 ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready");
2862                 // Ensure execution order.
2863                 deepEqual(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in bind-order, but those bound with jQuery(document).bind( 'ready', fn ) will always execute last");
2865                 // Ensure handler argument is correct.
2866                 equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
2867                 equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
2868                 ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).bind( 'ready', fn ) should be an event object");
2870                 order = [];
2872                 // Now that the ready event has fired, again bind to the ready event
2873                 // in every possible way. These event handlers should execute immediately.
2874                 jQuery(makeHandler("g"));
2875                 equal(order.pop(), "g", "Event handler should execute immediately");
2876                 equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
2878                 jQuery(document).ready(makeHandler("h"));
2879                 equal(order.pop(), "h", "Event handler should execute immediately");
2880                 equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
2882                 jQuery(document).bind("ready.readytest", makeHandler("never"));
2883                 equal(order.length, 0, "Event handler should never execute since DOM ready has already passed");
2885                 // Cleanup.
2886                 jQuery(document).unbind("ready.readytest");
2887         });
2889 })();
2891 test("change handler should be detached from element", function() {
2892         expect( 2 );
2894         var $fixture = jQuery( "<input type='text' id='change-ie-leak' />" ).appendTo( "body" );
2896         var originRemoveEvent =  jQuery.removeEvent;
2898         var wrapperRemoveEvent =  function(elem, type, handle){
2899                 equal("change", type, "Event handler for 'change' event should be removed");
2900                 equal("change-ie-leak", jQuery(elem).attr("id"), "Event handler for 'change' event should be removed from appropriate element");
2901                 originRemoveEvent(elem, type, handle);
2902         };
2904         jQuery.removeEvent = wrapperRemoveEvent ;
2906         $fixture.bind( "change", function( event ) {});
2907         $fixture.unbind( "change" );
2909         $fixture.remove();
2911         jQuery.removeEvent = originRemoveEvent;
2914 asyncTest("trigger click on checkbox, fires change event", function() {
2915         expect(1);
2917         var check = jQuery("#check2");
2919         check.on( "change", function() {
2920                 // get it?
2921                 check.off("change");
2922                 ok( true, "Change event fired as a result of triggered click" );
2923                 start();
2924         }).trigger("click");