1 QUnit
.module( "event", {
2 beforeEach: function() {
5 afterEach
: moduleTeardown
8 QUnit
.test( "null or undefined handler", function( assert
) {
11 // Supports Fixes bug trac-7229
13 jQuery( "#firstp" ).on( "click", null );
14 assert
.ok( true, "Passing a null handler will not throw an exception" );
18 jQuery( "#firstp" ).on( "click", undefined );
19 assert
.ok( true, "Passing an undefined handler will not throw an exception" );
22 var expectedElem
= jQuery( "#firstp" );
23 var actualElem
= expectedElem
.on( "click", null );
24 assert
.equal( actualElem
, expectedElem
, "Passing a null handler should return the original element" );
26 actualElem
= expectedElem
.on( "click", undefined );
27 assert
.equal( actualElem
, expectedElem
, "Passing a null handler should return the original element" );
30 QUnit
.test( "on() with non-null,defined data", function( assert
) {
34 var handler = function( event
, data
) {
35 assert
.equal( data
, 0, "non-null, defined data (zero) is correctly passed" );
38 jQuery( "#foo" ).on( "foo.on", handler
);
39 jQuery( "div" ).on( "foo.delegate", "#foo", handler
);
41 jQuery( "#foo" ).trigger( "foo", 0 );
43 jQuery( "#foo" ).off( "foo.on", handler
);
44 jQuery( "div" ).off( "foo.delegate", "#foo" );
48 QUnit
.test( "Handler changes and .trigger() order", function( assert
) {
52 "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
57 .find( "*" ).addBack().on( "click", function() {
58 path
+= this.nodeName
.toLowerCase() + " ";
60 .filter( "b" ).on( "click", function( e
) {
62 // Removing span should not stop propagation to original parents
63 if ( e
.target
=== this ) {
64 jQuery( this ).parent().remove();
68 markup
.find( "b" ).trigger( "click" );
70 assert
.equal( path
, "b p div div ", "Delivered all events" );
75 QUnit
.test( "on(), with data", function( assert
) {
77 var test
, handler
, handler2
;
79 handler = function( event
) {
80 assert
.ok( event
.data
, "on() with data, check passed data exists" );
81 assert
.equal( event
.data
.foo
, "bar", "on() with data, Check value of passed data" );
83 jQuery( "#firstp" ).on( "click", { "foo": "bar" }, handler
).trigger( "click" ).off( "click", handler
);
85 assert
.ok( !jQuery
._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using data." );
88 handler2 = function( event
) {
89 assert
.equal( event
.data
, test
, "on() with function data, Check value of passed data" );
91 jQuery( "#firstp" ).on( "click", test
, handler2
).trigger( "click" ).off( "click", handler2
);
94 QUnit
.test( "click(), with data", function( assert
) {
96 var handler = function( event
) {
97 assert
.ok( event
.data
, "on() with data, check passed data exists" );
98 assert
.equal( event
.data
.foo
, "bar", "on() with data, Check value of passed data" );
100 jQuery( "#firstp" ).on( "click", { "foo": "bar" }, handler
).trigger( "click" ).off( "click", handler
);
102 assert
.ok( !jQuery
._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using data." );
105 QUnit
.test( "on(), with data, trigger with data", function( assert
) {
107 var handler = function( event
, data
) {
108 assert
.ok( event
.data
, "check passed data exists" );
109 assert
.equal( event
.data
.foo
, "bar", "Check value of passed data" );
110 assert
.ok( data
, "Check trigger data" );
111 assert
.equal( data
.bar
, "foo", "Check value of trigger data" );
113 jQuery( "#firstp" ).on( "click", { foo
: "bar" }, handler
).trigger( "click", [ { bar
: "foo" } ] ).off( "click", handler
);
116 QUnit
.test( "on(), multiple events at once", function( assert
) {
120 mouseoverCounter
= 0;
121 handler = function( event
) {
122 if ( event
.type
=== "click" ) {
124 } else if ( event
.type
=== "mouseover" ) {
125 mouseoverCounter
+= 1;
129 jQuery( "#firstp" ).on( "click mouseover", handler
).trigger( "click" ).trigger( "mouseover" );
130 assert
.equal( clickCounter
, 1, "on() with multiple events at once" );
131 assert
.equal( mouseoverCounter
, 1, "on() with multiple events at once" );
134 QUnit
.test( "on(), five events at once", function( assert
) {
138 handler = function() {
142 jQuery( "#firstp" ).on( "click mouseover foo bar baz", handler
)
143 .trigger( "click" ).trigger( "mouseover" )
144 .trigger( "foo" ).trigger( "bar" )
147 assert
.equal( count
, 5, "on() five events at once" );
150 QUnit
.test( "on(), multiple events at once and namespaces", function( assert
) {
156 div
= jQuery( "<div></div>" ).on( "focusin.a", function( e
) {
157 assert
.equal( e
.type
, cur
, "Verify right single event was fired." );
161 div
.trigger( "focusin.a" );
163 // manually clean up detached elements
166 div
= jQuery( "<div></div>" ).on( "click mouseover", obj
, function( e
) {
167 assert
.equal( e
.type
, cur
, "Verify right multi event was fired." );
168 assert
.equal( e
.data
, obj
, "Make sure the data came in correctly." );
172 div
.trigger( "click" );
175 div
.trigger( "mouseover" );
177 // manually clean up detached elements
180 div
= jQuery( "<div></div>" ).on( "focusin.a focusout.b", function( e
) {
181 assert
.equal( e
.type
, cur
, "Verify right multi event was fired." );
185 div
.trigger( "focusin.a" );
188 div
.trigger( "focusout.b" );
190 // manually clean up detached elements
194 QUnit
.test( "on(), namespace with special add", function( assert
) {
198 div
= jQuery( "<div></div>" ).appendTo( "#qunit-fixture" ).on( "test", function() {
199 assert
.ok( true, "Test event fired." );
202 jQuery
.event
.special
.test
= {
203 _default: function( e
, data
) {
204 assert
.equal( e
.type
, "test", "Make sure we're dealing with a test event." );
205 assert
.ok( data
, "And that trigger data was passed." );
206 assert
.strictEqual( e
.target
, div
[ 0 ], "And that the target is correct." );
207 assert
.equal( this, window
, "And that the context is correct." );
209 setup: function() {},
210 teardown: function() {
211 assert
.ok( true, "Teardown called." );
213 add: function( handleObj
) {
214 var handler
= handleObj
.handler
;
215 handleObj
.handler = function( e
) {
217 handler
.apply( this, arguments
);
221 assert
.ok( true, "Remove called." );
225 div
.on( "test.a", { x
: 1 }, function( e
) {
226 assert
.ok( !!e
.xyz
, "Make sure that the data is getting passed through." );
227 assert
.equal( e
.data
[ "x" ], 1, "Make sure data is attached properly." );
230 div
.on( "test.b", { x
: 2 }, function( e
) {
231 assert
.ok( !!e
.xyz
, "Make sure that the data is getting passed through." );
232 assert
.equal( e
.data
[ "x" ], 2, "Make sure data is attached properly." );
236 div
.trigger( "test", 33.33 );
239 div
.trigger( "test.a", "George Harrison" );
242 div
.trigger( "test.b", { year
: 1982 } );
247 div
= jQuery( "<div></div>" ).on( "test", function() {
248 assert
.ok( true, "Test event fired." );
252 div
.appendTo( "#qunit-fixture" ).remove();
254 delete jQuery
.event
.special
.test
;
257 QUnit
.test( "on(), no data", function( assert
) {
259 var handler = function( event
) {
260 assert
.ok( !event
.data
, "Check that no data is added to the event object" );
262 jQuery( "#firstp" ).on( "click", handler
).trigger( "click" );
265 QUnit
.test( "on/one/off(Object)", function( assert
) {
270 mouseoverCounter
= 0;
272 function handler( event
) {
273 if ( event
.type
=== "click" ) {
275 } else if ( event
.type
=== "mouseover" ) {
280 function handlerWithData( event
) {
281 if ( event
.type
=== "click" ) {
282 clickCounter
+= event
.data
;
283 } else if ( event
.type
=== "mouseover" ) {
284 mouseoverCounter
+= event
.data
;
289 $elem
.trigger( "click" ).trigger( "mouseover" );
292 $elem
= jQuery( "#firstp" )
302 "click":handlerWithData
,
303 "mouseover":handlerWithData
308 assert
.equal( clickCounter
, 3, "on(Object)" );
309 assert
.equal( mouseoverCounter
, 3, "on(Object)" );
312 assert
.equal( clickCounter
, 4, "on(Object)" );
313 assert
.equal( mouseoverCounter
, 4, "on(Object)" );
315 jQuery( "#firstp" ).off( {
321 assert
.equal( clickCounter
, 4, "on(Object)" );
322 assert
.equal( mouseoverCounter
, 4, "on(Object)" );
325 QUnit
.test( "on/off(Object), on/off(Object, String)", function( assert
) {
330 mouseoverCounter
= 0,
331 $p
= jQuery( "#firstp" ),
332 $a
= $p
.find( "a" ).eq( 0 );
335 "click": function( event
) {
336 clickCounter
+= ( event
.data
|| 1 );
338 "mouseover": function( event
) {
339 mouseoverCounter
+= ( event
.data
|| 1 );
344 $a
.trigger( "click" ).trigger( "mouseover" );
347 jQuery( document
).on( events
, "#firstp a" );
348 $p
.on( events
, "a", 2 );
351 assert
.equal( clickCounter
, 3, "on" );
352 assert
.equal( mouseoverCounter
, 3, "on" );
354 $p
.off( events
, "a" );
357 assert
.equal( clickCounter
, 4, "off" );
358 assert
.equal( mouseoverCounter
, 4, "off" );
360 jQuery( document
).off( events
, "#firstp a" );
363 assert
.equal( clickCounter
, 4, "off" );
364 assert
.equal( mouseoverCounter
, 4, "off" );
367 QUnit
.test( "on immediate propagation", function( assert
) {
371 $p
= jQuery( "#firstp" ),
372 $a
= $p
.find( "a" ).eq( 0 );
375 jQuery( document
).on( "click", "#firstp a", function( e
) {
376 lastClick
= "click1";
377 e
.stopImmediatePropagation();
379 jQuery( document
).on( "click", "#firstp a", function() {
380 lastClick
= "click2";
382 $a
.trigger( "click" );
383 assert
.equal( lastClick
, "click1", "on stopImmediatePropagation" );
384 jQuery( document
).off( "click", "#firstp a" );
387 $p
.on( "click", "a", function( e
) {
388 lastClick
= "click1";
389 e
.stopImmediatePropagation();
391 $p
.on( "click", "a", function() {
392 lastClick
= "click2";
394 $a
.trigger( "click" );
395 assert
.equal( lastClick
, "click1", "on stopImmediatePropagation" );
396 $p
.off( "click", "**" );
399 QUnit
.test( "on bubbling, isDefaultPrevented, stopImmediatePropagation", function( assert
) {
402 var $anchor2
= jQuery( "#anchor2" ),
403 $main
= jQuery( "#qunit-fixture" ),
404 neverCallMe = function() {
405 assert
.ok( false, "immediate propagation should have been stopped" );
407 fakeClick = function( $jq
) {
409 // Use a native click so we don't get jQuery simulated bubbling
410 var e
= document
.createEvent( "MouseEvents" );
411 e
.initEvent( "click", true, true );
412 $jq
[ 0 ].dispatchEvent( e
);
414 $anchor2
.on( "click", function( e
) {
417 $main
.on( "click", "#foo", function( e
) {
418 assert
.equal( e
.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
420 fakeClick( $anchor2
);
421 $anchor2
.off( "click" );
422 $main
.off( "click", "**" );
423 $anchor2
.on( "click", function() {
425 // Let the default action occur
427 $main
.on( "click", "#foo", function( e
) {
428 assert
.equal( e
.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
430 fakeClick( $anchor2
);
431 $anchor2
.off( "click" );
432 $main
.off( "click", "**" );
434 $anchor2
.on( "click", function( e
) {
435 e
.stopImmediatePropagation();
436 assert
.ok( true, "anchor was clicked and prop stopped" );
438 $anchor2
[ 0 ].addEventListener( "click", neverCallMe
, false );
439 fakeClick( $anchor2
);
440 $anchor2
[ 0 ].removeEventListener( "click", neverCallMe
);
443 QUnit
.test( "triggered events stopPropagation() for natively-bound events", function( assert
) {
446 var $button
= jQuery( "#button" ),
447 $parent
= $button
.parent(),
448 neverCallMe = function() {
449 assert
.ok( false, "propagation should have been stopped" );
451 stopPropagationCallback = function( e
) {
452 assert
.ok( true, "propagation is stopped" );
456 $parent
[ 0 ].addEventListener( "click", neverCallMe
);
457 $button
.on( "click", stopPropagationCallback
);
458 $button
.trigger( "click" );
459 $parent
[ 0 ].removeEventListener( "click", neverCallMe
);
460 $button
.off( "click", stopPropagationCallback
);
463 QUnit
.test( "trigger() works with events that were previously stopped", function( assert
) {
466 var $button
= jQuery( "#button" ),
467 $parent
= $button
.parent(),
468 neverCallMe = function() {
469 assert
.ok( false, "propagation should have been stopped" );
472 $parent
[ 0 ].addEventListener( "click", neverCallMe
);
473 $button
.on( "click", neverCallMe
);
475 var clickEvent
= jQuery
.Event( "click" );
476 clickEvent
.stopPropagation();
477 $button
.trigger( clickEvent
);
479 $parent
[ 0 ].removeEventListener( "click", neverCallMe
);
480 $button
.off( "click", neverCallMe
);
484 QUnit
.test( "on(), iframes", function( assert
) {
487 // events don't work with iframes, see trac-939 - this test fails in IE because of contentDocument
488 var doc
= jQuery( "#loadediframe" ).contents();
490 jQuery( "div", doc
).on( "click", function() {
491 assert
.ok( true, "Binding to element inside iframe" );
492 } ).trigger( "click" ).off( "click" );
495 QUnit
.test( "on(), trigger change on select", function( assert
) {
498 function selectOnChange( event
) {
499 assert
.equal( event
.data
, counter
++, "Event.data is not a global event object" );
501 jQuery( "#form select" ).each( function( i
) {
502 jQuery( this ).on( "change", i
, selectOnChange
);
503 } ).trigger( "change" );
506 QUnit
.test( "on(), namespaced events, cloned events", function( assert
) {
509 var firstp
= jQuery( "#firstp" );
511 firstp
.on( "custom.test", function() {
512 assert
.ok( false, "Custom event triggered" );
515 firstp
.on( "click", function( e
) {
516 assert
.ok( true, "Normal click triggered" );
517 assert
.equal( e
.type
+ e
.namespace, "click", "Check that only click events trigger this fn" );
520 firstp
.on( "click.test", function( e
) {
522 assert
.ok( true, "Namespaced click triggered" );
526 assert
.equal( e
.type
+ e
.namespace, check
, "Check that only click/click.test events trigger this fn" );
529 //clone(true) element to verify events are cloned correctly
530 firstp
= firstp
.add( firstp
.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp
) );
532 // Trigger both bound fn (8)
533 firstp
.trigger( "click" );
535 // Trigger one bound fn (4)
536 firstp
.trigger( "click.test" );
538 // Remove only the one fn
539 firstp
.off( "click.test" );
541 // Trigger the remaining fn (4)
542 firstp
.trigger( "click" );
544 // Remove the remaining namespaced fn
545 firstp
.off( ".test" );
547 // Try triggering the custom event (0)
548 firstp
.trigger( "custom" );
550 // using contents will get comments regular, text, and comment nodes
551 jQuery( "#nonnodes" ).contents().on( "tester", function() {
552 assert
.equal( this.nodeType
, 1, "Check node,textnode,comment on just does real nodes" );
553 } ).trigger( "tester" );
555 // Make sure events stick with appendTo'd elements (which are cloned) trac-2027
556 jQuery( "<a href='#fail' class='test'>test</a>" ).on( "click", function() { return false; } ).appendTo( "#qunit-fixture" );
557 assert
.ok( jQuery( "a.test" ).eq( 0 ).triggerHandler( "click" ) === false, "Handler is bound to appendTo'd elements" );
560 QUnit
.test( "on(), multi-namespaced events", function( assert
) {
572 function check( name
, msg
) {
573 assert
.deepEqual( name
, order
.shift(), msg
);
576 jQuery( "#firstp" ).on( "custom.test", function() {
577 check( "custom.test", "Custom event triggered" );
580 jQuery( "#firstp" ).on( "custom.test2", function() {
581 check( "custom.test2", "Custom event triggered" );
584 jQuery( "#firstp" ).on( "click.test", function() {
585 check( "click.test", "Normal click triggered" );
588 jQuery( "#firstp" ).on( "click.test.abc", function() {
589 check( "click.test.abc", "Namespaced click triggered" );
592 // Those would not trigger/off (trac-5303)
593 jQuery( "#firstp" ).trigger( "click.a.test" );
594 jQuery( "#firstp" ).off( "click.a.test" );
596 // Trigger both bound fn (1)
597 jQuery( "#firstp" ).trigger( "click.test.abc" );
599 // Trigger one bound fn (1)
600 jQuery( "#firstp" ).trigger( "click.abc" );
602 // Trigger two bound fn (2)
603 jQuery( "#firstp" ).trigger( "click.test" );
605 // Remove only the one fn
606 jQuery( "#firstp" ).off( "click.abc" );
608 // Trigger the remaining fn (1)
609 jQuery( "#firstp" ).trigger( "click" );
611 // Remove the remaining fn
612 jQuery( "#firstp" ).off( ".test" );
614 // Trigger the remaining fn (1)
615 jQuery( "#firstp" ).trigger( "custom" );
618 QUnit
.test( "namespace-only event binding is a no-op", function( assert
) {
622 .on( ".whoops", function() {
623 assert
.ok( false, "called a namespace-only event" );
625 .on( "whoops", function() {
626 assert
.ok( true, "called whoops" );
628 .trigger( "whoops" ) // 1
630 .trigger( "whoops" ) // 2
634 QUnit
.test( "Empty namespace is ignored", function( assert
) {
638 .on( "meow.", function( e
) {
639 assert
.equal( e
.namespace, "", "triggered a namespace-less meow event" );
645 QUnit
.test( "on(), with same function", function( assert
) {
648 var count
= 0, func = function() {
652 jQuery( "#liveHandlerOrder" ).on( "foo.bar", func
).on( "foo.zar", func
);
653 jQuery( "#liveHandlerOrder" ).trigger( "foo.bar" );
655 assert
.equal( count
, 1, "Verify binding function with multiple namespaces." );
657 jQuery( "#liveHandlerOrder" ).off( "foo.bar", func
).off( "foo.zar", func
);
658 jQuery( "#liveHandlerOrder" ).trigger( "foo.bar" );
660 assert
.equal( count
, 1, "Verify that removing events still work." );
663 QUnit
.test( "on(), make sure order is maintained", function( assert
) {
666 var elem
= jQuery( "#firstp" ), log
= [], check
= [];
668 jQuery
.each( new Array( 100 ), function( i
) {
669 elem
.on( "click", function() {
677 elem
.trigger( "click" );
679 assert
.equal( log
.join( "," ), check
.join( "," ), "Make sure order was maintained." );
684 QUnit
.test( "on(), with different this object", function( assert
) {
686 var thisObject
= { myThis
: true },
687 data
= { myData
: true },
688 handler1 = function() {
689 assert
.equal( this, thisObject
, "on() with different this object" );
690 }.bind( thisObject
),
691 handler2 = function( event
) {
692 assert
.equal( this, thisObject
, "on() with different this object and data" );
693 assert
.equal( event
.data
, data
, "on() with different this object and data" );
694 }.bind( thisObject
);
697 .on( "click", handler1
).trigger( "click" ).off( "click", handler1
)
698 .on( "click", data
, handler2
).trigger( "click" ).off( "click", handler2
);
700 assert
.ok( !jQuery
._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using different this object and data." );
703 QUnit
.test( "on(name, false), off(name, false)", function( assert
) {
707 jQuery( "#qunit-fixture" ).on( "click", function() { main
++; } );
708 jQuery( "#ap" ).trigger( "click" );
709 assert
.equal( main
, 1, "Verify that the trigger happened correctly." );
712 jQuery( "#ap" ).on( "click", false );
713 jQuery( "#ap" ).trigger( "click" );
714 assert
.equal( main
, 0, "Verify that no bubble happened." );
717 jQuery( "#ap" ).off( "click", false );
718 jQuery( "#ap" ).trigger( "click" );
719 assert
.equal( main
, 1, "Verify that the trigger happened correctly." );
721 // manually clean up events from elements outside the fixture
722 jQuery( "#qunit-fixture" ).off( "click" );
725 QUnit
.test( "on(name, selector, false), off(name, selector, false)", function( assert
) {
730 jQuery( "#qunit-fixture" ).on( "click", "#ap", function() { main
++; } );
731 jQuery( "#ap" ).trigger( "click" );
732 assert
.equal( main
, 1, "Verify that the trigger happened correctly." );
735 jQuery( "#ap" ).on( "click", "#groups", false );
736 jQuery( "#groups" ).trigger( "click" );
737 assert
.equal( main
, 0, "Verify that no bubble happened." );
740 jQuery( "#ap" ).off( "click", "#groups", false );
741 jQuery( "#groups" ).trigger( "click" );
742 assert
.equal( main
, 1, "Verify that the trigger happened correctly." );
743 jQuery( "#qunit-fixture" ).off( "click", "#ap" );
746 QUnit
.test( "on()/trigger()/off() on plain object", function( assert
) {
752 // Make sure it doesn't complain when no events are found
753 jQuery( obj
).trigger( "test" );
755 // Make sure it doesn't complain when no events are found
756 jQuery( obj
).off( "test" );
760 assert
.ok( true, "Custom event run." );
762 "submit": function() {
763 assert
.ok( true, "Custom submit event run." );
767 events
= jQuery
._data( obj
, "events" );
768 assert
.ok( events
, "Object has events bound." );
769 assert
.equal( obj
[ "events" ], undefined, "Events object on plain objects is not events" );
770 assert
.equal( obj
.test
, undefined, "Make sure that test event is not on the plain object." );
771 assert
.equal( obj
.handle
, undefined, "Make sure that the event handler is not on the plain object." );
774 jQuery( obj
).trigger( "test" );
775 jQuery( obj
).trigger( "submit" );
777 jQuery( obj
).off( "test" );
778 jQuery( obj
).off( "submit" );
781 jQuery( obj
).trigger( "test" );
783 // Make sure it doesn't complain when no events are found
784 jQuery( obj
).off( "test" );
786 assert
.equal( obj
&& obj
[ jQuery
.expando
] &&
787 obj
[ jQuery
.expando
][ jQuery
.expando
] &&
788 obj
[ jQuery
.expando
][ jQuery
.expando
][ "events" ], undefined, "Make sure events object is removed" );
791 QUnit
.test( "off(type)", function( assert
) {
795 $elem
= jQuery( "#firstp" );
798 assert
.ok( false, message
);
801 message
= "unbind passing function";
802 $elem
.on( "error1", error
).off( "error1", error
).triggerHandler( "error1" );
804 message
= "unbind all from event";
805 $elem
.on( "error1", error
).off( "error1" ).triggerHandler( "error1" );
807 message
= "unbind all";
808 $elem
.on( "error1", error
).off().triggerHandler( "error1" );
810 message
= "unbind many with function";
811 $elem
.on( "error1 error2", error
)
812 .off( "error1 error2", error
)
813 .trigger( "error1" ).triggerHandler( "error2" );
815 message
= "unbind many"; // trac-3538
816 $elem
.on( "error1 error2", error
)
817 .off( "error1 error2" )
818 .trigger( "error1" ).triggerHandler( "error2" );
820 message
= "unbind without a type or handler";
821 $elem
.on( "error1 error2.test", error
)
823 .trigger( "error1" ).triggerHandler( "error2" );
825 // Should only unbind the specified function
826 jQuery( document
).on( "click", function() {
827 assert
.ok( true, "called handler after selective removal" );
829 func = function() {};
832 .off( "click", func
)
837 QUnit
.test( "off(eventObject)", function( assert
) {
840 var $elem
= jQuery( "#firstp" ),
843 function check( expected
) {
845 $elem
.trigger( "foo" ).triggerHandler( "bar" );
846 assert
.equal( num
, expected
, "Check the right handlers are triggered" );
851 // This handler shouldn't be unbound
852 .on( "foo", function() {
855 .on( "foo", function( e
) {
861 .on( "bar", function() {
875 QUnit
.test( "mouseover triggers mouseenter", function( assert
) {
879 elem
= jQuery( "<a></a>" );
880 elem
.on( "mouseenter", function() {
883 elem
.trigger( "mouseover" );
884 assert
.equal( count
, 1, "make sure mouseover triggers a mouseenter" );
889 QUnit
.test( "pointerover triggers pointerenter", function( assert
) {
893 elem
= jQuery( "<a></a>" );
894 elem
.on( "pointerenter", function() {
897 elem
.trigger( "pointerover" );
898 assert
.equal( count
, 1, "make sure pointerover triggers a pointerenter" );
903 QUnit
.test( "withinElement implemented with jQuery.contains()", function( assert
) {
907 jQuery( "#qunit-fixture" ).append( "<div id='jc-outer'><div id='jc-inner'></div></div>" );
909 jQuery( "#jc-outer" ).on( "mouseenter mouseleave", function( event
) {
910 assert
.equal( this.id
, "jc-outer", this.id
+ " " + event
.type
);
913 jQuery( "#jc-inner" ).trigger( "mouseenter" );
916 QUnit
.test( "mouseenter, mouseleave don't catch exceptions", function( assert
) {
919 var elem
= jQuery( "#firstp" ).on( "mouseenter mouseleave", function() {
920 throw "an Exception";
924 elem
.trigger( "mouseenter" );
926 assert
.equal( e
, "an Exception", "mouseenter doesn't catch exceptions" );
930 elem
.trigger( "mouseleave" );
932 assert
.equal( e
, "an Exception", "mouseleave doesn't catch exceptions" );
936 QUnit
.test( "trigger() bubbling", function( assert
) {
939 var win
= 0, doc
= 0, html
= 0, body
= 0, main
= 0, ap
= 0;
941 jQuery( window
).on( "click", function() { win
++; } );
942 jQuery( document
).on( "click", function( e
) { if ( e
.target
!== document
) { doc
++; } } );
943 jQuery( "html" ).on( "click", function() { html
++; } );
944 jQuery( "body" ).on( "click", function() { body
++; } );
945 jQuery( "#qunit-fixture" ).on( "click", function() { main
++; } );
946 jQuery( "#ap" ).on( "click", function() { ap
++; return false; } );
948 jQuery( "html" ).trigger( "click" );
949 assert
.equal( win
, 1, "HTML bubble" );
950 assert
.equal( doc
, 1, "HTML bubble" );
951 assert
.equal( html
, 1, "HTML bubble" );
953 jQuery( "body" ).trigger( "click" );
954 assert
.equal( win
, 2, "Body bubble" );
955 assert
.equal( doc
, 2, "Body bubble" );
956 assert
.equal( html
, 2, "Body bubble" );
957 assert
.equal( body
, 1, "Body bubble" );
959 jQuery( "#qunit-fixture" ).trigger( "click" );
960 assert
.equal( win
, 3, "Main bubble" );
961 assert
.equal( doc
, 3, "Main bubble" );
962 assert
.equal( html
, 3, "Main bubble" );
963 assert
.equal( body
, 2, "Main bubble" );
964 assert
.equal( main
, 1, "Main bubble" );
966 jQuery( "#ap" ).trigger( "click" );
967 assert
.equal( doc
, 3, "ap bubble" );
968 assert
.equal( html
, 3, "ap bubble" );
969 assert
.equal( body
, 2, "ap bubble" );
970 assert
.equal( main
, 1, "ap bubble" );
971 assert
.equal( ap
, 1, "ap bubble" );
973 jQuery( document
).trigger( "click" );
974 assert
.equal( win
, 4, "doc bubble" );
976 // manually clean up events from elements outside the fixture
977 jQuery( window
).off( "click" );
978 jQuery( document
).off( "click" );
979 jQuery( "html, body, #qunit-fixture" ).off( "click" );
982 QUnit
.test( "trigger(type, [data], [fn])", function( assert
) {
985 var $elem
, pass
, form
, elem2
,
986 handler = function( event
, a
, b
, c
) {
987 assert
.equal( event
.type
, "click", "check passed data" );
988 assert
.equal( a
, 1, "check passed data" );
989 assert
.equal( b
, "2", "check passed data" );
990 assert
.equal( c
, "abc", "check passed data" );
994 $elem
= jQuery( "#firstp" );
996 // Simulate a "native" click
997 $elem
[ 0 ].click = function() {
998 assert
.ok( true, "Native call was triggered" );
1001 jQuery( document
).on( "mouseenter", "#firstp", function() {
1002 assert
.ok( true, "Trigger mouseenter bound by on" );
1005 jQuery( document
).on( "mouseleave", "#firstp", function() {
1006 assert
.ok( true, "Trigger mouseleave bound by on" );
1009 $elem
.trigger( "mouseenter" );
1011 $elem
.trigger( "mouseleave" );
1013 jQuery( document
).off( "mouseenter mouseleave", "#firstp" );
1015 // Triggers handlers and native
1017 $elem
.on( "click", handler
).trigger( "click", [ 1, "2", "abc" ] );
1019 // Simulate a "native" click
1020 $elem
[ 0 ].click = function() {
1021 assert
.ok( false, "Native call was triggered" );
1024 // Trigger only the handlers (no native)
1026 assert
.equal( $elem
.triggerHandler( "click", [ 1, "2", "abc" ] ), "test", "Verify handler response" );
1030 elem2
= jQuery( "#form input" ).eq( 0 );
1031 elem2
.get( 0 ).style
.display
= "none";
1032 elem2
.trigger( "focus" );
1036 assert
.ok( pass
, "Trigger focus on hidden element" );
1040 jQuery( "#qunit-fixture table" ).eq( 0 ).on( "test:test", function() {} ).trigger( "test:test" );
1044 assert
.ok( pass
, "Trigger on a table with a colon in the even type, see trac-3533" );
1046 form
= jQuery( "<form action=''></form>" ).appendTo( "body" );
1048 // Make sure it can be prevented locally
1049 form
.on( "submit", function() {
1050 assert
.ok( true, "Local `on` still works." );
1055 form
.trigger( "submit" );
1057 form
.off( "submit" );
1059 jQuery( document
).on( "submit", function() {
1060 assert
.ok( true, "Make sure bubble works up to document." );
1065 form
.trigger( "submit" );
1067 jQuery( document
).off( "submit" );
1072 QUnit
.test( "submit event bubbles on copied forms (trac-11649)", function( assert
) {
1075 var $formByClone
, $formByHTML
,
1076 $testForm
= jQuery( "#testForm" ),
1077 $fixture
= jQuery( "#qunit-fixture" ),
1078 $wrapperDiv
= jQuery( "<div></div>" ).appendTo( $fixture
);
1080 function noSubmit( e
) {
1083 function delegatedSubmit() {
1084 assert
.ok( true, "Make sure submit event bubbles up." );
1088 // Attach a delegated submit handler to the parent element
1089 $fixture
.on( "submit", "form", delegatedSubmit
);
1091 // Trigger form submission to introduce the _submit_attached property
1092 $testForm
.on( "submit", noSubmit
).find( "input[name=sub1]" ).trigger( "click" );
1094 // Copy the form via .clone() and .html()
1095 $formByClone
= $testForm
.clone( true, true ).removeAttr( "id" );
1096 $formByHTML
= jQuery( jQuery
.parseHTML( $fixture
.html() ) ).filter( "#testForm" ).removeAttr( "id" );
1097 $wrapperDiv
.append( $formByClone
, $formByHTML
);
1099 // Check submit bubbling on the copied forms
1100 $wrapperDiv
.find( "form" ).on( "submit", noSubmit
).find( "input[name=sub1]" ).trigger( "click" );
1103 $wrapperDiv
.remove();
1104 $fixture
.off( "submit", "form", delegatedSubmit
);
1105 $testForm
.off( "submit", noSubmit
);
1108 QUnit
.test( "change event bubbles on copied forms (trac-11796)", function( assert
) {
1111 var $formByClone
, $formByHTML
,
1112 $form
= jQuery( "#form" ),
1113 $fixture
= jQuery( "#qunit-fixture" ),
1114 $wrapperDiv
= jQuery( "<div></div>" ).appendTo( $fixture
);
1116 function delegatedChange() {
1117 assert
.ok( true, "Make sure change event bubbles up." );
1121 // Attach a delegated change handler to the form
1122 $fixture
.on( "change", "form", delegatedChange
);
1124 // Trigger change event to introduce the _change_attached property
1125 $form
.find( "select[name=select1]" ).val( "1" ).trigger( "change" );
1127 // Copy the form via .clone() and .html()
1128 $formByClone
= $form
.clone( true, true ).removeAttr( "id" );
1129 $formByHTML
= jQuery( jQuery
.parseHTML( $fixture
.html() ) ).filter( "#form" ).removeAttr( "id" );
1130 $wrapperDiv
.append( $formByClone
, $formByHTML
);
1132 // Check change bubbling on the copied forms
1133 $wrapperDiv
.find( "form select[name=select1]" ).val( "2" ).trigger( "change" );
1136 $wrapperDiv
.remove();
1137 $fixture
.off( "change", "form", delegatedChange
);
1140 QUnit
.test( "trigger(eventObject, [data], [fn])", function( assert
) {
1141 assert
.expect( 28 );
1144 $parent
= jQuery( "<div id='par'></div>" ).appendTo( "body" ),
1145 $child
= jQuery( "<p id='child'>foo</p>" ).appendTo( $parent
);
1147 $parent
.get( 0 ).style
.display
= "none";
1149 event
= jQuery
.Event( "noNew" );
1150 assert
.ok( event
!== window
, "Instantiate jQuery.Event without the 'new' keyword" );
1151 assert
.equal( event
.type
, "noNew", "Verify its type" );
1153 assert
.equal( event
.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1154 assert
.equal( event
.isPropagationStopped(), false, "Verify isPropagationStopped" );
1155 assert
.equal( event
.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1157 event
.preventDefault();
1158 assert
.equal( event
.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
1159 event
.stopPropagation();
1160 assert
.equal( event
.isPropagationStopped(), true, "Verify isPropagationStopped" );
1162 event
.isPropagationStopped = function() { return false; };
1163 event
.stopImmediatePropagation();
1164 assert
.equal( event
.isPropagationStopped(), true, "Verify isPropagationStopped" );
1165 assert
.equal( event
.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
1167 $parent
.on( "foo", function( e
) {
1170 assert
.equal( e
.type
, "foo", "Verify event type when passed passing an event object" );
1171 assert
.equal( e
.target
.id
, "child", "Verify event.target when passed passing an event object" );
1172 assert
.equal( e
.currentTarget
.id
, "par", "Verify event.currentTarget when passed passing an event object" );
1173 assert
.equal( e
.secret
, "boo!", "Verify event object's custom attribute when passed passing an event object" );
1176 // test with an event object
1177 event
= new jQuery
.Event( "foo" );
1178 event
.secret
= "boo!";
1179 $child
.trigger( event
);
1181 // test with a literal object
1182 $child
.trigger( { "type": "foo", "secret": "boo!" } );
1187 assert
.ok( false, "This assertion shouldn't be reached" );
1190 $parent
.on( "foo", error
);
1192 $child
.on( "foo", function( e
, a
, b
, c
) {
1193 assert
.equal( arguments
.length
, 4, "Check arguments length" );
1194 assert
.equal( a
, 1, "Check first custom argument" );
1195 assert
.equal( b
, 2, "Check second custom argument" );
1196 assert
.equal( c
, 3, "Check third custom argument" );
1198 assert
.equal( e
.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1199 assert
.equal( e
.isPropagationStopped(), false, "Verify isPropagationStopped" );
1200 assert
.equal( e
.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1202 // Skips both errors
1203 e
.stopImmediatePropagation();
1208 // We should add this back in when we want to test the order
1209 // in which event handlers are iterated.
1210 //$child.on("foo", error );
1212 event
= new jQuery
.Event( "foo" );
1213 $child
.trigger( event
, [ 1, 2, 3 ] ).off();
1214 assert
.equal( event
.result
, "result", "Check event.result attribute" );
1216 // Will error if it bubbles
1217 $child
.triggerHandler( "foo" );
1220 $parent
.off().remove();
1222 // Ensure triggerHandler doesn't molest its event object (#xxx)
1223 event
= jQuery
.Event( "zowie" );
1224 jQuery( document
).triggerHandler( event
);
1225 assert
.equal( event
.type
, "zowie", "Verify its type" );
1226 assert
.equal( event
.isPropagationStopped(), false, "propagation not stopped" );
1227 assert
.equal( event
.isDefaultPrevented(), false, "default not prevented" );
1230 QUnit
.test( ".trigger() bubbling on disconnected elements (trac-10489)", function( assert
) {
1233 jQuery( window
).on( "click", function() {
1234 assert
.ok( false, "click fired on window" );
1237 jQuery( "<div><p>hi</p></div>" )
1238 .on( "click", function() {
1239 assert
.ok( true, "click fired on div" );
1242 .on( "click", function() {
1243 assert
.ok( true, "click fired on p" );
1251 jQuery( window
).off( "click" );
1254 QUnit
.test( ".trigger() doesn't bubble load event (trac-10717)", function( assert
) {
1257 jQuery( window
).on( "load", function() {
1258 assert
.ok( false, "load fired on window" );
1261 jQuery( "<img src='" + baseURL
+ "1x1.jpg' />" )
1263 .on( "load", function() {
1264 assert
.ok( true, "load fired on img" );
1269 jQuery( window
).off( "load" );
1272 QUnit
.test( "Delegated events in SVG (trac-10791; trac-13180)", function( assert
) {
1277 "<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>" +
1278 "<defs><rect id='ref' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect></defs>" +
1279 "<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1280 "<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1281 "<use id='use' xlink:href='#ref'></use>" +
1285 jQuery( "#qunit-fixture" )
1287 .on( "click", "#svg-by-id", function() {
1288 assert
.ok( true, "delegated id selector" );
1290 .on( "click", "[class~='svg-by-class']", function() {
1291 assert
.ok( true, "delegated class selector" );
1293 .find( "#svg-by-id, [class~='svg-by-class']" )
1297 // Fire a native click on an SVGElementInstance (the instance tree of an SVG <use>)
1298 // to confirm that it doesn't break our event delegation handling (trac-13180)
1299 useElem
= svg
.find( "#use" )[ 0 ];
1300 if ( document
.createEvent
&& useElem
&& useElem
.instanceRoot
) {
1301 e
= document
.createEvent( "MouseEvents" );
1302 e
.initEvent( "click", true, true );
1303 useElem
.instanceRoot
.dispatchEvent( e
);
1306 jQuery( "#qunit-fixture" ).off( "click" );
1309 QUnit
.test( "Delegated events with malformed selectors (gh-3071)", function( assert
) {
1312 assert
.throws( function() {
1313 jQuery( "#foo" ).on( "click", ":not", function() {} );
1314 }, "malformed selector throws on attach" );
1316 assert
.throws( function() {
1317 jQuery( "#foo" ).on( "click", "nonexistent:not", function() {} );
1318 }, "short-circuitable malformed selector throws on attach" );
1320 jQuery( "#foo > :first-child" ).trigger( "click" );
1321 assert
.ok( true, "malformed selector does not throw on event" );
1324 QUnit
.test( "Delegated events in forms (trac-10844; trac-11145; trac-8165; trac-11382, trac-11764)", function( assert
) {
1327 // Alias names like "id" cause havoc
1329 "<form id='myform'>" +
1330 "<input type='text' name='id' value='secret agent man' />" +
1333 .on( "submit", function( event
) {
1334 event
.preventDefault();
1336 .appendTo( "body" );
1339 .on( "submit", "#myform", function() {
1340 assert
.ok( true, "delegated id selector with aliased id" );
1343 .trigger( "submit" )
1347 form
.append( "<input type='text' name='disabled' value='differently abled' />" );
1349 .on( "submit", "#myform", function() {
1350 assert
.ok( true, "delegated id selector with aliased disabled" );
1353 .trigger( "submit" )
1358 .append( "<button id='nestyDisabledBtn'><span>Zing</span></button>" )
1359 .on( "click", "#nestyDisabledBtn", function() {
1360 assert
.ok( true, "click on enabled/disabled button with nesty elements" );
1362 .on( "mouseover", "#nestyDisabledBtn", function() {
1363 assert
.ok( true, "mouse on enabled/disabled button with nesty elements" );
1366 .trigger( "click" ) // yep
1367 .trigger( "mouseover" ) // yep
1369 .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
1371 .trigger( "click" ) // nope
1372 .trigger( "mouseover" ) // yep
1379 QUnit
.test( "Submit event can be stopped (trac-11049)", function( assert
) {
1382 // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
1384 "<form id='myform'>" +
1385 "<input type='text' name='sue' value='bawls' />" +
1386 "<input type='submit' />" +
1389 .appendTo( "body" );
1392 .on( "submit", function() {
1393 assert
.ok( true, "submit bubbled on first handler" );
1396 .find( "#myform input[type=submit]" )
1397 .each( function() { this.click(); } )
1399 .on( "submit", function() {
1400 assert
.ok( false, "submit bubbled on second handler" );
1403 .find( "#myform input[type=submit]" )
1405 jQuery( this.form
).on( "submit", function( e
) {
1407 e
.stopPropagation();
1417 // Support: iOS <=7 - 12+
1418 // iOS has the window.onbeforeunload field but doesn't support the beforeunload
1419 // handler making it impossible to feature-detect the support.
1420 QUnit
[ /(ipad|iphone|ipod)/i.test( navigator
.userAgent
) ? "skip" : "test" ](
1421 "on(beforeunload)", function( assert
) {
1423 var iframe
= jQuery( jQuery
.parseHTML( "<iframe src='" + baseURL
+ "event/onbeforeunload.html'><iframe>" ) );
1424 var done
= assert
.async();
1426 window
.onmessage = function( event
) {
1427 var payload
= JSON
.parse( event
.data
);
1429 assert
.ok( payload
.event
, "beforeunload", "beforeunload event" );
1432 window
.onmessage
= null;
1436 iframe
.appendTo( "#qunit-fixture" );
1439 QUnit
.test( "jQuery.Event( type, props )", function( assert
) {
1443 var event
= jQuery
.Event( "keydown", { keyCode
: 64 } ),
1444 handler = function( event
) {
1445 assert
.ok( "keyCode" in event
, "Special property 'keyCode' exists" );
1446 assert
.equal( event
.keyCode
, 64, "event.keyCode has explicit value '64'" );
1449 // Supports jQuery.Event implementation
1450 assert
.equal( event
.type
, "keydown", "Verify type" );
1452 // ensure "type" in props won't clobber the one set by constructor
1453 assert
.equal( jQuery
.inArray( "type", jQuery
.event
.props
), -1, "'type' property not in props (trac-10375)" );
1455 assert
.ok( "keyCode" in event
, "Special 'keyCode' property exists" );
1457 assert
.strictEqual( jQuery
.isPlainObject( event
), false, "Instances of $.Event should not be identified as a plain object." );
1459 jQuery( "body" ).on( "keydown", handler
).trigger( event
);
1461 jQuery( "body" ).off( "keydown" );
1465 QUnit
.test( "jQuery.Event properties", function( assert
) {
1466 assert
.expect( 12 );
1469 $structure
= jQuery( "<div id='ancestor'><p id='delegate'><span id='target'>shiny</span></p></div>" ),
1470 $target
= $structure
.find( "#target" );
1472 handler = function( e
) {
1473 assert
.strictEqual( e
.currentTarget
, this, "currentTarget at " + this.id
);
1474 assert
.equal( e
.isTrigger
, 3, "trigger at " + this.id
);
1476 $structure
.one( "click", handler
);
1477 $structure
.one( "click", "p", handler
);
1478 $target
.one( "click", handler
);
1479 $target
[ 0 ].onclick = function( e
) {
1480 assert
.strictEqual( e
.currentTarget
, this, "currentTarget at target (native handler)" );
1481 assert
.equal( e
.isTrigger
, 3, "trigger at target (native handler)" );
1483 $target
.trigger( "click" );
1485 $target
.one( "click", function( e
) {
1486 assert
.equal( e
.isTrigger
, 2, "triggerHandler at target" );
1488 $target
[ 0 ].onclick = function( e
) {
1489 assert
.equal( e
.isTrigger
, 2, "triggerHandler at target (native handler)" );
1491 $target
.triggerHandler( "click" );
1493 handler = function( e
) {
1494 assert
.strictEqual( e
.isTrigger
, undefined, "native event at " + this.id
);
1496 $target
.one( "click", handler
);
1497 $target
[ 0 ].onclick = function( e
) {
1498 assert
.strictEqual( e
.isTrigger
, undefined, "native event at target (native handler)" );
1500 fireNative( $target
[ 0 ], "click" );
1503 QUnit
.test( ".on()/.off()", function( assert
) {
1504 assert
.expect( 65 );
1506 var event
, clicked
, hash
, called
, livec
, lived
, livee
,
1507 submit
= 0, div
= 0, livea
= 0, liveb
= 0;
1509 jQuery( "#body" ).on( "submit", "#qunit-fixture div", function() { submit
++; return false; } );
1510 jQuery( "#body" ).on( "click", "#qunit-fixture div", function() { div
++; } );
1511 jQuery( "#body" ).on( "click", "div#nothiddendiv", function() { livea
++; } );
1512 jQuery( "#body" ).on( "click", "div#nothiddendivchild", function() { liveb
++; } );
1514 // Nothing should trigger on the body
1515 jQuery( "body" ).trigger( "click" );
1516 assert
.equal( submit
, 0, "Click on body" );
1517 assert
.equal( div
, 0, "Click on body" );
1518 assert
.equal( livea
, 0, "Click on body" );
1519 assert
.equal( liveb
, 0, "Click on body" );
1521 // This should trigger two events
1522 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1523 jQuery( "div#nothiddendiv" ).trigger( "click" );
1524 assert
.equal( submit
, 0, "Click on div" );
1525 assert
.equal( div
, 1, "Click on div" );
1526 assert
.equal( livea
, 1, "Click on div" );
1527 assert
.equal( liveb
, 0, "Click on div" );
1529 // This should trigger three events (w/ bubbling)
1530 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1531 jQuery( "div#nothiddendivchild" ).trigger( "click" );
1532 assert
.equal( submit
, 0, "Click on inner div" );
1533 assert
.equal( div
, 2, "Click on inner div" );
1534 assert
.equal( livea
, 1, "Click on inner div" );
1535 assert
.equal( liveb
, 1, "Click on inner div" );
1537 // This should trigger one submit
1538 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1539 jQuery( "div#nothiddendivchild" ).trigger( "submit" );
1540 assert
.equal( submit
, 1, "Submit on div" );
1541 assert
.equal( div
, 0, "Submit on div" );
1542 assert
.equal( livea
, 0, "Submit on div" );
1543 assert
.equal( liveb
, 0, "Submit on div" );
1545 // Make sure no other events were removed in the process
1546 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1547 jQuery( "div#nothiddendivchild" ).trigger( "click" );
1548 assert
.equal( submit
, 0, "off Click on inner div" );
1549 assert
.equal( div
, 2, "off Click on inner div" );
1550 assert
.equal( livea
, 1, "off Click on inner div" );
1551 assert
.equal( liveb
, 1, "off Click on inner div" );
1553 // Now make sure that the removal works
1554 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1555 jQuery( "#body" ).off( "click", "div#nothiddendivchild" );
1556 jQuery( "div#nothiddendivchild" ).trigger( "click" );
1557 assert
.equal( submit
, 0, "off Click on inner div" );
1558 assert
.equal( div
, 2, "off Click on inner div" );
1559 assert
.equal( livea
, 1, "off Click on inner div" );
1560 assert
.equal( liveb
, 0, "off Click on inner div" );
1562 // Make sure that the click wasn't removed too early
1563 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1564 jQuery( "div#nothiddendiv" ).trigger( "click" );
1565 assert
.equal( submit
, 0, "off Click on inner div" );
1566 assert
.equal( div
, 1, "off Click on inner div" );
1567 assert
.equal( livea
, 1, "off Click on inner div" );
1568 assert
.equal( liveb
, 0, "off Click on inner div" );
1570 // Make sure that stopPropagation doesn't stop live events
1571 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1572 jQuery( "#body" ).on( "click", "div#nothiddendivchild", function( e
) { liveb
++; e
.stopPropagation(); } );
1573 jQuery( "div#nothiddendivchild" ).trigger( "click" );
1574 assert
.equal( submit
, 0, "stopPropagation Click on inner div" );
1575 assert
.equal( div
, 1, "stopPropagation Click on inner div" );
1576 assert
.equal( livea
, 0, "stopPropagation Click on inner div" );
1577 assert
.equal( liveb
, 1, "stopPropagation Click on inner div" );
1579 // Make sure click events only fire with primary click
1580 submit
= 0; div
= 0; livea
= 0; liveb
= 0;
1581 event
= jQuery
.Event( "click" );
1583 jQuery( "div#nothiddendiv" ).trigger( event
);
1585 assert
.equal( livea
, 0, "on secondary click" );
1587 jQuery( "#body" ).off( "click", "div#nothiddendivchild" );
1588 jQuery( "#body" ).off( "click", "div#nothiddendiv" );
1589 jQuery( "#body" ).off( "click", "#qunit-fixture div" );
1590 jQuery( "#body" ).off( "submit", "#qunit-fixture div" );
1592 // Test binding with a different context
1594 jQuery( "#qunit-fixture" ).on( "click", "#foo", function() { clicked
++; } );
1595 jQuery( "#qunit-fixture div" ).trigger( "click" );
1596 jQuery( "#foo" ).trigger( "click" );
1597 jQuery( "#qunit-fixture" ).trigger( "click" );
1598 jQuery( "body" ).trigger( "click" );
1599 assert
.equal( clicked
, 2, "on with a context" );
1601 // Test unbinding with a different context
1602 jQuery( "#qunit-fixture" ).off( "click", "#foo" );
1603 jQuery( "#foo" ).trigger( "click" );
1604 assert
.equal( clicked
, 2, "off with a context" );
1606 // Test binding with event data
1607 jQuery( "#body" ).on( "click", "#foo", true, function( e
) {
1608 assert
.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
) {
1615 assert
.equal( data
, true, "on with trigger data" );
1617 jQuery( "#foo" ).trigger( "click", true );
1618 jQuery( "#body" ).off( "click", "#foo" );
1620 // Test binding with different this object
1621 jQuery( "#body" ).on( "click", "#foo", function() {
1622 assert
.equal( this.foo
, "bar", "on with event scope" );
1623 }.bind( { "foo": "bar" } ) );
1625 jQuery( "#foo" ).trigger( "click" );
1626 jQuery( "#body" ).off( "click", "#foo" );
1628 // Test binding with different this object, event data, and trigger data
1629 jQuery( "#body" ).on( "click", "#foo", true, function( e
, data
) {
1630 assert
.equal( e
.data
, true, "on with with different this object, event data, and trigger data" );
1631 assert
.equal( this.foo
, "bar", "on with with different this object, event data, and trigger data" );
1632 assert
.equal( data
, true, "on with with different this object, event data, and trigger data" );
1633 }.bind( { "foo": "bar" } ) );
1634 jQuery( "#foo" ).trigger( "click", true );
1635 jQuery( "#body" ).off( "click", "#foo" );
1637 // Verify that return false prevents default action
1638 jQuery( "#body" ).on( "click", "#anchor2", function() { return false; } );
1639 hash
= window
.location
.hash
;
1640 jQuery( "#anchor2" ).trigger( "click" );
1641 assert
.equal( window
.location
.hash
, hash
, "return false worked" );
1642 jQuery( "#body" ).off( "click", "#anchor2" );
1644 // Verify that .preventDefault() prevents default action
1645 jQuery( "#body" ).on( "click", "#anchor2", function( e
) { e
.preventDefault(); } );
1646 hash
= window
.location
.hash
;
1647 jQuery( "#anchor2" ).trigger( "click" );
1648 assert
.equal( window
.location
.hash
, hash
, "e.preventDefault() worked" );
1649 jQuery( "#body" ).off( "click", "#anchor2" );
1651 // Test binding the same handler to multiple points
1653 function callback() { called
++; return false; }
1655 jQuery( "#body" ).on( "click", "#nothiddendiv", callback
);
1656 jQuery( "#body" ).on( "click", "#anchor2", callback
);
1658 jQuery( "#nothiddendiv" ).trigger( "click" );
1659 assert
.equal( called
, 1, "Verify that only one click occurred." );
1662 jQuery( "#anchor2" ).trigger( "click" );
1663 assert
.equal( called
, 1, "Verify that only one click occurred." );
1665 // Make sure that only one callback is removed
1666 jQuery( "#body" ).off( "click", "#anchor2", callback
);
1669 jQuery( "#nothiddendiv" ).trigger( "click" );
1670 assert
.equal( called
, 1, "Verify that only one click occurred." );
1673 jQuery( "#anchor2" ).trigger( "click" );
1674 assert
.equal( called
, 0, "Verify that no click occurred." );
1676 // Make sure that it still works if the selector is the same,
1677 // but the event type is different
1678 jQuery( "#body" ).on( "foo", "#nothiddendiv", callback
);
1681 jQuery( "#body" ).off( "click", "#nothiddendiv", callback
);
1684 jQuery( "#nothiddendiv" ).trigger( "click" );
1685 assert
.equal( called
, 0, "Verify that no click occurred." );
1688 jQuery( "#nothiddendiv" ).trigger( "foo" );
1689 assert
.equal( called
, 1, "Verify that one foo occurred." );
1692 jQuery( "#body" ).off( "foo", "#nothiddendiv", callback
);
1694 // Make sure we don't loose the target by DOM modifications
1695 // after the bubble already reached the liveHandler
1697 jQuery( "#nothiddendivchild" ).html( "<span></span>" );
1699 jQuery( "#body" ).on( "click", "#nothiddendivchild", function() { jQuery( "#nothiddendivchild" ).html( "" ); } );
1700 jQuery( "#body" ).on( "click", "#nothiddendivchild", function( e
) { if ( e
.target
) {livec
++;} } );
1702 jQuery( "#nothiddendiv span" ).trigger( "click" );
1703 assert
.equal( jQuery( "#nothiddendiv span" ).length
, 0, "Verify that first handler occurred and modified the DOM." );
1704 assert
.equal( livec
, 1, "Verify that second handler occurred even with nuked target." );
1707 jQuery( "#body" ).off( "click", "#nothiddendivchild" );
1709 // Verify that .live() occurs and cancel bubble in the same order as
1710 // we would expect .on() and .click() without delegation
1714 // bind one pair in one order
1715 jQuery( "#body" ).on( "click", "span#liveSpan1 a", function() { lived
++; return false; } );
1716 jQuery( "#body" ).on( "click", "span#liveSpan1", function() { livee
++; } );
1718 jQuery( "span#liveSpan1 a" ).trigger( "click" );
1719 assert
.equal( lived
, 1, "Verify that only one first handler occurred." );
1720 assert
.equal( livee
, 0, "Verify that second handler doesn't." );
1722 // and one pair in inverse
1723 jQuery( "#body" ).on( "click", "span#liveSpan2", function() { livee
++; } );
1724 jQuery( "#body" ).on( "click", "span#liveSpan2 a", function() { lived
++; return false; } );
1728 jQuery( "span#liveSpan2 a" ).trigger( "click" );
1729 assert
.equal( lived
, 1, "Verify that only one first handler occurred." );
1730 assert
.equal( livee
, 0, "Verify that second handler doesn't." );
1733 jQuery( "#body" ).off( "click", "**" );
1735 // Test this, target and currentTarget are correct
1736 jQuery( "#body" ).on( "click", "span#liveSpan1", function( e
) {
1737 assert
.equal( this.id
, "liveSpan1", "Check the this within a on handler" );
1738 assert
.equal( e
.currentTarget
.id
, "liveSpan1", "Check the event.currentTarget within a on handler" );
1739 assert
.equal( e
.delegateTarget
, document
.body
, "Check the event.delegateTarget within a on handler" );
1740 assert
.equal( e
.target
.nodeName
.toUpperCase(), "A", "Check the event.target within a on handler" );
1743 jQuery( "span#liveSpan1 a" ).trigger( "click" );
1745 jQuery( "#body" ).off( "click", "span#liveSpan1" );
1747 // Work with deep selectors
1750 function clickB() { livee
++; }
1752 jQuery( "#body" ).on( "click", "#nothiddendiv div", function() { livee
++; } );
1753 jQuery( "#body" ).on( "click", "#nothiddendiv div", clickB
);
1754 jQuery( "#body" ).on( "mouseover", "#nothiddendiv div", function() { livee
++; } );
1756 assert
.equal( livee
, 0, "No clicks, deep selector." );
1759 jQuery( "#nothiddendivchild" ).trigger( "click" );
1760 assert
.equal( livee
, 2, "Click, deep selector." );
1763 jQuery( "#nothiddendivchild" ).trigger( "mouseover" );
1764 assert
.equal( livee
, 1, "Mouseover, deep selector." );
1766 jQuery( "#body" ).off( "mouseover", "#nothiddendiv div" );
1769 jQuery( "#nothiddendivchild" ).trigger( "click" );
1770 assert
.equal( livee
, 2, "Click, deep selector." );
1773 jQuery( "#nothiddendivchild" ).trigger( "mouseover" );
1774 assert
.equal( livee
, 0, "Mouseover, deep selector." );
1776 jQuery( "#body" ).off( "click", "#nothiddendiv div", clickB
);
1779 jQuery( "#nothiddendivchild" ).trigger( "click" );
1780 assert
.equal( livee
, 1, "Click, deep selector." );
1782 jQuery( "#body" ).off( "click", "#nothiddendiv div" );
1785 QUnit
.test( "jQuery.off using dispatched jQuery.Event", function( assert
) {
1788 var markup
= jQuery( "<p><a href='#'>target</a></p>" ),
1791 .on( "click.name", "a", function( event
) {
1792 assert
.equal( ++count
, 1, "event called once before removal" );
1793 jQuery().off( event
);
1795 .find( "a" ).trigger( "click" ).trigger( "click" ).end()
1799 QUnit
.test( "events with type matching an Object.prototype property (gh-3256)", function( assert
) {
1802 var elem
= jQuery( "<div></div>" ),
1805 elem
.appendTo( "#qunit-fixture" );
1809 .one( "hasOwnProperty", function() {
1812 .trigger( "hasOwnProperty" );
1814 assert
.strictEqual( eventFired
, true, "trigger fired without crashing" );
1818 QUnit
.test( "events with type matching an Object.prototype property, cloned element (gh-3256)",
1819 function( assert
) {
1822 var elem
= jQuery( "<div></div>" ),
1825 elem
.appendTo( "#qunit-fixture" );
1828 // Make sure the original element has some event data.
1829 elem
.on( "click", function() {} );
1833 .one( "hasOwnProperty", function() {
1836 .trigger( "hasOwnProperty" );
1838 assert
.strictEqual( eventFired
, true, "trigger fired without crashing" );
1842 // selector-native does not support scope-fixing in delegation
1843 QUnit
[ QUnit
.jQuerySelectors
? "test" : "skip" ]( "delegated event with delegateTarget-relative selector", function( assert
) {
1845 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" );
1847 // Non-positional selector (trac-12383)
1848 markup
.find( "#ul0" )
1849 .on( "click", "div li a", function() {
1850 assert
.ok( false, "div is ABOVE the delegation point!" );
1852 .on( "click", "ul a", function() {
1853 assert
.ok( false, "ul IS the delegation point!" );
1855 .on( "click", "li.test a", function() {
1856 assert
.ok( true, "li.test is below the delegation point." );
1858 .find( "#a0_0" ).trigger( "click" ).end()
1861 if ( QUnit
.jQuerySelectorsPos
) {
1862 // Positional selector (trac-11315)
1863 markup
.find( "ul" ).eq( 0 )
1864 .on( "click", ">li>a", function() {
1865 assert
.ok( this.id
=== "a0", "child li was clicked" );
1868 .on( "click", "li:first>a", function() {
1869 assert
.ok( this.id
=== "a0_0", "first li under #u10 was clicked" );
1872 .find( "a" ).trigger( "click" ).end()
1873 .find( "#ul0" ).off();
1875 assert
.ok( "skip", "Positional selectors are not supported" );
1876 assert
.ok( "skip", "Positional selectors are not supported" );
1882 QUnit
.test( "delegated event with selector matching Object.prototype property (trac-13203)", function( assert
) {
1887 jQuery( "#foo" ).on( "click", "toString", function() {
1891 jQuery( "#anchor2" ).trigger( "click" );
1893 assert
.equal( matched
, 0, "Nothing matched 'toString'" );
1896 QUnit
.test( "delegated event with intermediate DOM manipulation (trac-13208)", function( assert
) {
1899 jQuery( "#foo" ).on( "click", "[id=sap]", function() {} );
1900 jQuery( "#sap" ).on( "click", "[id=anchor2]", function() {
1901 document
.createDocumentFragment().appendChild( this.parentNode
);
1902 assert
.ok( true, "Element removed" );
1904 jQuery( "#anchor2" ).trigger( "click" );
1907 QUnit
.test( "ignore comment nodes in event delegation (gh-2055)", function( assert
) {
1910 // Test if DOMNodeInserted is supported
1911 // This is a back-up for when DOMNodeInserted support
1912 // is eventually removed from browsers
1915 var $fixture
= jQuery( "#qunit-fixture" );
1916 $fixture
.on( "DOMNodeInserted", function() {
1918 $fixture
.off( "DOMNodeInserted" );
1919 } ).append( "<div></div>" );
1923 var $foo
= jQuery( "#foo" ).on( "DOMNodeInserted", "[id]", function() {
1924 assert
.ok( true, "No error thrown on comment node" );
1926 $comment
= jQuery( document
.createComment( "comment" ) )
1927 .appendTo( $foo
.find( "#sap" ) );
1930 fireNative( $comment
[ 0 ], "DOMNodeInserted" );
1934 QUnit
.test( "stopPropagation() stops directly-bound events on delegated target", function( assert
) {
1937 var markup
= jQuery( "<div><p><a href=\"#\">target</a></p></div>" );
1939 .on( "click", function() {
1940 assert
.ok( false, "directly-bound event on delegate target was called" );
1942 .on( "click", "a", function( e
) {
1943 e
.stopPropagation();
1944 assert
.ok( true, "delegated handler was called" );
1946 .find( "a" ).trigger( "click" ).end()
1950 QUnit
.test( "off all bound delegated events", function( assert
) {
1955 div
= jQuery( "#body" );
1957 div
.on( "click submit", "div#nothiddendivchild", function() { count
++; } );
1958 div
.on( "click", function() { clicks
++; } );
1959 div
.off( undefined, "**" );
1961 jQuery( "div#nothiddendivchild" ).trigger( "click" );
1962 jQuery( "div#nothiddendivchild" ).trigger( "submit" );
1964 assert
.equal( count
, 0, "Make sure no events were triggered." );
1966 div
.trigger( "click" );
1967 assert
.equal( clicks
, 2, "Make sure delegated and directly bound event occurred." );
1971 QUnit
.test( "on with multiple delegated events", function( assert
) {
1975 div
= jQuery( "#body" );
1977 div
.on( "click submit", "div#nothiddendivchild", function() { count
++; } );
1979 jQuery( "div#nothiddendivchild" ).trigger( "click" );
1980 jQuery( "div#nothiddendivchild" ).trigger( "submit" );
1982 assert
.equal( count
, 2, "Make sure both the click and submit were triggered." );
1984 jQuery( "#body" ).off( undefined, "**" );
1987 QUnit
.test( "delegated on with change", function( assert
) {
1990 var select
, checkbox
, checkboxFunction
,
1991 text
, textChange
, oldTextVal
,
1992 password
, passwordChange
, oldPasswordVal
,
1996 select
= jQuery( "select[name='S1']" );
1997 jQuery( "#body" ).on( "change", "select[name='S1']", function() {
2001 checkbox
= jQuery( "#check2" );
2002 checkboxFunction = function() {
2005 jQuery( "#body" ).on( "change", "#check2", checkboxFunction
);
2007 // test click on select
2009 // second click that changed it
2011 select
[ 0 ].selectedIndex
= select
[ 0 ].selectedIndex
? 0 : 1;
2012 select
.trigger( "change" );
2013 assert
.equal( selectChange
, 1, "Change on click." );
2015 // test keys on select
2017 select
[ 0 ].selectedIndex
= select
[ 0 ].selectedIndex
? 0 : 1;
2018 select
.trigger( "change" );
2019 assert
.equal( selectChange
, 1, "Change on keyup." );
2021 // test click on checkbox
2022 checkbox
.trigger( "change" );
2023 assert
.equal( checkboxChange
, 1, "Change on checkbox." );
2025 // test blur/focus on text
2026 text
= jQuery( "#name" );
2028 oldTextVal
= text
.val();
2030 jQuery( "#body" ).on( "change", "#name", function() {
2034 text
.val( oldTextVal
+ "foo" );
2035 text
.trigger( "change" );
2036 assert
.equal( textChange
, 1, "Change on text input." );
2038 text
.val( oldTextVal
);
2039 jQuery( "#body" ).off( "change", "#name" );
2041 // test blur/focus on password
2042 password
= jQuery( "#name" );
2044 oldPasswordVal
= password
.val();
2045 jQuery( "#body" ).on( "change", "#name", function() {
2049 password
.val( oldPasswordVal
+ "foo" );
2050 password
.trigger( "change" );
2051 assert
.equal( passwordChange
, 1, "Change on password input." );
2053 password
.val( oldPasswordVal
);
2054 jQuery( "#body" ).off( "change", "#name" );
2056 // make sure die works
2060 jQuery( "#body" ).off( "change", "select[name='S1']" );
2061 select
[ 0 ].selectedIndex
= select
[ 0 ].selectedIndex
? 0 : 1;
2062 select
.trigger( "change" );
2063 assert
.equal( selectChange
, 0, "Die on click works." );
2066 select
[ 0 ].selectedIndex
= select
[ 0 ].selectedIndex
? 0 : 1;
2067 select
.trigger( "change" );
2068 assert
.equal( selectChange
, 0, "Die on keyup works." );
2070 // die specific checkbox
2071 jQuery( "#body" ).off( "change", "#check2", checkboxFunction
);
2072 checkbox
.trigger( "change" );
2073 assert
.equal( checkboxChange
, 1, "Die on checkbox." );
2076 QUnit
.test( "delegated on with submit", function( assert
) {
2079 var count1
= 0, count2
= 0;
2081 jQuery( "#body" ).on( "submit", "#testForm", function( ev
) {
2083 ev
.preventDefault();
2086 jQuery( document
).on( "submit", "body", function( ev
) {
2088 ev
.preventDefault();
2091 jQuery( "#testForm input[name=sub1]" ).trigger( "submit" );
2092 assert
.equal( count1
, 1, "Verify form submit." );
2093 assert
.equal( count2
, 1, "Verify body submit." );
2095 jQuery( "#body" ).off( undefined, "**" );
2096 jQuery( document
).off( undefined, "**" );
2099 QUnit
.test( "delegated off() with only namespaces", function( assert
) {
2102 var $delegate
= jQuery( "#liveHandlerOrder" ),
2105 $delegate
.on( "click.ns", "a", function() {
2109 jQuery( "a", $delegate
).eq( 0 ).trigger( "click.ns" );
2111 assert
.equal( count
, 1, "delegated click.ns" );
2113 $delegate
.off( ".ns", "**" );
2115 jQuery( "a", $delegate
).eq( 1 ).trigger( "click.ns" );
2117 assert
.equal( count
, 1, "no more .ns after off" );
2120 QUnit
.test( "Non DOM element events", function( assert
) {
2125 jQuery( o
).on( "nonelementobj", function() {
2126 assert
.ok( true, "Event on non-DOM object triggered" );
2129 jQuery( o
).trigger( "nonelementobj" ).off( "nonelementobj" );
2132 QUnit
.test( "inline handler returning false stops default", function( assert
) {
2135 var markup
= jQuery( "<div><a href=\"#\" onclick=\"return false\">x</a></div>" );
2136 markup
.on( "click", function( e
) {
2137 assert
.ok( e
.isDefaultPrevented(), "inline handler prevented default" );
2140 markup
.find( "a" ).trigger( "click" );
2141 markup
.off( "click" );
2144 QUnit
.test( "window resize", function( assert
) {
2147 jQuery( window
).off();
2149 jQuery( window
).on( "resize", function() {
2150 assert
.ok( true, "Resize event fired." );
2151 } ).trigger( "resize" ).off( "resize" );
2153 assert
.ok( !jQuery
._data( window
, "events" ), "Make sure all the events are gone." );
2156 QUnit
.test( "focusin bubbles", function( assert
) {
2159 var input
= jQuery( "<input type='text' />" ).prependTo( "body" ),
2162 // focus the element so DOM focus won't fire
2165 jQuery( "body" ).on( "focusin.focusinBubblesTest", function() {
2166 assert
.equal( 1, order
++, "focusin on the body second" );
2169 input
.on( "focusin.focusinBubblesTest", function() {
2170 assert
.equal( 0, order
++, "focusin on the element first" );
2173 // Removed since DOM focus is unreliable on test swarm
2175 // input[ 0 ].focus();
2177 // To make the next focus test work, we need to take focus off the input.
2178 // This will fire another focusin event, so set order to reflect that.
2180 // jQuery( "#text1" )[ 0 ].focus();
2182 // jQuery trigger, which calls DOM focus
2184 input
.trigger( "focus" );
2187 jQuery( "body" ).off( "focusin.focusinBubblesTest" );
2190 QUnit
.test( "focus does not bubble", function( assert
) {
2193 var done
= assert
.async(),
2194 input
= jQuery( "<input type='text' />" ).prependTo( "body" );
2196 // focus the element so DOM focus won't fire
2199 jQuery( "body" ).on( "focus.focusDoesNotBubbleTest", function() {
2200 assert
.ok( false, "focus doesn't fire on body" );
2203 input
.on( "focus.focusDoesNotBubbleTest", function() {
2204 assert
.ok( true, "focus on the element" );
2207 // Removed since DOM focus is unreliable on test swarm
2209 // input[ 0 ].focus();
2211 // To make the next focus test work, we need to take focus off the input.
2212 // This will fire another focusin event, so set order to reflect that.
2213 // jQuery( "#text1" )[ 0 ].focus();
2215 // jQuery trigger, which calls DOM focus
2216 input
.trigger( "focus" );
2219 jQuery( "body" ).off( "focus.focusDoesNotBubbleTest" );
2221 setTimeout( function() {
2226 QUnit
.test( "custom events with colons (trac-3533, trac-8272)", function( assert
) {
2229 var tab
= jQuery( "<table><tr><td>trigger</td></tr></table>" ).appendTo( "body" );
2231 tab
.trigger( "back:forth" );
2232 assert
.ok( true, "colon events don't throw" );
2234 assert
.ok( false, "colon events die" );
2240 QUnit
.test( ".on and .off", function( assert
) {
2242 var counter
, mixfn
, data
,
2243 $onandoff
= jQuery( "<div id=\"onandoff\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>" ).appendTo( "body" );
2246 jQuery( "#onandoff" )
2247 .on( "whip", function() {
2248 assert
.ok( true, "whipped it good" );
2253 // Direct events only
2255 jQuery( "#onandoff b" )
2256 .on( "click", 5, function( e
, trig
) {
2257 counter
+= e
.data
+ ( trig
|| 9 ); // twice, 5+9+5+17=36
2259 .one( "click", 7, function( e
, trig
) {
2260 counter
+= e
.data
+ ( trig
|| 11 ); // once, 7+11=18
2263 .trigger( "click", 17 )
2265 assert
.equal( counter
, 54, "direct event bindings with data" );
2267 // Delegated events only
2269 jQuery( "#onandoff" )
2270 .on( "click", "em", 5, function( e
, trig
) {
2271 counter
+= e
.data
+ ( trig
|| 9 ); // twice, 5+9+5+17=36
2273 .one( "click", "em", 7, function( e
, trig
) {
2274 counter
+= e
.data
+ ( trig
|| 11 ); // once, 7+11=18
2278 .trigger( "click", 17 )
2280 .off( "click", "em" );
2281 assert
.equal( counter
, 54, "delegated event bindings with data" );
2283 // Mixed event bindings and types
2285 mixfn = function( e
, trig
) {
2286 counter
+= ( e
.data
|| 0 ) + ( trig
|| 1 );
2288 jQuery( "#onandoff" )
2289 .on( " click clack cluck ", "em", 2, mixfn
)
2290 .on( "cluck", "b", 7, mixfn
)
2291 .on( "cluck", mixfn
)
2294 assert
.equal( counter
, 0, "nothing triggered yet" );
2297 .one( "cluck", 3, mixfn
)
2298 .trigger( "cluck", 8 ) // 3+8 2+8 + 0+8 = 29
2300 .trigger( "cluck", 9 ) // 2+9 + 0+9 = 20
2303 assert
.equal( counter
, 49, "after triggering em element" );
2305 .off( "cluck", function() {} ) // shouldn't remove anything
2306 .trigger( "cluck", 2 ) // 0+2 = 2
2308 assert
.equal( counter
, 51, "after triggering #onandoff cluck" );
2311 .on( "click", 95, mixfn
)
2312 .on( "clack", "p", 97, mixfn
)
2313 .one( "cluck", 3, mixfn
)
2314 .trigger( "quack", 19 ) // 0
2315 .off( "click clack cluck" )
2318 assert
.equal( counter
, 51, "after triggering b" );
2320 .trigger( "cluck", 3 ) // 0+3 = 3
2321 .off( "clack", "em", mixfn
)
2323 .trigger( "clack" ) // 0
2326 assert
.equal( counter
, 54, "final triggers" );
2328 .off( "click cluck" );
2330 // We should have removed all the event handlers ... kinda hacky way to check this
2331 data
= jQuery
.data
[ jQuery( "#onandoff" )[ 0 ].expando
] || {};
2332 assert
.equal( data
[ "events" ], undefined, "no events left" );
2337 QUnit
.test( "special on name mapping", function( assert
) {
2340 jQuery
.event
.special
.slap
= {
2342 delegateType
: "swing",
2343 handle: function( event
) {
2344 assert
.equal( event
.handleObj
.origType
, "slap", "slapped your mammy, " + event
.type
);
2348 var comeback = function( event
) {
2349 assert
.ok( true, "event " + event
.type
+ " triggered" );
2352 jQuery( "<div><button id=\"mammy\">Are We Not Men?</button></div>" )
2353 .on( "slap", "button", jQuery
.noop
)
2354 .on( "swing", "button", comeback
)
2356 .on( "slap", jQuery
.noop
)
2357 .on( "click", comeback
)
2358 .trigger( "click" ) // bindType-slap and click
2360 .trigger( "click" ) // click
2362 .trigger( "swing" ) // delegateType-slap and swing
2364 .off( "slap swing", "button" )
2365 .find( "button" ) // everything should be gone
2371 delete jQuery
.event
.special
.slap
;
2373 jQuery
.event
.special
.gutfeeling
= {
2375 delegateType
: "click",
2376 handle: function( event
) {
2377 assert
.equal( event
.handleObj
.origType
, "gutfeeling", "got a gutfeeling" );
2379 // Need to call the handler since .one() uses it to unbind
2380 return event
.handleObj
.handler
.call( this, event
);
2384 // Ensure a special event isn't removed by its mapped type
2385 jQuery( "<p>Gut Feeling</p>" )
2386 .on( "click", jQuery
.noop
)
2387 .on( "gutfeeling", jQuery
.noop
)
2389 .trigger( "gutfeeling" )
2392 // Ensure special events are removed when only a namespace is provided
2393 jQuery( "<p>Gut Feeling</p>" )
2394 .on( "gutfeeling.Devo", jQuery
.noop
)
2396 .trigger( "gutfeeling" )
2399 // Ensure .one() events are removed after their maiden voyage
2400 jQuery( "<p>Gut Feeling</p>" )
2401 .one( "gutfeeling", jQuery
.noop
)
2402 .trigger( "gutfeeling" ) // This one should
2403 .trigger( "gutfeeling" ) // This one should not
2406 delete jQuery
.event
.special
[ "gutfeeling" ];
2409 QUnit
.test( ".on and .off, selective mixed removal (trac-10705)", function( assert
) {
2412 var timingx = function( e
) {
2413 assert
.ok( true, "triggered " + e
.type
);
2416 jQuery( "<p>Strange Pursuit</p>" )
2417 .on( "click", timingx
)
2418 .on( "click.duty", timingx
)
2419 .on( "click.now", timingx
)
2420 .on( "devo", timingx
)
2421 .on( "future", timingx
)
2422 .trigger( "click" ) // 3
2423 .trigger( "devo" ) // 1
2424 .off( ".duty devo " ) // trailing space
2425 .trigger( "future" ) // 1
2426 .trigger( "click" ) // 2
2427 .off( "future click" )
2428 .trigger( "click" ); // 0
2431 QUnit
.test( "special interference with Object.prototype", function( assert
) {
2434 var triggered
= false;
2436 Object
.prototype.jqfake
= {
2437 trigger: function() {
2442 jQuery( "<div></div>" )
2443 .appendTo( "#qunit-fixture" )
2444 .trigger( "jqfake" );
2446 delete Object
.prototype.jqfake
;
2448 assert
.ok( !triggered
, "Object.prototype.jqfake.trigger not called" );
2451 QUnit
.test( ".on( event-map, null-selector, data ) trac-11130", function( assert
) {
2455 var $p
= jQuery( "<p>Strange Pursuit</p>" ),
2458 "foo": function( event
) {
2459 assert
.equal( event
.data
, "bar", "event.data correctly relayed with null selector" );
2464 $p
.on( map
, null, data
).trigger( "foo" );
2467 QUnit
.test( "clone() delegated events (trac-11076)", function( assert
) {
2470 var counter
= { "center": 0, "fold": 0, "centerfold": 0 },
2471 clicked = function() {
2472 counter
[ jQuery( this ).text().replace( /\s+/, "" ) ]++;
2475 jQuery( "<table><tr><td>center</td><td>fold</td></tr></table>" )
2476 .on( "click", "tr", clicked
)
2477 .on( "click", "td:first-child", clicked
)
2478 .on( "click", "td:last-child", clicked
),
2479 clone
= table
.clone( true );
2481 clone
.find( "td" ).trigger( "click" );
2482 assert
.equal( counter
.center
, 1, "first child" );
2483 assert
.equal( counter
.fold
, 1, "last child" );
2484 assert
.equal( counter
.centerfold
, 2, "all children" );
2490 QUnit
.test( "checkbox state (trac-3827)", function( assert
) {
2491 assert
.expect( 16 );
2493 var markup
= jQuery( "<div class='parent'><input type=checkbox><div>" ),
2494 cb
= markup
.find( "input" )[ 0 ];
2496 markup
.appendTo( "#qunit-fixture" );
2498 jQuery( cb
).on( "click", function() {
2499 assert
.equal( this.checked
, false, "just-clicked checkbox is not checked" );
2501 markup
.on( "click", function() {
2502 assert
.equal( cb
.checked
, false, "checkbox is not checked in bubbled event" );
2507 assert
.equal( cb
.checked
, true, "native event - checkbox is initially checked" );
2509 assert
.equal( cb
.checked
, false, "native event - checkbox is no longer checked" );
2513 assert
.equal( cb
.checked
, true, "jQuery event - checkbox is initially checked" );
2514 jQuery( cb
).trigger( "click" );
2515 assert
.equal( cb
.checked
, false, "jQuery event - checkbox is no longer checked" );
2517 // Handlers only; checkbox state remains false
2518 jQuery( cb
).triggerHandler( "click" );
2519 assert
.equal( cb
.checked
, false, "handlers only - checkbox is still unchecked" );
2521 // Trigger parameters are preserved (trac-13353, gh-4139)
2523 assert
.equal( cb
.checked
, true, "jQuery event with data - checkbox is initially checked" );
2524 jQuery( cb
).on( "click", function( e
, data
) {
2525 assert
.equal( data
, "clicked", "trigger data passed to handler" );
2527 markup
.on( "click", function( e
, data
) {
2528 assert
.equal( data
, "clicked", "trigger data passed to bubbled handler" );
2530 jQuery( cb
).trigger( "click", [ "clicked" ] );
2531 assert
.equal( cb
.checked
, false, "jQuery event with data - checkbox is no longer checked" );
2534 QUnit
.test( "event object properties on natively-triggered event", function( assert
) {
2537 var link
= document
.createElement( "a" ),
2538 $link
= jQuery( link
),
2539 evt
= document
.createEvent( "MouseEvents" );
2541 // Support: IE <=9 - 11+
2542 // IE requires element to be in the body before it will dispatch
2543 $link
.appendTo( "body" ).on( "click", function( e
) {
2545 // Not trying to assert specific values here, just ensure the property exists
2546 assert
.equal( "detail" in e
, true, "has .detail" );
2547 assert
.equal( "cancelable" in e
, true, "has .cancelable" );
2548 assert
.equal( "bubbles" in e
, true, "has .bubbles" );
2550 evt
.initEvent( "click", true, true );
2551 link
.dispatchEvent( evt
);
2552 $link
.off( "click" ).remove();
2555 QUnit
.test( "addProp extensions", function( assert
) {
2558 var $fixture
= jQuery( "<div>" ).appendTo( "#qunit-fixture" );
2560 // Ensure the property doesn't exist
2561 $fixture
.on( "click", function( event
) {
2562 assert
.ok( !( "testProperty" in event
), "event.testProperty does not exist" );
2564 fireNative( $fixture
[ 0 ], "click" );
2565 $fixture
.off( "click" );
2567 jQuery
.event
.addProp( "testProperty", function() { return 42; } );
2569 // Trigger a native click and ensure the property is set
2570 $fixture
.on( "click", function( event
) {
2571 assert
.equal( event
.testProperty
, 42, "event.testProperty getter was invoked" );
2573 fireNative( $fixture
[ 0 ], "click" );
2574 $fixture
.off( "click" );
2579 QUnit
.test( "drag/drop events copy mouse-related event properties (gh-1925, gh-2009)", function( assert
) {
2582 var $fixture
= jQuery( "<div id='drag-fixture'></div>" ).appendTo( "body" );
2584 $fixture
.on( "dragmove", function( evt
) {
2585 assert
.ok( "pageX" in evt
, "checking for pageX property on dragmove" );
2586 assert
.ok( "pageY" in evt
, "checking for pageY property on dragmove" );
2588 fireNative( $fixture
[ 0 ], "dragmove" );
2590 $fixture
.on( "drop", function( evt
) {
2591 assert
.ok( "pageX" in evt
, "checking for pageX property on drop" );
2592 assert
.ok( "pageY" in evt
, "checking for pageY property on drop" );
2595 fireNative( $fixture
[ 0 ], "drop" );
2597 $fixture
.off( "dragmove drop" ).remove();
2600 QUnit
.test( "focusin using non-element targets", function( assert
) {
2603 jQuery( document
).on( "focusin", function( e
) {
2604 assert
.ok( e
.type
=== "focusin", "got a focusin event on a document" );
2605 } ).trigger( "focusin" ).off( "focusin" );
2607 jQuery( window
).on( "focusin", function( e
) {
2608 assert
.ok( e
.type
=== "focusin", "got a focusin event on a window" );
2609 } ).trigger( "focusin" ).off( "focusin" );
2614 "focusin from an iframe",
2615 "event/focusinCrossFrame.html",
2616 function( assert
, framejQuery
, frameWin
, frameDoc
) {
2619 var done
= assert
.async(),
2621 input
= jQuery( frameDoc
).find( "#frame-input" );
2623 // Create a focusin handler on the parent; shouldn't affect the iframe's fate
2624 jQuery( "body" ).on( "focusin.iframeTest", function() {
2626 // Support: IE 9 - 11+
2627 // IE does propagate the event to the parent document. In this test
2628 // we mainly care about the inner element so we'll just skip this one
2630 if ( !document
.documentMode
) {
2631 assert
.ok( false, "fired a focusin event in the parent document" );
2635 input
.on( "focusin", function() {
2637 assert
.ok( true, "fired a focusin event in the iframe" );
2640 // Avoid a native event; Chrome can't force focus to another frame
2643 // Remove body handler manually since it's outside the fixture
2644 jQuery( "body" ).off( "focusin.iframeTest" );
2646 setTimeout( function() {
2648 // DOM focus is unreliable in TestSwarm
2649 if ( QUnit
.isSwarm
&& !focus
) {
2650 assert
.ok( true, "GAP: Could not observe focus change" );
2658 QUnit
.test( "focusin on document & window", function( assert
) {
2662 input
= jQuery( "<input />" );
2664 function increment() {
2668 input
.appendTo( "#qunit-fixture" );
2672 jQuery( window
).on( "focusout", increment
);
2673 jQuery( document
).on( "focusout", increment
);
2677 // DOM focus is unreliable in TestSwarm
2678 if ( QUnit
.isSwarm
&& counter
=== 0 ) {
2679 assert
.ok( true, "GAP: Could not observe focus change" );
2682 assert
.strictEqual( counter
, 2,
2683 "focusout handlers on document/window fired once only" );
2685 jQuery( window
).off( "focusout", increment
);
2686 jQuery( document
).off( "focusout", increment
);
2689 QUnit
.test( "element removed during focusout (gh-4417)", function( assert
) {
2692 var button
= jQuery( "<button>Click me</button>" );
2694 button
.appendTo( "#qunit-fixture" );
2696 button
.on( "click", function() {
2697 button
.trigger( "blur" );
2698 assert
.ok( true, "Removing the element didn't crash" );
2701 // Support: Chrome 86+
2702 // In Chrome, if an element having a focusout handler is blurred by
2703 // clicking outside of it, it invokes the handler synchronously. However,
2704 // if the click happens programmatically, the invocation is asynchronous.
2705 // As we have no way to simulate real user input in unit tests, simulate
2706 // this behavior by calling `jQuery.cleanData` & removing the element using
2708 button
[ 0 ].blur = function() {
2709 jQuery
.cleanData( [ this ] );
2710 this.parentNode
.removeChild( this );
2712 // Redefine `blur` to avoid a hard crash in Karma tests that stop
2713 // the test runner in case this test fails.
2714 this.blur
= jQuery
.noop
;
2717 button
[ 0 ].click();
2721 "jQuery.ready promise",
2722 "event/promiseReady.html",
2723 function( assert
, jQuery
, window
, document
, isOk
) {
2725 assert
.ok( isOk
, "$.when( $.ready ) works" );
2727 jQuery
.when
? QUnit
.test
: QUnit
.skip
2730 // need PHP here to make the incepted IFRAME hang
2733 "jQuery.ready uses interactive",
2734 "event/interactiveReady.html",
2735 function( assert
, jQuery
, window
, document
, isOk
) {
2737 assert
.ok( isOk
, "jQuery fires ready when the DOM can truly be interacted with" );
2743 "Focusing iframe element",
2744 "event/focusElem.html",
2745 function( assert
, jQuery
, window
, document
, isOk
) {
2747 assert
.ok( isOk
, "Focused an element in an iframe" );
2752 "triggerHandler(onbeforeunload)",
2753 "event/triggerunload.html",
2754 function( assert
, jQuery
, window
, document
, isOk
) {
2756 assert
.ok( isOk
, "Triggered onbeforeunload without an error" );
2760 // need PHP here to make the incepted IFRAME hang
2763 "jQuery.ready synchronous load with long loading subresources",
2764 "event/syncReady.html",
2765 function( assert
, jQuery
, window
, document
, isOk
) {
2767 assert
.ok( isOk
, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
2772 QUnit
.test( "change handler should be detached from element", function( assert
) {
2775 var $fixture
= jQuery( "<input type='text' id='change-ie-leak' />" ).appendTo( "body" ),
2776 originRemoveEvent
= jQuery
.removeEvent
,
2777 wrapperRemoveEvent = function( elem
, type
, handle
) {
2778 assert
.equal( "change", type
, "Event handler for 'change' event should be removed" );
2779 assert
.equal( "change-ie-leak", jQuery( elem
).attr( "id" ), "Event handler for 'change' event should be removed from appropriate element" );
2780 originRemoveEvent( elem
, type
, handle
);
2783 jQuery
.removeEvent
= wrapperRemoveEvent
;
2785 $fixture
.on( "change", function() {} );
2786 $fixture
.off( "change" );
2790 jQuery
.removeEvent
= originRemoveEvent
;
2793 QUnit
.test( "trigger click on checkbox, fires change event", function( assert
) {
2796 var check
= jQuery( "#check2" );
2797 var done
= assert
.async();
2799 check
.on( "change", function() {
2802 check
.off( "change" );
2803 assert
.ok( true, "Change event fired as a result of triggered click" );
2805 } ).trigger( "click" );
2808 QUnit
.test( "Namespace preserved when passed an Event (trac-12739)", function( assert
) {
2811 var markup
= jQuery(
2812 "<div id='parent'><div id='child'></div></div>"
2817 markup
.find( "div" )
2819 .on( "foo.bar", function( e
) {
2823 assert
.equal( e
.namespace, "bar", "namespace is bar" );
2824 jQuery( e
.target
).find( "div" ).each( function() {
2825 jQuery( this ).triggerHandler( e
);
2829 .on( "foo.bar2", function() {
2830 assert
.ok( false, "foo.bar2 called on trigger " + triggered
+ " id " + this.id
);
2833 markup
.trigger( "foo.bar" );
2834 markup
.trigger( jQuery
.Event( "foo.bar" ) );
2835 fooEvent
= jQuery
.Event( "foo" );
2836 fooEvent
.namespace = "bar";
2837 markup
.trigger( fooEvent
);
2840 assert
.equal( triggered
, 3, "foo.bar triggered" );
2843 QUnit
.test( "make sure events cloned correctly", function( assert
) {
2844 assert
.expect( 18 );
2847 fixture
= jQuery( "#qunit-fixture" ),
2848 checkbox
= jQuery( "#check1" ),
2849 p
= jQuery( "#firstp" );
2851 fixture
.on( "click change", function( event
, result
) {
2852 assert
.ok( result
, event
.type
+ " on original element is fired" );
2854 } ).on( "click", "#firstp", function( event
, result
) {
2855 assert
.ok( result
, "Click on original child element though delegation is fired" );
2857 } ).on( "change", "#check1", function( event
, result
) {
2858 assert
.ok( result
, "Change on original child element though delegation is fired" );
2861 p
.on( "click", function() {
2862 assert
.ok( true, "Click on original child element is fired" );
2865 checkbox
.on( "change", function() {
2866 assert
.ok( true, "Change on original child element is fired" );
2869 fixture
.clone().trigger( "click" ).trigger( "change" ); // 0 events should be fired
2871 clone
= fixture
.clone( true );
2873 clone
.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
2874 clone
.find( "#check1" ).trigger( "change", true ); // 3 events should fire
2877 clone
= fixture
.clone( true, true );
2878 clone
.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
2879 clone
.find( "#check1" ).trigger( "change", true ); // 3 events should fire
2885 p
.trigger( "click" ); // 0 should be fired
2886 checkbox
.trigger( "change" ); // 0 should be fired
2888 clone
.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
2889 clone
.find( "#check1" ).trigger( "change", true ); // 3 events should fire
2892 clone
.find( "p" ).eq( 0 ).trigger( "click" ); // 0 should be fired
2893 clone
.find( "#check1" ).trigger( "change" ); // 0 events should fire
2896 QUnit
.test( "String.prototype.namespace does not cause trigger() to throw (trac-13360)", function( assert
) {
2898 var errored
= false;
2900 String
.prototype.namespace = function() {};
2903 jQuery( "<p>" ).trigger( "foo.bar" );
2907 assert
.equal( errored
, false, "trigger() did not throw exception" );
2908 delete String
.prototype.namespace;
2911 QUnit
.test( "Inline event result is returned (trac-13993)", function( assert
) {
2914 var result
= jQuery( "<p onclick='return 42'>hello</p>" ).triggerHandler( "click" );
2916 assert
.equal( result
, 42, "inline handler returned value" );
2919 QUnit
.test( ".off() removes the expando when there's no more data", function( assert
) {
2923 div
= jQuery( "<div></div>" ).appendTo( "#qunit-fixture" );
2925 div
.on( "click", false );
2926 div
.on( "custom", function() {
2927 assert
.ok( true, "Custom event triggered" );
2929 div
.trigger( "custom" );
2930 div
.off( "click custom" );
2932 // Make sure the expando is gone
2933 for ( key
in div
[ 0 ] ) {
2934 if ( /^jQuery/.test( key
) ) {
2936 div
[ 0 ][ key
], undefined,
2937 "Expando was not removed when there was no more data"
2943 QUnit
.test( "jQuery.Event( src ) does not require a target property", function( assert
) {
2946 var event
= jQuery
.Event( { type
: "offtarget" } );
2948 assert
.equal( event
.type
, "offtarget", "correct type" );
2949 assert
.equal( event
.target
, undefined, "no target" );
2952 QUnit
.test( "preventDefault() on focusin does not throw exception", function( assert
) {
2955 var done
= assert
.async(),
2956 input
= jQuery( "<input/>" ).appendTo( "#form" );
2958 input
.on( "focusin", function( event
) {
2963 var exceptionCaught
;
2965 event
.preventDefault();
2966 } catch ( theException
) {
2967 exceptionCaught
= theException
;
2970 assert
.strictEqual( exceptionCaught
, undefined,
2971 "Preventing default on focusin throws no exception" );
2976 input
.trigger( "focus" );
2978 // DOM focus is unreliable in TestSwarm; set a simulated event workaround timeout
2979 setTimeout( function() {
2983 input
[ 0 ].addEventListener( "click", function( nativeEvent
) {
2984 jQuery
.event
.simulate( "focusin", this, jQuery
.event
.fix( nativeEvent
) );
2987 }, QUnit
.config
.testTimeout
/ 4 || 1000 );
2990 QUnit
.test( ".on('focus', fn) on a text node doesn't throw", function( assert
) {
2993 jQuery( document
.createTextNode( "text" ) )
2994 .on( "focus", function() {} );
2996 assert
.ok( true, "No crash" );
2999 QUnit
.test( "Donor event interference", function( assert
) {
3003 "<div id='donor-outer'>" +
3004 "<form id='donor-form'>" +
3005 "<input id='donor-input' type='checkbox' />" +
3008 ).appendTo( "#qunit-fixture" ),
3009 input
= jQuery( "#donor-input" );
3011 input
.on( "click", function( event
) {
3012 assert
.equal( event
.type
, "click", "click event at input" );
3013 assert
.ok( !event
.isPropagationStopped(), "click event at input is still propagating" );
3014 assert
.equal( typeof event
.originalEvent
, "object",
3015 "click event at input has originalEvent property" );
3017 outer
.on( "click", function( event
) {
3018 assert
.equal( event
.type
, "click", "click event at ancestor" );
3019 assert
.ok( !event
.isPropagationStopped(), "click event at ancestor is still propagating" );
3020 assert
.equal( typeof event
.originalEvent
, "object",
3021 "click event at ancestor has originalEvent property" );
3023 input
.on( "change", function( event
) {
3024 assert
.equal( event
.type
, "change", "change event at input" );
3025 assert
.equal( typeof event
.originalEvent
, "object",
3026 "change event at input has originalEvent property" );
3027 event
.stopPropagation();
3033 "simulated events shouldn't forward stopPropagation/preventDefault methods",
3034 function( assert
) {
3038 "<div id='donor-outer'>" +
3039 "<form id='donor-form'>" +
3040 "<input id='donor-input' type='checkbox' />" +
3043 ).appendTo( "#qunit-fixture" ),
3044 input
= jQuery( "#donor-input" ),
3047 jQuery( "#donor-form" )
3048 .on( "simulated", function( event
) {
3049 spy
.prevent
= sinon
.stub( event
.originalEvent
, "preventDefault" );
3050 event
.preventDefault();
3052 .on( "simulated", function( event
) {
3053 spy
.stop
= sinon
.stub( event
.originalEvent
, "stopPropagation" );
3054 event
.stopPropagation();
3056 .on( "simulated", function( event
) {
3057 spy
.immediate
= sinon
.stub( event
.originalEvent
, "stopImmediatePropagation" );
3058 event
.stopImmediatePropagation();
3060 .on( "simulated", function( event
) {
3061 assert
.ok( false, "simulated event immediate propagation stopped" );
3064 .on( "simulated", function( event
) {
3065 assert
.ok( false, "simulated event propagation stopped" );
3068 // Force a simulated event
3069 input
[ 0 ].addEventListener( "click", function( nativeEvent
) {
3070 jQuery
.event
.simulate( "simulated", this, jQuery
.event
.fix( nativeEvent
) );
3074 assert
.strictEqual( spy
.prevent
.called
, false, "Native preventDefault not called" );
3075 assert
.strictEqual( spy
.stop
.called
, false, "Native stopPropagation not called" );
3076 assert
.strictEqual( spy
.immediate
.called
, false,
3077 "Native stopImmediatePropagation not called" );
3081 QUnit
.test( "originalEvent type of simulated event", function( assert
) {
3085 "<div id='donor-outer'>" +
3086 "<form id='donor-form'>" +
3087 "<input id='donor-input' type='text' />" +
3090 ).appendTo( "#qunit-fixture" ),
3091 input
= jQuery( "#donor-input" ),
3092 done
= assert
.async(),
3093 finish = function() {
3095 // Remove jQuery handlers to ensure removal of capturing handlers on the document
3096 outer
.off( "focusin" );
3101 outer
.on( "focusin", function( event
) {
3102 assert
.equal( event
.type
, "focusin", "focusin event at ancestor" );
3103 assert
.equal( event
.originalEvent
.type
, "click",
3104 "focus event at ancestor has correct originalEvent type" );
3105 setTimeout( finish
);
3108 input
[ 0 ].addEventListener( "click", function( nativeEvent
) {
3109 jQuery
.event
.simulate( "focusin", this, jQuery
.event
.fix( nativeEvent
) );
3114 QUnit
.test( "trigger('click') on radio passes extra params", function( assert
) {
3116 var $radio
= jQuery( "<input type='radio' />" ).appendTo( "#qunit-fixture" )
3117 .on( "click", function( e
, data
) {
3118 assert
.ok( data
, "Trigger data is passed to radio click handler" );
3121 $radio
.trigger( "click", [ true ] );
3124 QUnit
.test( "focusout/focusin support", function( assert
) {
3128 parent
= jQuery( "<div>" ),
3129 input
= jQuery( "<input>" ),
3130 inputExternal
= jQuery( "<input>" );
3132 parent
.append( input
);
3133 jQuery( "#qunit-fixture" ).append( parent
).append( inputExternal
);
3135 // initially, lose focus
3136 inputExternal
[ 0 ].focus();
3139 .on( "focus", function() {
3140 assert
.ok( false, "parent: focus not fired" );
3142 .on( "focusin", function() {
3143 assert
.ok( true, "parent: focusin fired" );
3145 .on( "blur", function() {
3146 assert
.ok( false, "parent: blur not fired" );
3148 .on( "focusout", function() {
3149 assert
.ok( true, "parent: focusout fired" );
3153 .on( "focus", function() {
3154 assert
.ok( true, "element: focus fired" );
3156 .on( "focusin", function() {
3157 assert
.ok( true, "element: focusin fired" );
3160 .on( "blur", function() {
3161 assert
.ok( true, "parent: blur fired" );
3163 .on( "focusout", function() {
3164 assert
.ok( true, "element: focusout fired" );
3171 inputExternal
[ 0 ].focus();
3173 // DOM focus is unreliable in TestSwarm
3174 if ( QUnit
.isSwarm
&& !focus
) {
3175 assert
.ok( true, "GAP: Could not observe focus change" );
3176 assert
.ok( true, "GAP: Could not observe focus change" );
3177 assert
.ok( true, "GAP: Could not observe focus change" );
3178 assert
.ok( true, "GAP: Could not observe focus change" );
3179 assert
.ok( true, "GAP: Could not observe focus change" );
3180 assert
.ok( true, "GAP: Could not observe focus change" );
3188 QUnit
.test( "focus-blur order (trac-12868)", function( assert
) {
3192 $text
= jQuery( "#text1" ),
3193 $radio
= jQuery( "#radio1" );
3195 $radio
[ 0 ].focus();
3198 .on( "focus", function() {
3199 assert
.equal( order
++, 1, "text focus" );
3201 .on( "blur", function() {
3202 assert
.equal( order
++, 0, "text blur" );
3205 .on( "focus", function() {
3206 assert
.equal( order
++, 1, "radio focus" );
3208 .on( "blur", function() {
3209 assert
.equal( order
++, 0, "radio blur" );
3212 // Enabled input getting focus
3214 assert
.equal( document
.activeElement
, $radio
[ 0 ], "radio has focus" );
3215 $text
.trigger( "focus" );
3217 // DOM focus is unreliable in TestSwarm
3218 if ( QUnit
.isSwarm
&& order
=== 0 ) {
3219 assert
.ok( true, "GAP: Could not observe focus change" );
3220 assert
.ok( true, "GAP: Could not observe focus change" );
3223 assert
.equal( document
.activeElement
, $text
[ 0 ], "text has focus" );
3225 // Run handlers without native method on an input
3227 $radio
.triggerHandler( "focus" );
3234 QUnit
.test( "Event handling works with multiple async focus events (gh-4350)", function( assert
) {
3238 input
= jQuery( "#name" ),
3239 done
= assert
.async();
3242 .on( "focus", function() {
3244 assert
.ok( true, "received focus event, expecting " + remaining
+ " more" );
3245 if ( remaining
> 0 ) {
3246 input
.trigger( "blur" );
3251 // Support: <=IE 11+
3252 // In IE, one of the blurs sometimes triggers a focus on body
3253 // which in turn restores focus to the input, leading to 4 assertions
3254 // firing instead of three. This only happens if other tests are
3255 // running on the same test page. Avoid this issue in tests by removing
3256 // the handler early.
3257 input
.off( "focus" );
3262 .on( "blur", function() {
3263 setTimeout( function() {
3264 input
.trigger( "focus" );
3269 input
.trigger( "focus" );
3271 // DOM focus is unreliable in TestSwarm
3272 setTimeout( function() {
3273 if ( QUnit
.isSwarm
&& remaining
=== 3 ) {
3274 assert
.ok( true, "GAP: Could not observe focus change" );
3275 assert
.ok( true, "GAP: Could not observe focus change" );
3276 assert
.ok( true, "GAP: Could not observe focus change" );
3277 setTimeout( function() {
3284 // Support: IE <=9 - 11+
3285 // focus and blur events are asynchronous.
3286 // The browser window must be topmost for this to work properly!!
3287 QUnit
.test( "async focus queues properly (gh-4859)", function( assert
) {
3290 var $text
= jQuery( "#text1" ),
3291 $radio
= jQuery( "#radio1" ),
3292 done
= assert
.async();
3294 $text
.trigger( "focus" );
3295 $radio
.trigger( "focus" );
3296 $text
.trigger( "focus" );
3298 setTimeout( function() {
3299 assert
.equal( document
.activeElement
, $text
[ 0 ], "focus follows the last trigger" );
3304 // Support: IE <=9 - 11+
3305 // focus and blur events are asynchronous.
3306 // The browser window must be topmost for this to work properly!!
3307 QUnit
.test( "async focus queues properly with blur (gh-4856)", function( assert
) {
3310 var $text
= jQuery( "#text1" ),
3311 done
= assert
.async();
3313 $text
.trigger( "focus" );
3314 $text
.trigger( "blur" );
3315 $text
.trigger( "focus" );
3317 setTimeout( function() {
3318 assert
.equal( document
.activeElement
, $text
[ 0 ], "focus-after-blur is respected" );
3323 QUnit
.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", function( assert
) {
3324 assert
.expect( 17 );
3326 var parent
= supportjQuery(
3327 "<div class='parent'><input type='checkbox'><input type='radio'></div>"
3328 ).appendTo( "#qunit-fixture" ),
3329 targets
= jQuery( parent
[ 0 ].childNodes
),
3330 checkbox
= jQuery( targets
[ 0 ] ),
3331 data
= [ "arg1", "arg2" ],
3335 assert
.strictEqual( targets
[ 0 ].checked
, false, "checkbox unchecked before click" );
3336 assert
.strictEqual( targets
[ 1 ].checked
, false, "radio unchecked before click" );
3337 targets
.add( parent
).on( "click", function( event
) {
3338 var type
= event
.target
.type
,
3339 level
= event
.currentTarget
=== parent
[ 0 ] ? "parent" : "";
3340 assert
.strictEqual( event
.target
.checked
, true,
3341 type
+ " toggled before invoking " + level
+ " handler" );
3342 assert
.deepEqual( slice
.call( arguments
, 1 ), data
,
3343 type
+ " " + level
+ " handler received correct data" );
3345 targets
.trigger( "click", data
);
3346 assert
.strictEqual( targets
[ 0 ].checked
, true,
3347 "checkbox toggled after click (default action)" );
3348 assert
.strictEqual( targets
[ 1 ].checked
, true,
3349 "radio toggled after event (default action)" );
3352 assert
.notEqual( document
.activeElement
, checkbox
[ 0 ],
3353 "element not focused before focus event" );
3354 checkbox
.on( "focus blur", function( event
) {
3355 var type
= event
.type
;
3356 assert
.deepEqual( slice
.call( arguments
, 1 ), data
,
3357 type
+ " handler received correct data" );
3359 if ( QUnit
.isIE
&& type
=== "focus" ) {
3361 // Support: <=IE 11+
3362 // In IE, one of the blurs sometimes triggers a focus on body
3363 // which in turn restores focus to the input, leading to 4 assertions
3364 // firing instead of three. This only happens if other tests are
3365 // running on the same test page. Avoid this issue in tests by removing
3366 // the handler early.
3367 checkbox
.off( "focus" );
3370 checkbox
.trigger( "focus", data
);
3372 assert
.strictEqual( document
.activeElement
, checkbox
[ 0 ],
3373 "element focused after focus event (default action)" );
3374 checkbox
.trigger( "blur", data
);
3376 assert
.notEqual( document
.activeElement
, checkbox
[ 0 ],
3377 "element not focused after blur event (default action)" );
3380 QUnit
.test( "focus change during a focus handler (gh-4382)", function( assert
) {
3383 var done
= assert
.async(),
3384 select
= jQuery( "<select><option selected='selected'>A</option></select>" ),
3385 button
= jQuery( "<button>Focus target</button>" );
3387 jQuery( "#qunit-fixture" )
3391 select
.on( "focus", function() {
3392 button
.trigger( "focus" );
3395 jQuery( document
).on( "focusin.focusTests", function( ev
) {
3397 // In IE focus is async so focusin on document is fired multiple times,
3398 // for each of the elements. In other browsers it's fired just once, for
3400 if ( ev
.target
=== button
[ 0 ] ) {
3401 assert
.ok( true, "focusin propagated to document from the button" );
3405 select
.trigger( "focus" );
3407 setTimeout( function() {
3408 assert
.strictEqual( document
.activeElement
, button
[ 0 ], "Focus redirect worked" );
3409 jQuery( document
).off( ".focusTests" );
3414 QUnit
.test( "trigger(focus) works after .on(focus).off(focus) (gh-4867)", function( assert
) {
3417 var input
= jQuery( "<input />" );
3419 input
.appendTo( "#qunit-fixture" );
3422 .on( "focus", function() {} )
3425 input
.trigger( "focus" );
3427 assert
.equal( document
.activeElement
, input
[ 0 ], "input has focus" );
3430 QUnit
.test( "trigger(focus) works after focusing when hidden (gh-4950)", function( assert
) {
3433 var input
= jQuery( "<input />" );
3435 input
.appendTo( "#qunit-fixture" );
3438 .css( "display", "none" )
3440 .css( "display", "" )
3441 .trigger( "focus" );
3443 assert
.equal( document
.activeElement
, input
[ 0 ], "input has focus" );
3446 QUnit
.test( "trigger(focus) fires native & jQuery handlers (gh-5015)", function( assert
) {
3449 var input
= jQuery( "<input />" ),
3451 // Support: IE 9 - 11+
3452 // focus is async in IE; we now emulate it via sync focusin in jQuery
3453 // but this test also attaches native handlers.
3454 done
= assert
.async( 3 );
3456 input
.appendTo( "#qunit-fixture" );
3458 input
[ 0 ].addEventListener( "focus", function() {
3459 assert
.ok( true, "1st native handler fired" );
3463 input
.on( "focus", function() {
3464 assert
.ok( true, "jQuery handler fired" );
3468 input
[ 0 ].addEventListener( "focus", function() {
3469 assert
.ok( true, "2nd native handler fired" );
3473 input
.trigger( "focus" );
3476 // TODO replace with an adaptation of
3477 // https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464
3481 checkbox
: "<input type='checkbox'>",
3482 radio
: "<input type='radio'>"
3484 function( type
, html
) {
3485 makeTestForGh3751( type
, html
);
3486 makeTestForGh5015( type
, html
);
3490 function makeTestForGh3751( type
, html
) {
3491 var testName
= "native-backed namespaced clicks are handled correctly (gh-3751) - " + type
;
3492 QUnit
.test( testName
, function( assert
) {
3495 var parent
= supportjQuery( "<div class='parent'>" + html
+ "</div>" ),
3496 target
= jQuery( parent
[ 0 ].firstChild
);
3498 parent
.appendTo( "#qunit-fixture" );
3500 target
.add( parent
)
3501 .on( "click.notFired", function( event
) {
3502 assert
.ok( false, "namespaced event should not be received" +
3503 " by wrong-namespace listener at " + event
.currentTarget
.nodeName
);
3505 .on( "click.fired", function( event
) {
3506 assert
.equal( event
.target
.checked
, true,
3507 "toggled before invoking handler at " + event
.currentTarget
.nodeName
);
3509 .on( "click", function( event
) {
3510 assert
.ok( false, "namespaced event should not be received" +
3511 " by non-namespaced listener at " + event
.currentTarget
.nodeName
);
3514 target
.trigger( "click.fired" );
3518 function makeTestForGh5015( type
, html
) {
3519 var testName
= "trigger(click) fires native & jQuery handlers (gh-5015) - " + type
;
3520 QUnit
.test( testName
, function( assert
) {
3523 var parent
= supportjQuery( "<div class='parent'>" + html
+ "</div>" ),
3524 input
= jQuery( parent
[ 0 ].firstChild
);
3526 parent
.appendTo( "#qunit-fixture" );
3528 input
[ 0 ].addEventListener( "click", function() {
3529 assert
.ok( true, "1st native handler fired" );
3532 input
.on( "click", function() {
3533 assert
.ok( true, "jQuery handler fired" );
3536 input
[ 0 ].addEventListener( "click", function() {
3537 assert
.ok( true, "2nd native handler fired" );
3540 input
.trigger( "click" );