Data: camelCasing should not ignore case
[jquery.git] / test / unit / event.js
blob95f6f4b33aa0edf29329935f7035cf3a4e89c9c8
1 module( "event", {
2         setup: function() {
3                 document.body.focus();
4         },
5         teardown: moduleTeardown
6 });
8 test("on() with non-null,defined data", function() {
10         expect(2);
12         var handler = function( event, data ) {
13                 equal( data, 0, "non-null, defined data (zero) is correctly passed" );
14         };
16         jQuery("#foo").on("foo.on", handler);
17         jQuery("div").on("foo.delegate", "#foo", handler);
19         jQuery("#foo").trigger("foo", 0);
21         jQuery("#foo").off("foo.on", handler);
22         jQuery("div").off("foo.delegate", "#foo");
24 });
26 test("Handler changes and .trigger() order", function() {
27         expect(1);
29         var markup = jQuery(
30                 "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
31         ),
32         path = "";
34         markup
35                 .find( "*" ).addBack().on( "click", function() {
36                         path += this.nodeName.toLowerCase() + " ";
37                 })
38                 .filter( "b" ).on( "click", function( e ) {
39                         // Removing span should not stop propagation to original parents
40                         if ( e.target === this ) {
41                                 jQuery(this).parent().remove();
42                         }
43                 });
45         markup.find( "b" ).trigger( "click" );
47         equal( path, "b p div div ", "Delivered all events" );
49         markup.remove();
50 });
52 test("on(), with data", function() {
53         expect(4);
54         var test, handler, handler2;
56         handler = function(event) {
57                 ok( event.data, "on() with data, check passed data exists" );
58                 equal( event.data["foo"], "bar", "on() with data, Check value of passed data" );
59         };
60         jQuery("#firstp").on("click", {"foo": "bar"}, handler).trigger("click").off("click", handler);
62         ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
64         test = function(){};
65         handler2 = function(event) {
66                 equal( event.data, test, "on() with function data, Check value of passed data" );
67         };
68         jQuery("#firstp").on("click", test, handler2).trigger("click").off("click", handler2);
69 });
71 test("click(), with data", function() {
72         expect(3);
73         var handler = function(event) {
74                 ok( event.data, "on() with data, check passed data exists" );
75                 equal( event.data["foo"], "bar", "on() with data, Check value of passed data" );
76         };
77         jQuery("#firstp").on( "click", {"foo": "bar"}, handler).trigger("click").off("click", handler);
79         ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
80 });
82 test("on(), with data, trigger with data", function() {
83         expect(4);
84         var handler = function(event, data) {
85                 ok( event.data, "check passed data exists" );
86                 equal( event.data.foo, "bar", "Check value of passed data" );
87                 ok( data, "Check trigger data" );
88                 equal( data.bar, "foo", "Check value of trigger data" );
89         };
90         jQuery("#firstp").on("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]).off("click", handler);
91 });
93 test("on(), multiple events at once", function() {
94         expect(2);
95         var handler,
96                 clickCounter = 0,
97                 mouseoverCounter = 0;
98         handler = function(event) {
99                 if (event.type === "click") {
100                         clickCounter += 1;
101                 }
102                 else if (event.type === "mouseover") {
103                         mouseoverCounter += 1;
104                 }
105         };
107         jQuery("#firstp").on("click mouseover", handler).trigger("click").trigger("mouseover");
108         equal( clickCounter, 1, "on() with multiple events at once" );
109         equal( mouseoverCounter, 1, "on() with multiple events at once" );
112 test("on(), five events at once", function() {
113         expect(1);
115         var count = 0,
116                 handler = function() {
117                         count++;
118                 };
120         jQuery("#firstp").on("click mouseover foo bar baz", handler)
121         .trigger("click").trigger("mouseover")
122                 .trigger("foo").trigger("bar")
123                 .trigger("baz");
125         equal( count, 5, "on() five events at once" );
128 test("on(), multiple events at once and namespaces", function() {
129         expect(7);
131         var cur, div,
132                 obj = {};
134         div = jQuery("<div/>").on("focusin.a", function(e) {
135                 equal( e.type, cur, "Verify right single event was fired." );
136         });
138         cur = "focusin";
139         div.trigger("focusin.a");
141         // manually clean up detached elements
142         div.remove();
144         div = jQuery("<div/>").on("click mouseover", obj, function(e) {
145                 equal( e.type, cur, "Verify right multi event was fired." );
146                 equal( e.data, obj, "Make sure the data came in correctly." );
147         });
149         cur = "click";
150         div.trigger("click");
152         cur = "mouseover";
153         div.trigger("mouseover");
155         // manually clean up detached elements
156         div.remove();
158         div = jQuery("<div/>").on("focusin.a focusout.b", function(e) {
159                 equal( e.type, cur, "Verify right multi event was fired." );
160         });
162         cur = "focusin";
163         div.trigger("focusin.a");
165         cur = "focusout";
166         div.trigger("focusout.b");
168         // manually clean up detached elements
169         div.remove();
172 test("on(), namespace with special add", function() {
173         expect(27);
175         var i = 0,
176                 div = jQuery("<div/>").appendTo("#qunit-fixture").on( "test", function() {
177                         ok( true, "Test event fired." );
178                 });
180         jQuery.event.special["test"] = {
181                 _default: function( e, data ) {
182                         equal( e.type, "test", "Make sure we're dealing with a test event." );
183                         ok( data, "And that trigger data was passed." );
184                         strictEqual( e.target, div[0], "And that the target is correct." );
185                         equal( this, window, "And that the context is correct." );
186                 },
187                 setup: function() {},
188                 teardown: function() {
189                         ok( true, "Teardown called." );
190                 },
191                 add: function( handleObj ) {
192                         var handler = handleObj.handler;
193                         handleObj.handler = function( e ) {
194                                 e.xyz = ++i;
195                                 handler.apply( this, arguments );
196                         };
197                 },
198                 remove: function() {
199                         ok( true, "Remove called." );
200                 }
201         };
203         div.on( "test.a", { x: 1 }, function( e ) {
204                 ok( !!e.xyz, "Make sure that the data is getting passed through." );
205                 equal( e.data["x"], 1, "Make sure data is attached properly." );
206         });
208         div.on( "test.b", { x: 2 }, function( e ) {
209                 ok( !!e.xyz, "Make sure that the data is getting passed through." );
210                 equal( e.data["x"], 2, "Make sure data is attached properly." );
211         });
213         // Should trigger 5
214         div.trigger( "test", 33.33 );
216         // Should trigger 2
217         div.trigger( "test.a", "George Harrison" );
219         // Should trigger 2
220         div.trigger( "test.b", { year: 1982 } );
222         // Should trigger 4
223         div.off("test");
225         div = jQuery("<div/>").on( "test", function() {
226                 ok( true, "Test event fired." );
227         });
229         // Should trigger 2
230         div.appendTo("#qunit-fixture").remove();
232         delete jQuery.event.special["test"];
235 test("on(), no data", function() {
236         expect(1);
237         var handler = function(event) {
238                 ok ( !event.data, "Check that no data is added to the event object" );
239         };
240         jQuery("#firstp").on("click", handler).trigger("click");
243 test("on/one/off(Object)", function(){
244         expect(6);
246         var $elem,
247                 clickCounter = 0,
248                 mouseoverCounter = 0;
250         function handler(event) {
251                 if (event.type === "click") {
252                         clickCounter++;
253                 } else if (event.type === "mouseover") {
254                         mouseoverCounter++;
255                 }
256         }
258         function handlerWithData(event) {
259                 if (event.type === "click") {
260                         clickCounter += event.data;
261                 } else if (event.type === "mouseover") {
262                         mouseoverCounter += event.data;
263                 }
264         }
266         function trigger(){
267                 $elem.trigger("click").trigger("mouseover");
268         }
270         $elem = jQuery("#firstp")
271                 // Regular bind
272                 .on({
273                         "click":handler,
274                         "mouseover":handler
275                 })
276                 // Bind with data
277                 .one({
278                         "click":handlerWithData,
279                         "mouseover":handlerWithData
280                 }, 2 );
282         trigger();
284         equal( clickCounter, 3, "on(Object)" );
285         equal( mouseoverCounter, 3, "on(Object)" );
287         trigger();
288         equal( clickCounter, 4, "on(Object)" );
289         equal( mouseoverCounter, 4, "on(Object)" );
291         jQuery("#firstp").off({
292                 "click":handler,
293                 "mouseover":handler
294         });
296         trigger();
297         equal( clickCounter, 4, "on(Object)" );
298         equal( mouseoverCounter, 4, "on(Object)" );
301 test("on/off(Object), on/off(Object, String)", function() {
302         expect(6);
304         var events,
305                 clickCounter = 0,
306                 mouseoverCounter = 0,
307                 $p = jQuery("#firstp"),
308                 $a = $p.find("a").eq(0);
310         events = {
311                 "click": function( event ) {
312                         clickCounter += ( event.data || 1 );
313                 },
314                 "mouseover": function( event ) {
315                         mouseoverCounter += ( event.data || 1 );
316                 }
317         };
319         function trigger() {
320                 $a.trigger("click").trigger("mouseover");
321         }
323         jQuery( document ).on( events, "#firstp a" );
324         $p.on( events, "a", 2 );
326         trigger();
327         equal( clickCounter, 3, "on" );
328         equal( mouseoverCounter, 3, "on" );
330         $p.off( events, "a" );
332         trigger();
333         equal( clickCounter, 4, "off" );
334         equal( mouseoverCounter, 4, "off" );
336         jQuery( document ).off( events, "#firstp a" );
338         trigger();
339         equal( clickCounter, 4, "off" );
340         equal( mouseoverCounter, 4, "off" );
343 test("on immediate propagation", function() {
344         expect(2);
346         var lastClick,
347                 $p = jQuery("#firstp"),
348                 $a = $p.find("a").eq(0);
350         lastClick = "";
351         jQuery( document ).on( "click", "#firstp a", function(e) {
352                 lastClick = "click1";
353                 e.stopImmediatePropagation();
354         });
355         jQuery( document ).on( "click", "#firstp a", function() {
356                 lastClick = "click2";
357         });
358         $a.trigger( "click" );
359         equal( lastClick, "click1", "on stopImmediatePropagation" );
360         jQuery( document ).off( "click", "#firstp a" );
362         lastClick = "";
363         $p.on( "click", "a", function(e) {
364                 lastClick = "click1";
365                 e.stopImmediatePropagation();
366         });
367         $p.on( "click", "a", function() {
368                 lastClick = "click2";
369         });
370         $a.trigger( "click" );
371         equal( lastClick, "click1", "on stopImmediatePropagation" );
372         $p.off( "click", "**" );
375 test("on bubbling, isDefaultPrevented, stopImmediatePropagation", function() {
376         expect( 3 );
378         var $anchor2 = jQuery( "#anchor2" ),
379                 $main = jQuery( "#qunit-fixture" ),
380                 neverCallMe = function() {
381                         ok( false, "immediate propagation should have been stopped" );
382                 },
383                 fakeClick = function($jq) {
384                         // Use a native click so we don't get jQuery simulated bubbling
385                         var e = document.createEvent( "MouseEvents" );
386                         e.initEvent( "click", true, true );
387                         $jq[ 0 ].dispatchEvent( e );
388                 };
389         $anchor2.on( "click", function(e) {
390                 e.preventDefault();
391         });
392         $main.on( "click", "#foo", function( e ) {
393                 equal( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
394         });
395         fakeClick( $anchor2 );
396         $anchor2.off( "click" );
397         $main.off( "click", "**" );
398         $anchor2.on( "click", function() {
399                 // Let the default action occur
400         });
401         $main.on("click", "#foo", function(e) {
402                 equal( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
403         });
404         fakeClick( $anchor2 );
405         $anchor2.off( "click" );
406         $main.off( "click", "**" );
408         // Android 2.3 doesn't support stopImmediatePropagation; jQuery fallbacks to stopPropagation
409         // in such a case.
410         // Support: Android 2.3
411         if ( /android 2\.3/i.test( navigator.userAgent ) ) {
412                 ok( true, "Android 2.3, skipping native stopImmediatePropagation check" );
413         } else {
414                 $anchor2.on( "click", function( e ) {
415                         e.stopImmediatePropagation();
416                         ok( true, "anchor was clicked and prop stopped" );
417                 });
418                 $anchor2[0].addEventListener( "click", neverCallMe, false );
419                 fakeClick( $anchor2 );
420                 $anchor2[0].removeEventListener( "click", neverCallMe );
421         }
424 test("on(), iframes", function() {
425         expect( 1 );
427         // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
428         var doc = jQuery("#loadediframe").contents();
430         jQuery("div", doc).on("click", function() {
431                 ok( true, "Binding to element inside iframe" );
432         }).trigger("click").off("click");
435 test("on(), trigger change on select", function() {
436         expect(5);
437         var counter = 0;
438         function selectOnChange(event) {
439                 equal( event.data, counter++, "Event.data is not a global event object" );
440         }
441         jQuery("#form select").each(function(i){
442                 jQuery(this).on("change", i, selectOnChange);
443         }).trigger("change");
446 test("on(), namespaced events, cloned events", 18, function() {
447         var firstp = jQuery( "#firstp" );
449         firstp.on("custom.test",function(){
450                 ok(false, "Custom event triggered");
451         });
453         firstp.on("click",function(e){
454                 ok(true, "Normal click triggered");
455                 equal( e.type + e.namespace, "click", "Check that only click events trigger this fn" );
456         });
458         firstp.on("click.test",function(e){
459                 var check = "click";
460                 ok( true, "Namespaced click triggered" );
461                 if ( e.namespace ) {
462                         check += "test";
463                 }
464                 equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
465         });
467         //clone(true) element to verify events are cloned correctly
468         firstp = firstp.add( firstp.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp ) );
470         // Trigger both bound fn (8)
471         firstp.trigger("click");
473         // Trigger one bound fn (4)
474         firstp.trigger("click.test");
476         // Remove only the one fn
477         firstp.off("click.test");
479         // Trigger the remaining fn (4)
480         firstp.trigger("click");
482         // Remove the remaining namespaced fn
483         firstp.off(".test");
485         // Try triggering the custom event (0)
486         firstp.trigger("custom");
488         // using contents will get comments regular, text, and comment nodes
489         jQuery("#nonnodes").contents().on("tester", function () {
490                 equal(this.nodeType, 1, "Check node,textnode,comment on just does real nodes" );
491         }).trigger("tester");
493         // Make sure events stick with appendTo'd elements (which are cloned) #2027
494         jQuery("<a href='#fail' class='test'>test</a>").on( "click", function(){ return false; }).appendTo("#qunit-fixture");
495         ok( jQuery("a.test").eq(0).triggerHandler("click") === false, "Handler is bound to appendTo'd elements" );
498 test("on(), multi-namespaced events", function() {
499         expect(6);
501         var order = [
502                 "click.test.abc",
503                 "click.test.abc",
504                 "click.test",
505                 "click.test.abc",
506                 "click.test",
507                 "custom.test2"
508         ];
510         function check(name, msg){
511                 deepEqual( name, order.shift(), msg );
512         }
514         jQuery("#firstp").on("custom.test",function() {
515                 check("custom.test", "Custom event triggered");
516         });
518         jQuery("#firstp").on("custom.test2",function() {
519                 check("custom.test2", "Custom event triggered");
520         });
522         jQuery("#firstp").on("click.test",function() {
523                 check("click.test", "Normal click triggered");
524         });
526         jQuery("#firstp").on("click.test.abc",function() {
527                 check("click.test.abc", "Namespaced click triggered");
528         });
530         // Those would not trigger/off (#5303)
531         jQuery("#firstp").trigger("click.a.test");
532         jQuery("#firstp").off("click.a.test");
534         // Trigger both bound fn (1)
535         jQuery("#firstp").trigger("click.test.abc");
537         // Trigger one bound fn (1)
538         jQuery("#firstp").trigger("click.abc");
540         // Trigger two bound fn (2)
541         jQuery("#firstp").trigger("click.test");
543         // Remove only the one fn
544         jQuery("#firstp").off("click.abc");
546         // Trigger the remaining fn (1)
547         jQuery("#firstp").trigger("click");
549         // Remove the remaining fn
550         jQuery("#firstp").off(".test");
552         // Trigger the remaining fn (1)
553         jQuery("#firstp").trigger("custom");
556 test("namespace-only event binding is a no-op", function(){
557         expect(2);
559         jQuery("#firstp")
560                 .on( ".whoops", function() {
561                         ok( false, "called a namespace-only event" );
562                 })
563                 .on( "whoops", function() {
564                         ok( true, "called whoops" );
565                 })
566                 .trigger("whoops")      // 1
567                 .off(".whoops")
568                 .trigger("whoops")      // 2
569                 .off("whoops");
572 test("Empty namespace is ignored", function(){
573         expect( 1 );
575         jQuery("#firstp")
576                 .on( "meow.", function( e ) {
577                         equal( e.namespace, "", "triggered a namespace-less meow event" );
578                 })
579                 .trigger("meow.")
580                 .off("meow.");
583 test("on(), with same function", function() {
584         expect(2);
586         var count = 0, func = function(){
587                 count++;
588         };
590         jQuery("#liveHandlerOrder").on("foo.bar", func).on("foo.zar", func);
591         jQuery("#liveHandlerOrder").trigger("foo.bar");
593         equal(count, 1, "Verify binding function with multiple namespaces." );
595         jQuery("#liveHandlerOrder").off("foo.bar", func).off("foo.zar", func);
596         jQuery("#liveHandlerOrder").trigger("foo.bar");
598         equal(count, 1, "Verify that removing events still work." );
601 test("on(), make sure order is maintained", function() {
602         expect(1);
604         var elem = jQuery("#firstp"), log = [], check = [];
606         jQuery.each( new Array(100), function( i ) {
607                 elem.on( "click", function(){
608                         log.push( i );
609                 });
611                 check.push( i );
613         });
615         elem.trigger("click");
617         equal( log.join(","), check.join(","), "Make sure order was maintained." );
619         elem.off("click");
622 test("on(), with different this object", function() {
623         expect(4);
624         var thisObject = { myThis: true },
625                 data = { myData: true },
626                 handler1 = function() {
627                         equal( this, thisObject, "on() with different this object" );
628                 },
629                 handler2 = function( event ) {
630                         equal( this, thisObject, "on() with different this object and data" );
631                         equal( event.data, data, "on() with different this object and data" );
632                 };
634         jQuery("#firstp")
635                 .on("click", jQuery.proxy(handler1, thisObject)).trigger("click").off("click", handler1)
636                 .on("click", data, jQuery.proxy(handler2, thisObject)).trigger("click").off("click", handler2);
638         ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
641 test("on(name, false), off(name, false)", function() {
642         expect(3);
644         var main = 0;
645         jQuery("#qunit-fixture").on("click", function(){ main++; });
646         jQuery("#ap").trigger("click");
647         equal( main, 1, "Verify that the trigger happened correctly." );
649         main = 0;
650         jQuery("#ap").on("click", false);
651         jQuery("#ap").trigger("click");
652         equal( main, 0, "Verify that no bubble happened." );
654         main = 0;
655         jQuery("#ap").off("click", false);
656         jQuery("#ap").trigger("click");
657         equal( main, 1, "Verify that the trigger happened correctly." );
659         // manually clean up events from elements outside the fixture
660         jQuery("#qunit-fixture").off("click");
663 test("on(name, selector, false), off(name, selector, false)", function() {
664         expect(3);
666         var main = 0;
668         jQuery("#qunit-fixture").on("click", "#ap", function(){ main++; });
669         jQuery("#ap").trigger("click");
670         equal( main, 1, "Verify that the trigger happened correctly." );
672         main = 0;
673         jQuery("#ap").on("click", "#groups", false);
674         jQuery("#groups").trigger("click");
675         equal( main, 0, "Verify that no bubble happened." );
677         main = 0;
678         jQuery("#ap").off("click", "#groups", false);
679         jQuery("#groups").trigger("click");
680         equal( main, 1, "Verify that the trigger happened correctly." );
681         jQuery("#qunit-fixture").off("click", "#ap");
684 test("on()/trigger()/off() on plain object", function() {
685         expect( 7 );
687         var events,
688                 obj = {};
690         // Make sure it doesn't complain when no events are found
691         jQuery(obj).trigger("test");
693         // Make sure it doesn't complain when no events are found
694         jQuery(obj).off("test");
696         jQuery(obj).on({
697                 "test": function() {
698                         ok( true, "Custom event run." );
699                 },
700                 "submit": function() {
701                         ok( true, "Custom submit event run." );
702                 }
703         });
705         events = jQuery._data(obj, "events");
706         ok( events, "Object has events bound." );
707         equal( obj["events"], undefined, "Events object on plain objects is not events" );
708         equal( obj["test"], undefined, "Make sure that test event is not on the plain object." );
709         equal( obj["handle"], undefined, "Make sure that the event handler is not on the plain object." );
711         // Should trigger 1
712         jQuery(obj).trigger("test");
713         jQuery(obj).trigger("submit");
715         jQuery(obj).off("test");
716         jQuery(obj).off("submit");
718         // Should trigger 0
719         jQuery(obj).trigger("test");
721         // Make sure it doesn't complain when no events are found
722         jQuery(obj).off("test");
724         equal( obj && obj[ jQuery.expando ] &&
725                         obj[ jQuery.expando ][ jQuery.expando ] &&
726                         obj[ jQuery.expando ][ jQuery.expando ]["events"], undefined, "Make sure events object is removed" );
729 test("off(type)", function() {
730         expect( 1 );
732         var message, func,
733                 $elem = jQuery("#firstp");
735         function error(){
736                 ok( false, message );
737         }
739         message = "unbind passing function";
740         $elem.on("error1", error).off("error1", error).triggerHandler("error1");
742         message = "unbind all from event";
743         $elem.on("error1", error).off("error1").triggerHandler("error1");
745         message = "unbind all";
746         $elem.on("error1", error).off().triggerHandler("error1");
748         message = "unbind many with function";
749         $elem.on("error1 error2",error)
750                 .off("error1 error2", error )
751                 .trigger("error1").triggerHandler("error2");
753         message = "unbind many"; // #3538
754         $elem.on("error1 error2", error)
755                 .off("error1 error2")
756                 .trigger("error1").triggerHandler("error2");
758         message = "unbind without a type or handler";
759         $elem.on("error1 error2.test",error)
760                 .off()
761                 .trigger("error1").triggerHandler("error2");
763         // Should only unbind the specified function
764         jQuery( document ).on( "click", function(){
765                 ok( true, "called handler after selective removal");
766         });
767         func = function() {};
768         jQuery( document )
769                 .on( "click", func )
770                 .off( "click", func )
771                 .trigger("click")
772                 .off( "click" );
775 test("off(eventObject)", function() {
776         expect(4);
778         var $elem = jQuery("#firstp"),
779                 num;
781         function assert( expected ){
782                 num = 0;
783                 $elem.trigger("foo").triggerHandler("bar");
784                 equal( num, expected, "Check the right handlers are triggered" );
785         }
787         $elem
788                 // This handler shouldn't be unbound
789                 .on("foo", function(){
790                         num += 1;
791                 })
792                 .on("foo", function(e){
793                         $elem.off( e );
794                         num += 2;
795                 })
796                 // Neither this one
797                 .on("bar", function(){
798                         num += 4;
799                 });
801         assert( 7 );
802         assert( 5 );
804         $elem.off("bar");
805         assert( 1 );
807         $elem.off();
808         assert( 0 );
811 if ( jQuery.fn.hover ) {
812         test("hover() mouseenter mouseleave", function() {
813                 expect(1);
815                 var times = 0,
816                         handler1 = function() { ++times; },
817                         handler2 = function() { ++times; };
819                 jQuery("#firstp")
820                         .hover(handler1, handler2)
821                         .mouseenter().mouseleave()
822                         .off("mouseenter", handler1)
823                         .off("mouseleave", handler2)
824                         .hover(handler1)
825                         .mouseenter().mouseleave()
826                         .off("mouseenter mouseleave", handler1)
827                         .mouseenter().mouseleave();
829                 equal( times, 4, "hover handlers fired" );
831         });
834 test("mouseover triggers mouseenter", function() {
835         expect(1);
837         var count = 0,
838                 elem = jQuery("<a />");
839         elem.on( "mouseenter", function () {
840                 count++;
841         });
842         elem.trigger("mouseover");
843         equal(count, 1, "make sure mouseover triggers a mouseenter" );
845         elem.remove();
848 test("pointerover triggers pointerenter", function() {
849         expect(1);
851         var count = 0,
852                 elem = jQuery("<a />");
853         elem.on( "pointerenter", function () {
854                 count++;
855         });
856         elem.trigger("pointerover");
857         equal(count, 1, "make sure pointerover triggers a pointerenter" );
859         elem.remove();
862 test("withinElement implemented with jQuery.contains()", function() {
864         expect(1);
866         jQuery("#qunit-fixture").append("<div id='jc-outer'><div id='jc-inner'></div></div>");
868         jQuery("#jc-outer").on("mouseenter mouseleave", function( event ) {
870                 equal( this.id, "jc-outer", this.id + " " + event.type );
872         }).trigger("mouseenter");
874         jQuery("#jc-inner").trigger("mousenter");
876         jQuery("#jc-outer").off("mouseenter mouseleave").remove();
877         jQuery("#jc-inner").remove();
881 test("mouseenter, mouseleave don't catch exceptions", function() {
882         expect(2);
884         var elem = jQuery("#firstp").on( "mouseenter mouseleave", function() {
885                         throw "an Exception";
886                 });
888         try {
889                 elem.trigger("mouseenter");
890         } catch (e) {
891                 equal( e, "an Exception", "mouseenter doesn't catch exceptions" );
892         }
894         try {
895                 elem.trigger("mouseleave");
896         } catch (e) {
897                 equal( e, "an Exception", "mouseleave doesn't catch exceptions" );
898         }
901 if ( jQuery.fn.click ) {
903         test("trigger() shortcuts", function() {
904                 expect(6);
906                 var counter, clickCounter,
907                         elem = jQuery("<li><a href='#'>Change location</a></li>").prependTo("#firstUL");
908                 elem.find("a").on("click", function() {
909                         var close = jQuery("spanx", this); // same with jQuery(this).find("span");
910                         equal( close.length, 0, "Context element does not exist, length must be zero" );
911                         ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
912                         return false;
913                 }).click();
915                 // manually clean up detached elements
916                 elem.remove();
918                 jQuery("#check1").click(function() {
919                         ok( true, "click event handler for checkbox gets fired twice, see #815" );
920                 }).click();
922                 counter = 0;
923                 jQuery("#firstp")[0].onclick = function() {
924                         counter++;
925                 };
926                 jQuery("#firstp").click();
927                 equal( counter, 1, "Check that click, triggers onclick event handler also" );
929                 clickCounter = 0;
930                 jQuery("#simon1")[0].onclick = function() {
931                         clickCounter++;
932                 };
933                 jQuery("#simon1").click();
934                 equal( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
936                 elem = jQuery("<img />").load(function(){
937                         ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
938                 }).load();
940                 // manually clean up detached elements
941                 elem.remove();
943                 // test that special handlers do not blow up with VML elements (#7071)
944                 jQuery("<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />").appendTo("head");
945                 jQuery("<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>").appendTo("#form");
946                 jQuery("#oval").click().keydown();
947         });
951 test("trigger() bubbling", function() {
952         expect(18);
954         var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
956         jQuery(window).on("click", function(){ win++; });
957         jQuery(document).on("click", function( e ){ if ( e.target !== document) { doc++; } });
958         jQuery("html").on("click", function(){ html++; });
959         jQuery("body").on("click", function(){ body++; });
960         jQuery("#qunit-fixture").on("click", function(){ main++; });
961         jQuery("#ap").on("click", function(){ ap++; return false; });
963         jQuery("html").trigger("click");
964         equal( win, 1, "HTML bubble" );
965         equal( doc, 1, "HTML bubble" );
966         equal( html, 1, "HTML bubble" );
968         jQuery("body").trigger("click");
969         equal( win, 2, "Body bubble" );
970         equal( doc, 2, "Body bubble" );
971         equal( html, 2, "Body bubble" );
972         equal( body, 1, "Body bubble" );
974         jQuery("#qunit-fixture").trigger("click");
975         equal( win, 3, "Main bubble" );
976         equal( doc, 3, "Main bubble" );
977         equal( html, 3, "Main bubble" );
978         equal( body, 2, "Main bubble" );
979         equal( main, 1, "Main bubble" );
981         jQuery("#ap").trigger("click");
982         equal( doc, 3, "ap bubble" );
983         equal( html, 3, "ap bubble" );
984         equal( body, 2, "ap bubble" );
985         equal( main, 1, "ap bubble" );
986         equal( ap, 1, "ap bubble" );
988         jQuery( document ).trigger("click");
989         equal( win, 4, "doc bubble" );
991         // manually clean up events from elements outside the fixture
992         jQuery(window).off("click");
993         jQuery(document).off("click");
994         jQuery("html, body, #qunit-fixture").off("click");
997 test("trigger(type, [data], [fn])", function() {
998         expect(16);
1000         var $elem, pass, form, elem2,
1001                 handler = function(event, a, b, c) {
1002                 equal( event.type, "click", "check passed data" );
1003                 equal( a, 1, "check passed data" );
1004                 equal( b, "2", "check passed data" );
1005                 equal( c, "abc", "check passed data" );
1006                 return "test";
1007         };
1009         $elem = jQuery("#firstp");
1011         // Simulate a "native" click
1012         $elem[0].click = function(){
1013                 ok( true, "Native call was triggered" );
1014         };
1017         jQuery( document ).on("mouseenter", "#firstp", function(){
1018                 ok( true, "Trigger mouseenter bound by on" );
1019         });
1021         jQuery( document ).on("mouseleave", "#firstp", function(){
1022                 ok( true, "Trigger mouseleave bound by on" );
1023         });
1025         $elem.trigger("mouseenter");
1027         $elem.trigger("mouseleave");
1029         jQuery( document ).off( "mouseenter mouseleave", "#firstp");
1031         // Triggers handlers and native
1032         // Trigger 5
1033         $elem.on("click", handler).trigger("click", [1, "2", "abc"]);
1035         // Simulate a "native" click
1036         $elem[0].click = function(){
1037                 ok( false, "Native call was triggered" );
1038         };
1040         // Trigger only the handlers (no native)
1041         // Triggers 5
1042         equal( $elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
1044         pass = true;
1045         try {
1046                 elem2 = jQuery("#form input").eq(0);
1047                 elem2.get(0).style.display = "none";
1048                 elem2.trigger("focus");
1049         } catch( e ) {
1050                 pass = false;
1051         }
1052         ok( pass, "Trigger focus on hidden element" );
1054         pass = true;
1055         try {
1056                 jQuery("#qunit-fixture table").eq(0).on("test:test", function(){}).trigger("test:test");
1057         } catch ( e ) {
1058                 pass = false;
1059         }
1060         ok( pass, "Trigger on a table with a colon in the even type, see #3533" );
1062         form = jQuery("<form action=''></form>").appendTo("body");
1064         // Make sure it can be prevented locally
1065         form.on( "submit", function(){
1066                 ok( true, "Local `on` still works." );
1067                 return false;
1068         });
1070         // Trigger 1
1071         form.trigger("submit");
1073         form.off("submit");
1075         jQuery(document).on( "submit", function(){
1076                 ok( true, "Make sure bubble works up to document." );
1077                 return false;
1078         });
1080         // Trigger 1
1081         form.trigger("submit");
1083         jQuery(document).off("submit");
1085         form.remove();
1088 test( "submit event bubbles on copied forms (#11649)", function() {
1089         expect( 3 );
1091         var $formByClone, $formByHTML,
1092                 $testForm = jQuery("#testForm"),
1093                 $fixture = jQuery("#qunit-fixture"),
1094                 $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
1096         function noSubmit( e ) {
1097                 e.preventDefault();
1098         }
1099         function delegatedSubmit() {
1100                 ok( true, "Make sure submit event bubbles up." );
1101                 return false;
1102         }
1104         // Attach a delegated submit handler to the parent element
1105         $fixture.on( "submit", "form", delegatedSubmit );
1107         // Trigger form submission to introduce the _submit_attached property
1108         $testForm.on( "submit", noSubmit ).find("input[name=sub1]").trigger("click");
1110         // Copy the form via .clone() and .html()
1111         $formByClone = $testForm.clone( true, true ).removeAttr("id");
1112         $formByHTML = jQuery( jQuery.parseHTML($fixture.html()) ).filter("#testForm").removeAttr("id");
1113         $wrapperDiv.append( $formByClone, $formByHTML );
1115         // Check submit bubbling on the copied forms
1116         $wrapperDiv.find("form").on( "submit", noSubmit ).find("input[name=sub1]").trigger("click");
1118         // Clean up
1119         $wrapperDiv.remove();
1120         $fixture.off( "submit", "form", delegatedSubmit );
1121         $testForm.off( "submit", noSubmit );
1124 test( "change event bubbles on copied forms (#11796)", function(){
1125         expect( 3 );
1127         var $formByClone, $formByHTML,
1128                 $form = jQuery("#form"),
1129                 $fixture = jQuery("#qunit-fixture"),
1130                 $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
1132         function delegatedChange() {
1133                 ok( true, "Make sure change event bubbles up." );
1134                 return false;
1135         }
1137         // Attach a delegated change handler to the form
1138         $fixture.on( "change", "form", delegatedChange );
1140         // Trigger change event to introduce the _change_attached property
1141         $form.find("select[name=select1]").val("1").trigger("change");
1143         // Copy the form via .clone() and .html()
1144         $formByClone = $form.clone( true, true ).removeAttr("id");
1145         $formByHTML = jQuery( jQuery.parseHTML($fixture.html()) ).filter("#form").removeAttr("id");
1146         $wrapperDiv.append( $formByClone, $formByHTML );
1148         // Check change bubbling on the copied forms
1149         $wrapperDiv.find("form select[name=select1]").val("2").trigger("change");
1151         // Clean up
1152         $wrapperDiv.remove();
1153         $fixture.off( "change", "form", delegatedChange );
1156 test("trigger(eventObject, [data], [fn])", function() {
1157         expect(28);
1159         var event,
1160                 $parent = jQuery("<div id='par' />").appendTo("body"),
1161                 $child = jQuery("<p id='child'>foo</p>").appendTo( $parent );
1163         $parent.get( 0 ).style.display = "none";
1165         event = jQuery.Event("noNew");
1166         ok( event !== window, "Instantiate jQuery.Event without the 'new' keyword" );
1167         equal( event.type, "noNew", "Verify its type" );
1169         equal( event.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1170         equal( event.isPropagationStopped(), false, "Verify isPropagationStopped" );
1171         equal( event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1173         event.preventDefault();
1174         equal( event.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
1175         event.stopPropagation();
1176         equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
1178         event.isPropagationStopped = function(){ return false; };
1179         event.stopImmediatePropagation();
1180         equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
1181         equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
1183         $parent.on("foo",function( e ) {
1184                 // Tries bubbling
1185                 equal( e.type, "foo", "Verify event type when passed passing an event object" );
1186                 equal( e.target.id, "child", "Verify event.target when passed passing an event object" );
1187                 equal( e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object" );
1188                 equal( e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object" );
1189         });
1191         // test with an event object
1192         event = new jQuery.Event("foo");
1193         event.secret = "boo!";
1194         $child.trigger(event);
1196         // test with a literal object
1197         $child.trigger({"type": "foo", "secret": "boo!"});
1199         $parent.off();
1201         function error(){
1202                 ok( false, "This assertion shouldn't be reached");
1203         }
1205         $parent.on("foo", error );
1207         $child.on("foo",function(e, a, b, c ){
1208                 equal( arguments.length, 4, "Check arguments length");
1209                 equal( a, 1, "Check first custom argument");
1210                 equal( b, 2, "Check second custom argument");
1211                 equal( c, 3, "Check third custom argument");
1213                 equal( e.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1214                 equal( e.isPropagationStopped(), false, "Verify isPropagationStopped" );
1215                 equal( e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1217                 // Skips both errors
1218                 e.stopImmediatePropagation();
1220                 return "result";
1221         });
1223         // We should add this back in when we want to test the order
1224         // in which event handlers are iterated.
1225         //$child.on("foo", error );
1227         event = new jQuery.Event("foo");
1228         $child.trigger( event, [1,2,3] ).off();
1229         equal( event.result, "result", "Check event.result attribute");
1231         // Will error if it bubbles
1232         $child.triggerHandler("foo");
1234         $child.off();
1235         $parent.off().remove();
1237         // Ensure triggerHandler doesn't molest its event object (#xxx)
1238         event = jQuery.Event( "zowie" );
1239         jQuery( document ).triggerHandler( event );
1240         equal( event.type, "zowie", "Verify its type" );
1241         equal( event.isPropagationStopped(), false, "propagation not stopped" );
1242         equal( event.isDefaultPrevented(), false, "default not prevented" );
1245 test(".trigger() bubbling on disconnected elements (#10489)", function() {
1246         expect(2);
1248         jQuery( window ).on( "click", function(){
1249                 ok( false, "click fired on window" );
1250         });
1252         jQuery( "<div><p>hi</p></div>" )
1253                 .on( "click", function() {
1254                         ok( true, "click fired on div" );
1255                 })
1256                 .find( "p" )
1257                         .on( "click", function() {
1258                                 ok( true, "click fired on p" );
1259                         })
1260                         .trigger("click")
1261                         .off( "click" )
1262                 .end()
1263                 .off( "click" )
1264                 .remove();
1266         jQuery( window ).off( "click" );
1269 test(".trigger() doesn't bubble load event (#10717)", function() {
1270         expect(1);
1272         jQuery( window ).on( "load", function(){
1273                 ok( false, "load fired on window" );
1274         });
1276         // It's not an image, but as long as it fires load...
1277         jQuery("<img src='index.html' />")
1278                 .appendTo( "body" )
1279                 .on( "load", function() {
1280                         ok( true, "load fired on img" );
1281                 })
1282                 .trigger( "load" )
1283                 .remove();
1285         jQuery( window ).off( "load" );
1288 test("Delegated events in SVG (#10791; #13180)", function() {
1289         expect(2);
1291         var useElem, e,
1292                 svg = jQuery(
1293                         "<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>" +
1294                         "<defs><rect id='ref' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect></defs>" +
1295                         "<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1296                         "<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1297                         "<use id='use' xlink:href='#ref'></use>" +
1298                         "</svg>"
1299                 );
1301         jQuery("#qunit-fixture")
1302                 .append( svg )
1303                 .on( "click", "#svg-by-id", function() {
1304                         ok( true, "delegated id selector" );
1305                 })
1306                 .on( "click", "[class~='svg-by-class']", function() {
1307                         ok( true, "delegated class selector" );
1308                 })
1309                 .find( "#svg-by-id, [class~='svg-by-class']" )
1310                         .trigger("click")
1311                 .end();
1313         // Fire a native click on an SVGElementInstance (the instance tree of an SVG <use>)
1314         // to confirm that it doesn't break our event delegation handling (#13180)
1315         useElem = svg.find("#use")[0];
1316         if ( document.createEvent && useElem && useElem.instanceRoot ) {
1317                 e = document.createEvent("MouseEvents");
1318                 e.initEvent( "click", true, true );
1319                 useElem.instanceRoot.dispatchEvent( e );
1320         }
1322         jQuery("#qunit-fixture").off("click");
1325 test("Delegated events in forms (#10844; #11145; #8165; #11382, #11764)", function() {
1326         expect(5);
1328         // Alias names like "id" cause havoc
1329         var form = jQuery(
1330                         "<form id='myform'>" +
1331                                 "<input type='text' name='id' value='secret agent man' />" +
1332                         "</form>"
1333                 )
1334                 .on( "submit", function( event ) {
1335                         event.preventDefault();
1336                 })
1337                 .appendTo("body");
1339         jQuery("body")
1340                 .on( "submit", "#myform", function() {
1341                         ok( true, "delegated id selector with aliased id" );
1342                 })
1343                 .find("#myform")
1344                         .trigger("submit")
1345                 .end()
1346                 .off("submit");
1348         form.append("<input type='text' name='disabled' value='differently abled' />");
1349         jQuery("body")
1350                 .on( "submit", "#myform", function() {
1351                         ok( true, "delegated id selector with aliased disabled" );
1352                 })
1353                 .find("#myform")
1354                         .trigger("submit")
1355                 .end()
1356                 .off("submit");
1358         form
1359                 .append( "<button id='nestyDisabledBtn'><span>Zing</span></button>" )
1360                 .on( "click", "#nestyDisabledBtn", function() {
1361                         ok( true, "click on enabled/disabled button with nesty elements" );
1362                 })
1363                 .on( "mouseover", "#nestyDisabledBtn", function() {
1364                         ok( true, "mouse on enabled/disabled button with nesty elements" );
1365                 })
1366                 .find( "span" )
1367                         .trigger( "click" )             // yep
1368                         .trigger( "mouseover" ) // yep
1369                 .end()
1370                 .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
1371                 .find( "span" )
1372                         .trigger( "click" )             // nope
1373                         .trigger( "mouseover" ) // yep
1374                 .end()
1375                 .off( "click" );
1377         form.remove();
1380 test("Submit event can be stopped (#11049)", function() {
1381         expect(1);
1383         // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
1384         var form = jQuery(
1385                         "<form id='myform'>" +
1386                                 "<input type='text' name='sue' value='bawls' />" +
1387                                 "<input type='submit' />" +
1388                         "</form>"
1389                 )
1390                 .appendTo("body");
1392         jQuery( "body" )
1393                 .on( "submit", function() {
1394                         ok( true, "submit bubbled on first handler" );
1395                         return false;
1396                 })
1397                 .find( "#myform input[type=submit]" )
1398                         .each( function(){ this.click(); } )
1399                 .end()
1400                 .on( "submit", function() {
1401                         ok( false, "submit bubbled on second handler" );
1402                         return false;
1403                 })
1404                 .find( "#myform input[type=submit]" )
1405                         .each( function(){
1406                                 jQuery( this.form ).on( "submit", function( e ) {
1407                                         e.preventDefault();
1408                                         e.stopPropagation();
1409                                 });
1410                                 this.click();
1411                         })
1412                 .end()
1413                 .off( "submit" );
1415         form.remove();
1418 // Test beforeunload event only if it supported.
1419 // Support: iOS 7+, Android<4.0
1420 // iOS & old Android have the window.onbeforeunload field but don't support the beforeunload
1421 // handler making it impossible to feature-detect the support.
1422 if ( window.onbeforeunload === null &&
1423         !/(ipad|iphone|ipod|android 2\.3)/i.test( navigator.userAgent ) ) {
1424         asyncTest("on(beforeunload)", 1, function() {
1425                 var iframe = jQuery(jQuery.parseHTML("<iframe src='data/event/onbeforeunload.html'><iframe>"));
1427                 window.onmessage = function( event ) {
1428                         var payload = JSON.parse( event.data );
1430                         ok( payload.event, "beforeunload", "beforeunload event" );
1432                         iframe.remove();
1433                         window.onmessage = null;
1434                         start();
1435                 };
1437                 iframe.appendTo("#qunit-fixture");
1438         });
1441 test("jQuery.Event( type, props )", function() {
1443         expect(6);
1445         var event = jQuery.Event( "keydown", { keyCode: 64 }),
1446                         handler = function( event ) {
1447                                 ok( "keyCode" in event, "Special property 'keyCode' exists" );
1448                                 equal( event.keyCode, 64, "event.keyCode has explicit value '64'" );
1449                         };
1451         // Supports jQuery.Event implementation
1452         equal( event.type, "keydown", "Verify type" );
1454         // ensure "type" in props won't clobber the one set by constructor
1455         equal( jQuery.inArray("type", jQuery.event.props), -1, "'type' property not in props (#10375)" );
1457         ok( "keyCode" in event, "Special 'keyCode' property exists" );
1459         strictEqual( jQuery.isPlainObject( event ), false, "Instances of $.Event should not be identified as a plain object." );
1461         jQuery("body").on( "keydown", handler ).trigger( event );
1463         jQuery("body").off( "keydown" );
1467 test("jQuery.Event properties", function(){
1468         expect(12);
1470         var handler,
1471                 $structure = jQuery("<div id='ancestor'><p id='delegate'><span id='target'>shiny</span></p></div>"),
1472                 $target = $structure.find("#target");
1474         handler = function( e ) {
1475                 strictEqual( e.currentTarget, this, "currentTarget at " + this.id );
1476                 equal( e.isTrigger, 3, "trigger at " + this.id );
1477         };
1478         $structure.one( "click", handler );
1479         $structure.one( "click", "p", handler );
1480         $target.one( "click", handler );
1481         $target[0].onclick = function( e ) {
1482                 strictEqual( e.currentTarget, this, "currentTarget at target (native handler)" );
1483                 equal( e.isTrigger, 3, "trigger at target (native handler)" );
1484         };
1485         $target.trigger("click");
1487         $target.one( "click", function( e ) {
1488                 equal( e.isTrigger, 2, "triggerHandler at target" );
1489         });
1490         $target[0].onclick = function( e ) {
1491                 equal( e.isTrigger, 2, "triggerHandler at target (native handler)" );
1492         };
1493         $target.triggerHandler("click");
1495         handler = function( e ) {
1496                 strictEqual( e.isTrigger, undefined, "native event at " + this.id );
1497         };
1498         $target.one( "click", handler );
1499         $target[0].onclick = function( e ) {
1500                 strictEqual( e.isTrigger, undefined, "native event at target (native handler)" );
1501         };
1502         fireNative( $target[0], "click" );
1505 test(".on()/.off()", function() {
1506         expect(65);
1508         var event, clicked, hash, called, livec, lived, livee,
1509                 submit = 0, div = 0, livea = 0, liveb = 0;
1511         jQuery("#body").on("submit", "#qunit-fixture div", function(){ submit++; return false; });
1512         jQuery("#body").on("click", "#qunit-fixture div", function(){ div++; });
1513         jQuery("#body").on("click", "div#nothiddendiv", function(){ livea++; });
1514         jQuery("#body").on("click", "div#nothiddendivchild", function(){ liveb++; });
1516         // Nothing should trigger on the body
1517         jQuery("body").trigger("click");
1518         equal( submit, 0, "Click on body" );
1519         equal( div, 0, "Click on body" );
1520         equal( livea, 0, "Click on body" );
1521         equal( liveb, 0, "Click on body" );
1523         // This should trigger two events
1524         submit = 0; div = 0; livea = 0; liveb = 0;
1525         jQuery("div#nothiddendiv").trigger("click");
1526         equal( submit, 0, "Click on div" );
1527         equal( div, 1, "Click on div" );
1528         equal( livea, 1, "Click on div" );
1529         equal( liveb, 0, "Click on div" );
1531         // This should trigger three events (w/ bubbling)
1532         submit = 0; div = 0; livea = 0; liveb = 0;
1533         jQuery("div#nothiddendivchild").trigger("click");
1534         equal( submit, 0, "Click on inner div" );
1535         equal( div, 2, "Click on inner div" );
1536         equal( livea, 1, "Click on inner div" );
1537         equal( liveb, 1, "Click on inner div" );
1539         // This should trigger one submit
1540         submit = 0; div = 0; livea = 0; liveb = 0;
1541         jQuery("div#nothiddendivchild").trigger("submit");
1542         equal( submit, 1, "Submit on div" );
1543         equal( div, 0, "Submit on div" );
1544         equal( livea, 0, "Submit on div" );
1545         equal( liveb, 0, "Submit on div" );
1547         // Make sure no other events were removed in the process
1548         submit = 0; div = 0; livea = 0; liveb = 0;
1549         jQuery("div#nothiddendivchild").trigger("click");
1550         equal( submit, 0, "off Click on inner div" );
1551         equal( div, 2, "off Click on inner div" );
1552         equal( livea, 1, "off Click on inner div" );
1553         equal( liveb, 1, "off Click on inner div" );
1555         // Now make sure that the removal works
1556         submit = 0; div = 0; livea = 0; liveb = 0;
1557         jQuery("#body").off("click", "div#nothiddendivchild");
1558         jQuery("div#nothiddendivchild").trigger("click");
1559         equal( submit, 0, "off Click on inner div" );
1560         equal( div, 2, "off Click on inner div" );
1561         equal( livea, 1, "off Click on inner div" );
1562         equal( liveb, 0, "off Click on inner div" );
1564         // Make sure that the click wasn't removed too early
1565         submit = 0; div = 0; livea = 0; liveb = 0;
1566         jQuery("div#nothiddendiv").trigger("click");
1567         equal( submit, 0, "off Click on inner div" );
1568         equal( div, 1, "off Click on inner div" );
1569         equal( livea, 1, "off Click on inner div" );
1570         equal( liveb, 0, "off Click on inner div" );
1572         // Make sure that stopPropagation doesn't stop live events
1573         submit = 0; div = 0; livea = 0; liveb = 0;
1574         jQuery("#body").on("click", "div#nothiddendivchild", function( e ){ liveb++; e.stopPropagation(); });
1575         jQuery("div#nothiddendivchild").trigger("click");
1576         equal( submit, 0, "stopPropagation Click on inner div" );
1577         equal( div, 1, "stopPropagation Click on inner div" );
1578         equal( livea, 0, "stopPropagation Click on inner div" );
1579         equal( liveb, 1, "stopPropagation Click on inner div" );
1581         // Make sure click events only fire with primary click
1582         submit = 0; div = 0; livea = 0; liveb = 0;
1583         event = jQuery.Event("click");
1584         event.button = 1;
1585         jQuery("div#nothiddendiv").trigger(event);
1587         equal( livea, 0, "on secondary click" );
1589         jQuery("#body").off("click", "div#nothiddendivchild");
1590         jQuery("#body").off("click", "div#nothiddendiv");
1591         jQuery("#body").off("click", "#qunit-fixture div");
1592         jQuery("#body").off("submit", "#qunit-fixture div");
1594         // Test binding with a different context
1595         clicked = 0;
1596         jQuery("#qunit-fixture").on("click", "#foo", function(){ clicked++; });
1597         jQuery("#qunit-fixture div").trigger("click");
1598         jQuery("#foo").trigger("click");
1599         jQuery("#qunit-fixture").trigger("click");
1600         jQuery("body").trigger("click");
1601         equal( clicked, 2, "on with a context" );
1603         // Test unbinding with a different context
1604         jQuery("#qunit-fixture").off("click", "#foo");
1605         jQuery("#foo").trigger("click");
1606         equal( clicked, 2, "off with a context");
1608         // Test binding with event data
1609         jQuery("#body").on("click", "#foo", true, function( e ){ equal( e.data, true, "on with event data" ); });
1610         jQuery("#foo").trigger("click");
1611         jQuery("#body").off("click", "#foo");
1613         // Test binding with trigger data
1614         jQuery("#body").on("click", "#foo", function(e, data){ equal( data, true, "on with trigger data" ); });
1615         jQuery("#foo").trigger("click", true);
1616         jQuery("#body").off("click", "#foo");
1618         // Test binding with different this object
1619         jQuery("#body").on("click", "#foo", jQuery.proxy(function(){ equal( this["foo"], "bar", "on with event scope" ); }, { "foo": "bar" }));
1620         jQuery("#foo").trigger("click");
1621         jQuery("#body").off("click", "#foo");
1623         // Test binding with different this object, event data, and trigger data
1624         jQuery("#body").on("click", "#foo", true, jQuery.proxy(function(e, data){
1625                 equal( e.data, true, "on with with different this object, event data, and trigger data" );
1626                 equal( this.foo, "bar", "on with with different this object, event data, and trigger data" );
1627                 equal( data, true, "on with with different this object, event data, and trigger data");
1628         }, { "foo": "bar" }));
1629         jQuery("#foo").trigger("click", true);
1630         jQuery("#body").off("click", "#foo");
1632         // Verify that return false prevents default action
1633         jQuery("#body").on("click", "#anchor2", function(){ return false; });
1634         hash = window.location.hash;
1635         jQuery("#anchor2").trigger("click");
1636         equal( window.location.hash, hash, "return false worked" );
1637         jQuery("#body").off("click", "#anchor2");
1639         // Verify that .preventDefault() prevents default action
1640         jQuery("#body").on("click", "#anchor2", function(e){ e.preventDefault(); });
1641         hash = window.location.hash;
1642         jQuery("#anchor2").trigger("click");
1643         equal( window.location.hash, hash, "e.preventDefault() worked" );
1644         jQuery("#body").off("click", "#anchor2");
1646         // Test binding the same handler to multiple points
1647         called = 0;
1648         function callback(){ called++; return false; }
1650         jQuery("#body").on("click", "#nothiddendiv", callback);
1651         jQuery("#body").on("click", "#anchor2", callback);
1653         jQuery("#nothiddendiv").trigger("click");
1654         equal( called, 1, "Verify that only one click occurred." );
1656         called = 0;
1657         jQuery("#anchor2").trigger("click");
1658         equal( called, 1, "Verify that only one click occurred." );
1660         // Make sure that only one callback is removed
1661         jQuery("#body").off("click", "#anchor2", callback);
1663         called = 0;
1664         jQuery("#nothiddendiv").trigger("click");
1665         equal( called, 1, "Verify that only one click occurred." );
1667         called = 0;
1668         jQuery("#anchor2").trigger("click");
1669         equal( called, 0, "Verify that no click occurred." );
1671         // Make sure that it still works if the selector is the same,
1672         // but the event type is different
1673         jQuery("#body").on("foo", "#nothiddendiv", callback);
1675         // Cleanup
1676         jQuery("#body").off("click", "#nothiddendiv", callback);
1678         called = 0;
1679         jQuery("#nothiddendiv").trigger("click");
1680         equal( called, 0, "Verify that no click occurred." );
1682         called = 0;
1683         jQuery("#nothiddendiv").trigger("foo");
1684         equal( called, 1, "Verify that one foo occurred." );
1686         // Cleanup
1687         jQuery("#body").off("foo", "#nothiddendiv", callback);
1689         // Make sure we don't loose the target by DOM modifications
1690         // after the bubble already reached the liveHandler
1691         livec = 0;
1692         jQuery("#nothiddendivchild").html("<span></span>");
1694         jQuery("#body").on("click", "#nothiddendivchild", function(){ jQuery("#nothiddendivchild").html(""); });
1695         jQuery("#body").on("click", "#nothiddendivchild", function(e){ if(e.target) {livec++;} });
1697         jQuery("#nothiddendiv span").trigger("click");
1698         equal( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
1699         equal( livec, 1, "Verify that second handler occurred even with nuked target." );
1701         // Cleanup
1702         jQuery("#body").off("click", "#nothiddendivchild");
1704         // Verify that .live() occurs and cancel bubble in the same order as
1705         // we would expect .on() and .click() without delegation
1706         lived = 0;
1707         livee = 0;
1709         // bind one pair in one order
1710         jQuery("#body").on("click", "span#liveSpan1 a", function(){ lived++; return false; });
1711         jQuery("#body").on("click", "span#liveSpan1", function(){ livee++; });
1713         jQuery("span#liveSpan1 a").trigger("click");
1714         equal( lived, 1, "Verify that only one first handler occurred." );
1715         equal( livee, 0, "Verify that second handler doesn't." );
1717         // and one pair in inverse
1718         jQuery("#body").on("click", "span#liveSpan2", function(){ livee++; });
1719         jQuery("#body").on("click", "span#liveSpan2 a", function(){ lived++; return false; });
1721         lived = 0;
1722         livee = 0;
1723         jQuery("span#liveSpan2 a").trigger("click");
1724         equal( lived, 1, "Verify that only one first handler occurred." );
1725         equal( livee, 0, "Verify that second handler doesn't." );
1727         // Cleanup
1728         jQuery("#body").off("click", "**");
1730         // Test this, target and currentTarget are correct
1731         jQuery("#body").on("click", "span#liveSpan1", function( e ) {
1732                 equal( this.id, "liveSpan1", "Check the this within a on handler" );
1733                 equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a on handler" );
1734                 equal( e.delegateTarget, document.body, "Check the event.delegateTarget within a on handler" );
1735                 equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a on handler" );
1736         });
1738         jQuery("span#liveSpan1 a").trigger("click");
1740         jQuery("#body").off("click", "span#liveSpan1");
1742         // Work with deep selectors
1743         livee = 0;
1745         function clickB() { livee++; }
1747         jQuery("#body").on("click", "#nothiddendiv div", function(){ livee++; });
1748         jQuery("#body").on("click", "#nothiddendiv div", clickB);
1749         jQuery("#body").on("mouseover", "#nothiddendiv div", function(){ livee++; });
1751         equal( livee, 0, "No clicks, deep selector." );
1753         livee = 0;
1754         jQuery("#nothiddendivchild").trigger("click");
1755         equal( livee, 2, "Click, deep selector." );
1757         livee = 0;
1758         jQuery("#nothiddendivchild").trigger("mouseover");
1759         equal( livee, 1, "Mouseover, deep selector." );
1761         jQuery("#body").off("mouseover", "#nothiddendiv div");
1763         livee = 0;
1764         jQuery("#nothiddendivchild").trigger("click");
1765         equal( livee, 2, "Click, deep selector." );
1767         livee = 0;
1768         jQuery("#nothiddendivchild").trigger("mouseover");
1769         equal( livee, 0, "Mouseover, deep selector." );
1771         jQuery("#body").off("click", "#nothiddendiv div", clickB);
1773         livee = 0;
1774         jQuery("#nothiddendivchild").trigger("click");
1775         equal( livee, 1, "Click, deep selector." );
1777         jQuery("#body").off("click", "#nothiddendiv div");
1780 test("jQuery.off using dispatched jQuery.Event", function() {
1781         expect(1);
1783         var markup = jQuery("<p><a href='#'>target</a></p>"),
1784                 count = 0;
1785         markup
1786                 .on( "click.name", "a", function( event ) {
1787                         equal( ++count, 1, "event called once before removal" );
1788                         jQuery().off( event );
1789                 })
1790                 .find("a").trigger("click").trigger("click").end()
1791                 .remove();
1794 test( "delegated event with delegateTarget-relative selector", function() {
1795         expect(3);
1796         var markup = jQuery("<div><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></div>").appendTo("#qunit-fixture");
1798         // Non-positional selector (#12383)
1799         markup.find("#ul0")
1800                 .on( "click", "div li a", function() {
1801                         ok( false, "div is ABOVE the delegation point!" );
1802                 })
1803                 .on( "click", "ul a", function() {
1804                         ok( false, "ul IS the delegation point!" );
1805                 })
1806                 .on( "click", "li.test a", function() {
1807                         ok( true, "li.test is below the delegation point." );
1808                 })
1809                 .find("#a0_0").trigger("click").end()
1810                 .off("click");
1812         // Positional selector (#11315)
1813         markup.find("ul").eq(0)
1814                 .on( "click", ">li>a", function() {
1815                         ok( this.id === "a0", "child li was clicked" );
1816                 })
1817                 .find("#ul0")
1818                         .on( "click", "li:first>a", function() {
1819                                 ok( this.id === "a0_0" , "first li under #u10 was clicked" );
1820                         })
1821                 .end()
1822                 .find("a").trigger("click").end()
1823                 .find("#ul0").off();
1825         markup.remove();
1828 test( "delegated event with selector matching Object.prototype property (#13203)", function() {
1829         expect(1);
1831         var matched = 0;
1833         jQuery("#foo").on( "click", "toString", function() {
1834                 matched++;
1835         });
1837         jQuery("#anchor2").trigger("click");
1839         equal( matched, 0, "Nothing matched 'toString'" );
1842 test("stopPropagation() stops directly-bound events on delegated target", function() {
1843         expect(1);
1845         var markup = jQuery("<div><p><a href=\"#\">target</a></p></div>");
1846         markup
1847                 .on( "click", function() {
1848                         ok( false, "directly-bound event on delegate target was called" );
1849                 })
1850                 .on( "click", "a", function( e ) {
1851                         e.stopPropagation();
1852                         ok( true, "delegated handler was called" );
1853                 })
1854                 .find("a").trigger("click").end()
1855                 .remove();
1858 test("off all bound delegated events", function(){
1859         expect(2);
1861         var count = 0,
1862                 clicks = 0,
1863                 div = jQuery("#body");
1865         div.on( "click submit", "div#nothiddendivchild", function(){ count++; } );
1866         div.on( "click", function(){ clicks++; } );
1867         div.off( undefined, "**" );
1869         jQuery("div#nothiddendivchild").trigger("click");
1870         jQuery("div#nothiddendivchild").trigger("submit");
1872         equal( count, 0, "Make sure no events were triggered." );
1874         div.trigger("click");
1875         equal( clicks, 2, "Make sure delegated and directly bound event occurred." );
1876         div.off("click");
1879 test("on with multiple delegated events", function(){
1880         expect(1);
1882         var count = 0,
1883                 div = jQuery("#body");
1885         div.on("click submit", "div#nothiddendivchild", function(){ count++; });
1887         jQuery("div#nothiddendivchild").trigger("click");
1888         jQuery("div#nothiddendivchild").trigger("submit");
1890         equal( count, 2, "Make sure both the click and submit were triggered." );
1892         jQuery("#body").off( undefined, "**" );
1895 test("delegated on with change", function(){
1896         expect(8);
1898         var select, checkbox, checkboxFunction,
1899                 text, textChange, oldTextVal,
1900                 password, passwordChange, oldPasswordVal,
1901                 selectChange = 0,
1902                 checkboxChange = 0;
1904         select = jQuery("select[name='S1']");
1905         jQuery("#body").on("change", "select[name='S1']", function() {
1906                 selectChange++;
1907         });
1909         checkbox = jQuery("#check2");
1910         checkboxFunction = function(){
1911                 checkboxChange++;
1912         };
1913         jQuery("#body").on("change", "#check2", checkboxFunction);
1915         // test click on select
1917         // second click that changed it
1918         selectChange = 0;
1919         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1920         select.trigger("change");
1921         equal( selectChange, 1, "Change on click." );
1923         // test keys on select
1924         selectChange = 0;
1925         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1926         select.trigger("change");
1927         equal( selectChange, 1, "Change on keyup." );
1929         // test click on checkbox
1930         checkbox.trigger("change");
1931         equal( checkboxChange, 1, "Change on checkbox." );
1933         // test blur/focus on text
1934         text = jQuery("#name");
1935         textChange = 0;
1936         oldTextVal = text.val();
1938         jQuery("#body").on("change", "#name", function() {
1939                 textChange++;
1940         });
1942         text.val(oldTextVal+"foo");
1943         text.trigger("change");
1944         equal( textChange, 1, "Change on text input." );
1946         text.val(oldTextVal);
1947         jQuery("#body").off("change", "#name");
1949         // test blur/focus on password
1950         password = jQuery("#name");
1951         passwordChange = 0;
1952         oldPasswordVal = password.val();
1953         jQuery("#body").on("change", "#name", function() {
1954                 passwordChange++;
1955         });
1957         password.val(oldPasswordVal + "foo");
1958         password.trigger("change");
1959         equal( passwordChange, 1, "Change on password input." );
1961         password.val(oldPasswordVal);
1962         jQuery("#body").off("change", "#name");
1964         // make sure die works
1966         // die all changes
1967         selectChange = 0;
1968         jQuery("#body").off("change", "select[name='S1']");
1969         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1970         select.trigger("change");
1971         equal( selectChange, 0, "Die on click works." );
1973         selectChange = 0;
1974         select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1975         select.trigger("change");
1976         equal( selectChange, 0, "Die on keyup works." );
1978         // die specific checkbox
1979         jQuery("#body").off("change", "#check2", checkboxFunction);
1980         checkbox.trigger("change");
1981         equal( checkboxChange, 1, "Die on checkbox." );
1984 test("delegated on with submit", function() {
1985         expect( 2 );
1987         var count1 = 0, count2 = 0;
1989         jQuery("#body").on("submit", "#testForm", function(ev) {
1990                 count1++;
1991                 ev.preventDefault();
1992         });
1994         jQuery(document).on("submit", "body", function(ev) {
1995                 count2++;
1996                 ev.preventDefault();
1997         });
1999         jQuery("#testForm input[name=sub1]").trigger("submit");
2000         equal( count1, 1, "Verify form submit." );
2001         equal( count2, 1, "Verify body submit." );
2003         jQuery("#body").off( undefined, "**" );
2004         jQuery(document).off( undefined, "**" );
2007 test("delegated off() with only namespaces", function() {
2008         expect(2);
2010         var $delegate = jQuery("#liveHandlerOrder"),
2011                 count = 0;
2013         $delegate.on("click.ns", "a", function() {
2014                 count++;
2015         });
2017         jQuery("a", $delegate).eq(0).trigger("click.ns");
2019         equal( count, 1, "delegated click.ns");
2021         $delegate.off( ".ns", "**" );
2023         jQuery("a", $delegate).eq(1).trigger("click.ns");
2025         equal( count, 1, "no more .ns after off");
2028 test("Non DOM element events", function() {
2029         expect(1);
2031         var o = {};
2033         jQuery(o).on("nonelementobj", function() {
2034                 ok( true, "Event on non-DOM object triggered" );
2035         });
2037         jQuery(o).trigger("nonelementobj").off("nonelementobj");
2040 test("inline handler returning false stops default", function() {
2041         expect(1);
2043         var markup = jQuery("<div><a href=\"#\" onclick=\"return false\">x</a></div>");
2044         markup.on( "click", function(e) {
2045                 ok( e.isDefaultPrevented(), "inline handler prevented default");
2046                 return false;
2047         });
2048         markup.find("a").trigger("click");
2049         markup.off("click");
2052 test("window resize", function() {
2053         expect(2);
2055         jQuery(window).off();
2057         jQuery(window).on( "resize", function(){
2058                 ok( true, "Resize event fired." );
2059         }).trigger("resize").off("resize");
2061         ok( !jQuery._data(window, "events"), "Make sure all the events are gone." );
2064 test("focusin bubbles", function() {
2065         expect(2);
2067         var input = jQuery( "<input type='text' />" ).prependTo( "body" ),
2068                 order = 0;
2070         // focus the element so DOM focus won't fire
2071         input[0].focus();
2073         jQuery( "body" ).on( "focusin.focusinBubblesTest", function(){
2074                 equal( 1, order++, "focusin on the body second" );
2075         });
2077         input.on( "focusin.focusinBubblesTest", function(){
2078                 equal( 0, order++, "focusin on the element first" );
2079         });
2081 // Removed since DOM focus is unreliable on test swarm
2082         // DOM focus method
2083 //      input[0].focus();
2085         // To make the next focus test work, we need to take focus off the input.
2086         // This will fire another focusin event, so set order to reflect that.
2087 //      order = 1;
2088 //      jQuery("#text1")[0].focus();
2090         // jQuery trigger, which calls DOM focus
2091         order = 0;
2092         input.trigger( "focus" );
2094         input.remove();
2095         jQuery( "body" ).off( "focusin.focusinBubblesTest" );
2098 test("custom events with colons (#3533, #8272)", function() {
2099         expect(1);
2101         var tab = jQuery("<table><tr><td>trigger</td></tr></table>").appendTo("body");
2102         try {
2103                 tab.trigger("back:forth");
2104                 ok( true, "colon events don't throw" );
2105         } catch ( e ) {
2106                 ok( false, "colon events die" );
2107         }
2108         tab.remove();
2112 test(".on and .off", function() {
2113         expect(9);
2114         var counter, mixfn, data,
2115                 $onandoff = jQuery("<div id=\"onandoff\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>").appendTo("body");
2117         // Simple case
2118         jQuery( "#onandoff" )
2119                 .on( "whip", function() {
2120                         ok( true, "whipped it good" );
2121                 })
2122                 .trigger( "whip" )
2123                 .off();
2125         // Direct events only
2126         counter = 0;
2127         jQuery( "#onandoff b" )
2128                 .on( "click", 5, function( e, trig ) {
2129                         counter += e.data + (trig || 9);        // twice, 5+9+5+17=36
2130                 })
2131                 .one( "click", 7, function( e, trig ) {
2132                         counter += e.data + (trig || 11);       // once, 7+11=18
2133                 })
2134                 .trigger("click")
2135                 .trigger( "click", 17 )
2136                 .off( "click" );
2137         equal( counter, 54, "direct event bindings with data" );
2139         // Delegated events only
2140         counter = 0;
2141         jQuery( "#onandoff" )
2142                 .on( "click", "em", 5, function( e, trig ) {
2143                         counter += e.data + (trig || 9);        // twice, 5+9+5+17=36
2144                 })
2145                 .one( "click", "em", 7, function( e, trig ) {
2146                         counter += e.data + (trig || 11);       // once, 7+11=18
2147                 })
2148                 .find("em")
2149                         .trigger("click")
2150                         .trigger( "click", 17 )
2151                 .end()
2152                 .off( "click", "em" );
2153         equal( counter, 54, "delegated event bindings with data" );
2156         // Mixed event bindings and types
2157         counter = 0;
2158         mixfn = function(e, trig) {
2159                 counter += (e.data || 0) + (trig || 1);
2160         };
2161         jQuery( "#onandoff" )
2162                 .on( " click  clack cluck ", "em", 2, mixfn )
2163                 .on( "cluck", "b", 7, mixfn )
2164                 .on( "cluck", mixfn )
2165                 .trigger( "what!" )
2166                 .each( function() {
2167                         equal( counter, 0, "nothing triggered yet" );
2168                 })
2169                 .find( "em" )
2170                         .one( "cluck", 3, mixfn )
2171                         .trigger( "cluck", 8 )                  // 3+8 2+8 + 0+8 = 29
2172                         .off()
2173                         .trigger( "cluck", 9 )                  // 2+9 + 0+9 = 20
2174                 .end()
2175                 .each( function() {
2176                         equal( counter, 49, "after triggering em element" );
2177                 })
2178                 .off( "cluck", function(){} )           // shouldn't remove anything
2179                 .trigger( "cluck", 2 )                          // 0+2 = 2
2180                 .each( function() {
2181                         equal( counter, 51, "after triggering #onandoff cluck" );
2182                 })
2183                 .find( "b" )
2184                         .on( "click", 95, mixfn )
2185                         .on( "clack", "p", 97, mixfn )
2186                         .one( "cluck", 3, mixfn )
2187                         .trigger( "quack", 19 )                 // 0
2188                         .off( "click clack cluck" )
2189                 .end()
2190                 .each( function() {
2191                         equal( counter, 51, "after triggering b" );
2192                 })
2193                 .trigger( "cluck", 3 )                          // 0+3 = 3
2194                 .off( "clack", "em", mixfn )
2195                 .find( "em" )
2196                         .trigger( "clack" )                             // 0
2197                 .end()
2198                 .each( function() {
2199                         equal( counter, 54, "final triggers" );
2200                 })
2201                 .off( "click cluck" );
2203         // We should have removed all the event handlers ... kinda hacky way to check this
2204         data = jQuery.data[ jQuery( "#onandoff" )[0].expando ] || {};
2205         equal( data["events"], undefined, "no events left" );
2207         $onandoff.remove();
2210 test("special on name mapping", function() {
2211         expect( 7 );
2213         jQuery.event.special["slap"] = {
2214                 bindType: "click",
2215                 delegateType: "swing",
2216                 handle: function( event ) {
2217                         equal( event.handleObj.origType, "slap", "slapped your mammy, " + event.type );
2218                 }
2219         };
2221         var comeback = function( event ) {
2222                 ok( true, "event " + event.type + " triggered" );
2223         };
2225         jQuery("<div><button id=\"mammy\">Are We Not Men?</button></div>")
2226                 .on( "slap", "button", jQuery.noop )
2227                 .on( "swing", "button", comeback )
2228                 .find( "button" )
2229                         .on( "slap", jQuery.noop )
2230                         .on( "click", comeback )
2231                         .trigger( "click" )             // bindType-slap and click
2232                         .off( "slap" )
2233                         .trigger( "click" )             // click
2234                         .off( "click" )
2235                         .trigger( "swing" )             // delegateType-slap and swing
2236                 .end()
2237                 .off( "slap swing", "button" )
2238                 .find( "button" )                       // everything should be gone
2239                         .trigger( "slap" )
2240                         .trigger( "click" )
2241                         .trigger( "swing" )
2242                 .end()
2243                 .remove();
2244         delete jQuery.event.special["slap"];
2246         jQuery.event.special["gutfeeling"] = {
2247                 bindType: "click",
2248                 delegateType: "click",
2249                 handle: function( event ) {
2250                         equal( event.handleObj.origType, "gutfeeling", "got a gutfeeling" );
2251                         // Need to call the handler since .one() uses it to unbind
2252                         return event.handleObj.handler.call( this , event );
2253                 }
2254         };
2256         // Ensure a special event isn't removed by its mapped type
2257         jQuery( "<p>Gut Feeling</p>" )
2258                 .on( "click", jQuery.noop )
2259                 .on( "gutfeeling", jQuery.noop )
2260                 .off( "click" )
2261                 .trigger( "gutfeeling" )
2262                 .remove();
2264         // Ensure special events are removed when only a namespace is provided
2265         jQuery( "<p>Gut Feeling</p>" )
2266                 .on( "gutfeeling.Devo", jQuery.noop )
2267                 .off( ".Devo" )
2268                 .trigger( "gutfeeling" )
2269                 .remove();
2271         // Ensure .one() events are removed after their maiden voyage
2272         jQuery( "<p>Gut Feeling</p>" )
2273                 .one( "gutfeeling", jQuery.noop )
2274                 .trigger( "gutfeeling" )        // This one should
2275                 .trigger( "gutfeeling" )        // This one should not
2276                 .remove();
2278         delete jQuery.event.special["gutfeeling"];
2281 test(".on and .off, selective mixed removal (#10705)", function() {
2282         expect(7);
2284         var timingx = function( e ) {
2285                 ok( true, "triggered " + e.type );
2286         };
2288         jQuery( "<p>Strange Pursuit</p>" )
2289                 .on( "click", timingx )
2290                 .on( "click.duty", timingx )
2291                 .on( "click.now", timingx )
2292                 .on( "devo", timingx )
2293                 .on( "future", timingx )
2294                 .trigger( "click" )             // 3
2295                 .trigger( "devo" )              // 1
2296                 .off( ".duty devo " )   // trailing space
2297                 .trigger( "future" )    // 1
2298                 .trigger( "click" )             // 2
2299                 .off( "future click" )
2300                 .trigger( "click" );    // 0
2303 test(".on( event-map, null-selector, data ) #11130", function() {
2305         expect( 1 );
2307         var $p = jQuery("<p>Strange Pursuit</p>"),
2308                 data = "bar",
2309                 map = {
2310                         "foo": function( event ) {
2311                                 equal( event.data, "bar", "event.data correctly relayed with null selector" );
2312                                 $p.remove();
2313                         }
2314                 };
2316         $p.on( map, null, data ).trigger("foo");
2319 test("clone() delegated events (#11076)", function() {
2320         expect(3);
2322         var counter = { "center": 0, "fold": 0, "centerfold": 0 },
2323                 clicked = function() {
2324                         counter[ jQuery(this).text().replace(/\s+/, "") ]++;
2325                 },
2326                 table =
2327                         jQuery( "<table><tr><td>center</td><td>fold</td></tr></table>" )
2328                         .on( "click", "tr", clicked )
2329                         .on( "click", "td:first-child", clicked )
2330                         .on( "click", "td:last-child", clicked ),
2331                 clone = table.clone( true );
2333         clone.find("td").trigger("click");
2334         equal( counter["center"], 1, "first child" );
2335         equal( counter["fold"], 1, "last child" );
2336         equal( counter["centerfold"], 2, "all children" );
2338         table.remove();
2339         clone.remove();
2342 test("checkbox state (#3827)", function() {
2343         expect( 9 );
2345         var markup = jQuery("<div><input type=checkbox><div>").appendTo("#qunit-fixture"),
2346                 cb = markup.find("input")[0];
2348         jQuery(cb).on( "click", function(){
2349                 equal( this.checked, false, "just-clicked checkbox is not checked" );
2350         });
2351         markup.on( "click", function(){
2352                 equal( cb.checked, false, "checkbox is not checked in bubbled event" );
2353         });
2355         // Native click
2356         cb.checked = true;
2357         equal( cb.checked, true, "native - checkbox is initially checked" );
2358         cb.click();
2359         equal( cb.checked, false, "native - checkbox is no longer checked" );
2361         // jQuery click
2362         cb.checked = true;
2363         equal( cb.checked, true, "jQuery - checkbox is initially checked" );
2364         jQuery( cb ).trigger("click");
2365         equal( cb.checked, false, "jQuery - checkbox is no longer checked" );
2367         // Handlers only; checkbox state remains false
2368         jQuery( cb ).triggerHandler( "click" );
2371 test("hover event no longer special since 1.9", function() {
2372         expect( 1 );
2374         jQuery("<div>craft</div>")
2375                 .on( "hover", function( e ) {
2376                         equal( e.type, "hover", "I am hovering!" );
2377                 })
2378                 .trigger("hover")
2379                 .off("hover");
2382 test( "event object properties on natively-triggered event", function() {
2383         expect( 3 );
2385         var link = document.createElement( "a" ),
2386                 $link = jQuery( link ),
2387                 evt = document.createEvent( "MouseEvents" );
2389         // IE9+ requires element to be in the body before it will dispatch
2390         $link.appendTo( "body" ).on( "click", function( e ) {
2391                 // Not trying to assert specific values here, just ensure the property exists
2392                 equal( "detail" in e, true, "has .detail" );
2393                 equal( "cancelable" in e, true, "has .cancelable" );
2394                 equal( "bubbles" in e, true, "has .bubbles" );
2395         });
2396         evt.initEvent( "click", true, true );
2397         link.dispatchEvent( evt );
2398         $link.off( "click" ).remove();
2401 test("fixHooks extensions", function() {
2402         expect( 2 );
2404         // IE requires focusable elements to be visible, so append to body
2405         var $fixture = jQuery( "<input type='text' id='hook-fixture' />" ).appendTo( "body" ),
2406                 saved = jQuery.event.fixHooks.click;
2408         // Ensure the property doesn't exist
2409         $fixture.on( "click", function( event ) {
2410                 ok( !("blurrinessLevel" in event), "event.blurrinessLevel does not exist" );
2411         });
2412         fireNative( $fixture[0], "click" );
2413         $fixture.off( "click" );
2415         jQuery.event.fixHooks.click = {
2416                 filter: function( event ) {
2417                         event.blurrinessLevel = 42;
2418                         return event;
2419                 }
2420         };
2422         // Trigger a native click and ensure the property is set
2423         $fixture.on( "click", function( event ) {
2424                 equal( event.blurrinessLevel, 42, "event.blurrinessLevel was set" );
2425         });
2426         fireNative( $fixture[0], "click" );
2428         delete jQuery.event.fixHooks.click;
2429         $fixture.off( "click" ).remove();
2430         jQuery.event.fixHooks.click = saved;
2433 test( "drag/drop events copy mouse-related event properties (gh-1925, gh-2009)", function() {
2434         expect( 4 );
2436         var $fixture = jQuery( "<div id='drag-fixture'></div>" ).appendTo( "body" );
2438         $fixture.on( "dragmove", function( evt ) {
2439                 ok( "pageX" in evt, "checking for pageX property on dragmove" );
2440                 ok( "pageY" in evt, "checking for pageY property on dragmove" );
2441         });
2442         fireNative( $fixture[ 0 ], "dragmove" );
2444         $fixture.on( "drop", function( evt ) {
2445                 ok( "pageX" in evt, "checking for pageX property on drop" );
2446                 ok( "pageY" in evt, "checking for pageY property on drop" );
2447         });
2449         fireNative( $fixture[ 0 ], "drop" );
2451         $fixture.unbind( "dragmove drop" ).remove();
2454 test( "focusin using non-element targets", function() {
2455         expect( 2 );
2457         jQuery( document ).on( "focusin", function( e ) {
2458                 ok( e.type === "focusin", "got a focusin event on a document" );
2459         }).trigger( "focusin" ).off( "focusin" );
2461         jQuery( window ).on( "focusin", function( e ) {
2462                 ok( e.type === "focusin", "got a focusin event on a window" );
2463         }).trigger( "focusin" ).off( "focusin" );
2467 testIframeWithCallback( "focusin from an iframe", "event/focusinCrossFrame.html", function( frameDoc ) {
2468         expect(1);
2470         var input = jQuery( frameDoc ).find( "#frame-input" );
2472         // Create a focusin handler on the parent; shouldn't affect the iframe's fate
2473         jQuery ( "body" ).on( "focusin.iframeTest", function() {
2474                 ok( false, "fired a focusin event in the parent document" );
2475         });
2477         input.on( "focusin", function() {
2478                 ok( true, "fired a focusin event in the iframe" );
2479         });
2481         // Avoid a native event; Chrome can't force focus to another frame
2482         input.trigger( "focusin" );
2484         // Must manually remove handler to avoid leaks in our data store
2485         input.remove();
2487         // Be sure it was removed; nothing should happen
2488         input.trigger( "focusin" );
2490         // Remove body handler manually since it's outside the fixture
2491         jQuery( "body" ).off( "focusin.iframeTest" );
2494 testIframeWithCallback( "jQuery.ready promise", "event/promiseReady.html", function( isOk ) {
2495         expect(1);
2496         ok( isOk, "$.when( $.ready ) works" );
2499 testIframeWithCallback( "Focusing iframe element", "event/focusElem.html", function( isOk ) {
2500         expect(1);
2501         ok( isOk, "Focused an element in an iframe" );
2504 testIframeWithCallback( "triggerHandler(onbeforeunload)", "event/triggerunload.html", function( isOk ) {
2505         expect( 1 );
2506         ok( isOk, "Triggered onbeforeunload without an error" );
2509 // need PHP here to make the incepted IFRAME hang
2510 if ( hasPHP ) {
2511         testIframeWithCallback( "jQuery.ready synchronous load with long loading subresources", "event/syncReady.html", function( isOk ) {
2512                 expect(1);
2513                 ok( isOk, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
2514         });
2517 test("change handler should be detached from element", function() {
2518         expect( 2 );
2520         var $fixture = jQuery( "<input type='text' id='change-ie-leak' />" ).appendTo( "body" ),
2521                 originRemoveEvent = jQuery.removeEvent,
2522                 wrapperRemoveEvent =  function(elem, type, handle){
2523                         equal("change", type, "Event handler for 'change' event should be removed");
2524                         equal("change-ie-leak", jQuery(elem).attr("id"), "Event handler for 'change' event should be removed from appropriate element");
2525                         originRemoveEvent(elem, type, handle);
2526                 };
2528         jQuery.removeEvent = wrapperRemoveEvent ;
2530         $fixture.on( "change", function() {});
2531         $fixture.off( "change" );
2533         $fixture.remove();
2535         jQuery.removeEvent = originRemoveEvent;
2538 asyncTest("trigger click on checkbox, fires change event", function() {
2539         expect(1);
2541         var check = jQuery("#check2");
2543         check.on( "change", function() {
2544                 // get it?
2545                 check.off("change");
2546                 ok( true, "Change event fired as a result of triggered click" );
2547                 start();
2548         }).trigger("click");
2551 test( "Namespace preserved when passed an Event (#12739)", function() {
2552         expect( 4 );
2554         var markup = jQuery(
2555                         "<div id='parent'><div id='child'></div></div>"
2556                 ),
2557                 triggered = 0,
2558                 fooEvent;
2560         markup.find("div")
2561                 .addBack()
2562                 .on( "foo.bar", function( e ) {
2563                         if ( !e.handled ) {
2564                                 triggered++;
2565                                 e.handled = true;
2566                                 equal( e.namespace, "bar", "namespace is bar" );
2567                                 jQuery( e.target ).find("div").each(function() {
2568                                         jQuery( this ).triggerHandler( e );
2569                                 });
2570                         }
2571                 })
2572                 .on( "foo.bar2", function() {
2573                         ok( false, "foo.bar2 called on trigger " + triggered + " id " + this.id );
2574                 });
2576         markup.trigger("foo.bar");
2577         markup.trigger( jQuery.Event("foo.bar") );
2578         fooEvent = jQuery.Event("foo");
2579         fooEvent.namespace = "bar";
2580         markup.trigger( fooEvent );
2581         markup.remove();
2583         equal( triggered, 3, "foo.bar triggered" );
2586 test( "make sure events cloned correctly", 18, function() {
2587         var clone,
2588                 fixture = jQuery("#qunit-fixture"),
2589                 checkbox = jQuery("#check1"),
2590                 p = jQuery("#firstp");
2592         fixture.on( "click change", function( event, result ) {
2593                 ok( result,  event.type + " on original element is fired" );
2595         }).on( "click", "#firstp", function( event, result ) {
2596                 ok( result, "Click on original child element though delegation is fired" );
2598         }).on( "change", "#check1", function( event, result ) {
2599                 ok( result, "Change on original child element though delegation is fired" );
2600         });
2602         p.on("click", function() {
2603                 ok( true, "Click on original child element is fired" );
2604         });
2606         checkbox.on("change", function() {
2607                 ok( true, "Change on original child element is fired" );
2608         });
2610         fixture.clone().trigger("click").trigger("change"); // 0 events should be fired
2612         clone = fixture.clone( true );
2614         clone.find("p").eq(0).trigger( "click", true ); // 3 events should fire
2615         clone.find("#check1").trigger( "change", true ); // 3 events should fire
2616         clone.remove();
2618         clone = fixture.clone( true, true );
2619         clone.find("p").eq(0).trigger( "click", true ); // 3 events should fire
2620         clone.find("#check1").trigger( "change", true ); // 3 events should fire
2622         fixture.off();
2623         p.off();
2624         checkbox.off();
2626         p.trigger("click"); // 0 should be fired
2627         checkbox.trigger("change"); // 0 should be fired
2629         clone.find("p").eq(0).trigger( "click", true );  // 3 events should fire
2630         clone.find("#check1").trigger( "change", true ); // 3 events should fire
2631         clone.remove();
2633         clone.find("p").eq(0).trigger("click");  // 0 should be fired
2634         clone.find("#check1").trigger("change"); // 0 events should fire
2637 test( "String.prototype.namespace does not cause trigger() to throw (#13360)", function() {
2638         expect( 1 );
2639         var errored = false;
2641         String.prototype.namespace = function() {};
2643         try {
2644                 jQuery("<p>").trigger("foo.bar");
2645         } catch( e ) {
2646                 errored = true;
2647         }
2648         equal( errored, false, "trigger() did not throw exception" );
2649         delete String.prototype.namespace;
2652 test( "Inline event result is returned (#13993)", function() {
2653         expect( 1 );
2655         var result = jQuery("<p onclick='return 42'>hello</p>").triggerHandler("click");
2657         equal( result, 42, "inline handler returned value" );
2660 // This tests are unreliable in Firefox
2661 if ( !(/firefox/i.test( window.navigator.userAgent )) ) {
2662         test( "Check order of focusin/focusout events", 2, function() {
2663                 var focus, blur,
2664                         input = jQuery( "#name" );
2666                 input.on( "focus", function() {
2667                         focus = true;
2669                 }).on( "focusin", function() {
2670                         ok( !focus, "Focusin event should fire before focus does" );
2672                 }).on( "blur", function() {
2673                         blur = true;
2675                 }).on( "focusout", function() {
2676                         ok( !blur, "Focusout event should fire before blur does" );
2677                 });
2679                 // gain focus
2680                 input.trigger( "focus" );
2682                 // then lose it
2683                 jQuery( "#search" ).trigger( "focus" );
2685                 // cleanup
2686                 input.off();
2687         });
2689         test("focus-blur order (#12868)", function() {
2690                 expect( 5 );
2692                 var order,
2693                         $text = jQuery("#text1"),
2694                         $radio = jQuery("#radio1").trigger("focus");
2696                 // IE8-10 fire focus/blur events asynchronously; this is the resulting mess.
2697                 // IE's browser window must be topmost for this to work properly!!
2698                 stop();
2699                 $radio[0].focus();
2701                 setTimeout( function() {
2703                         $text
2704                                 .on( "focus", function(){
2705                                         equal( order++, 1, "text focus" );
2706                                 })
2707                                 .on( "blur", function(){
2708                                         equal( order++, 0, "text blur" );
2709                                 });
2710                         $radio
2711                                 .on( "focus", function(){
2712                                         equal( order++, 1, "radio focus" );
2713                                 })
2714                                 .on( "blur", function(){
2715                                         equal( order++, 0, "radio blur" );
2716                                 });
2718                         // Enabled input getting focus
2719                         order = 0;
2720                         equal( document.activeElement, $radio[0], "radio has focus" );
2721                         $text.trigger("focus");
2722                         setTimeout( function() {
2723                                 equal( document.activeElement, $text[0], "text has focus" );
2725                                 // Run handlers without native method on an input
2726                                 order = 1;
2727                                 $radio.triggerHandler( "focus" );
2728                                 $text.off();
2729                                 start();
2730                         }, 50 );
2731                 }, 50 );
2732         });