Build: replace CRLF with LF during minify
[jquery.git] / test / unit / event.js
blob920b2a182d3e2d1774797619e6330bfdeeb08167
1 QUnit.module( "event", {
2 beforeEach: function() {
3 document.body.focus();
4 },
5 afterEach: moduleTeardown
6 } );
8 QUnit.test( "null or undefined handler", function( assert ) {
9 assert.expect( 4 );
11 // Supports Fixes bug trac-7229
12 try {
13 jQuery( "#firstp" ).on( "click", null );
14 assert.ok( true, "Passing a null handler will not throw an exception" );
15 } catch ( e ) {}
17 try {
18 jQuery( "#firstp" ).on( "click", undefined );
19 assert.ok( true, "Passing an undefined handler will not throw an exception" );
20 } catch ( e ) {}
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" );
28 } );
30 QUnit.test( "on() with non-null,defined data", function( assert ) {
32 assert.expect( 2 );
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" );
46 } );
48 QUnit.test( "Handler changes and .trigger() order", function( assert ) {
49 assert.expect( 1 );
51 var markup = jQuery(
52 "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
54 path = "";
56 markup
57 .find( "*" ).addBack().on( "click", function() {
58 path += this.nodeName.toLowerCase() + " ";
59 } )
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();
66 } );
68 markup.find( "b" ).trigger( "click" );
70 assert.equal( path, "b p div div ", "Delivered all events" );
72 markup.remove();
73 } );
75 QUnit.test( "on(), with data", function( assert ) {
76 assert.expect( 4 );
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." );
87 test = function() {};
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 );
92 } );
94 QUnit.test( "click(), with data", function( assert ) {
95 assert.expect( 3 );
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." );
103 } );
105 QUnit.test( "on(), with data, trigger with data", function( assert ) {
106 assert.expect( 4 );
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 );
114 } );
116 QUnit.test( "on(), multiple events at once", function( assert ) {
117 assert.expect( 2 );
118 var handler,
119 clickCounter = 0,
120 mouseoverCounter = 0;
121 handler = function( event ) {
122 if ( event.type === "click" ) {
123 clickCounter += 1;
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" );
132 } );
134 QUnit.test( "on(), five events at once", function( assert ) {
135 assert.expect( 1 );
137 var count = 0,
138 handler = function() {
139 count++;
142 jQuery( "#firstp" ).on( "click mouseover foo bar baz", handler )
143 .trigger( "click" ).trigger( "mouseover" )
144 .trigger( "foo" ).trigger( "bar" )
145 .trigger( "baz" );
147 assert.equal( count, 5, "on() five events at once" );
148 } );
150 QUnit.test( "on(), multiple events at once and namespaces", function( assert ) {
151 assert.expect( 7 );
153 var cur, div,
154 obj = {};
156 div = jQuery( "<div></div>" ).on( "focusin.a", function( e ) {
157 assert.equal( e.type, cur, "Verify right single event was fired." );
158 } );
160 cur = "focusin";
161 div.trigger( "focusin.a" );
163 // manually clean up detached elements
164 div.remove();
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." );
169 } );
171 cur = "click";
172 div.trigger( "click" );
174 cur = "mouseover";
175 div.trigger( "mouseover" );
177 // manually clean up detached elements
178 div.remove();
180 div = jQuery( "<div></div>" ).on( "focusin.a focusout.b", function( e ) {
181 assert.equal( e.type, cur, "Verify right multi event was fired." );
182 } );
184 cur = "focusin";
185 div.trigger( "focusin.a" );
187 cur = "focusout";
188 div.trigger( "focusout.b" );
190 // manually clean up detached elements
191 div.remove();
192 } );
194 QUnit.test( "on(), namespace with special add", function( assert ) {
195 assert.expect( 27 );
197 var i = 0,
198 div = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" ).on( "test", function() {
199 assert.ok( true, "Test event fired." );
200 } );
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 ) {
216 e.xyz = ++i;
217 handler.apply( this, arguments );
220 remove: function() {
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." );
228 } );
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." );
233 } );
235 // Should trigger 5
236 div.trigger( "test", 33.33 );
238 // Should trigger 2
239 div.trigger( "test.a", "George Harrison" );
241 // Should trigger 2
242 div.trigger( "test.b", { year: 1982 } );
244 // Should trigger 4
245 div.off( "test" );
247 div = jQuery( "<div></div>" ).on( "test", function() {
248 assert.ok( true, "Test event fired." );
249 } );
251 // Should trigger 2
252 div.appendTo( "#qunit-fixture" ).remove();
254 delete jQuery.event.special.test;
255 } );
257 QUnit.test( "on(), no data", function( assert ) {
258 assert.expect( 1 );
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" );
263 } );
265 QUnit.test( "on/one/off(Object)", function( assert ) {
266 assert.expect( 6 );
268 var $elem,
269 clickCounter = 0,
270 mouseoverCounter = 0;
272 function handler( event ) {
273 if ( event.type === "click" ) {
274 clickCounter++;
275 } else if ( event.type === "mouseover" ) {
276 mouseoverCounter++;
280 function handlerWithData( event ) {
281 if ( event.type === "click" ) {
282 clickCounter += event.data;
283 } else if ( event.type === "mouseover" ) {
284 mouseoverCounter += event.data;
288 function trigger() {
289 $elem.trigger( "click" ).trigger( "mouseover" );
292 $elem = jQuery( "#firstp" )
294 // Regular bind
295 .on( {
296 "click":handler,
297 "mouseover":handler
300 // Bind with data
301 .one( {
302 "click":handlerWithData,
303 "mouseover":handlerWithData
304 }, 2 );
306 trigger();
308 assert.equal( clickCounter, 3, "on(Object)" );
309 assert.equal( mouseoverCounter, 3, "on(Object)" );
311 trigger();
312 assert.equal( clickCounter, 4, "on(Object)" );
313 assert.equal( mouseoverCounter, 4, "on(Object)" );
315 jQuery( "#firstp" ).off( {
316 "click":handler,
317 "mouseover":handler
318 } );
320 trigger();
321 assert.equal( clickCounter, 4, "on(Object)" );
322 assert.equal( mouseoverCounter, 4, "on(Object)" );
323 } );
325 QUnit.test( "on/off(Object), on/off(Object, String)", function( assert ) {
326 assert.expect( 6 );
328 var events,
329 clickCounter = 0,
330 mouseoverCounter = 0,
331 $p = jQuery( "#firstp" ),
332 $a = $p.find( "a" ).eq( 0 );
334 events = {
335 "click": function( event ) {
336 clickCounter += ( event.data || 1 );
338 "mouseover": function( event ) {
339 mouseoverCounter += ( event.data || 1 );
343 function trigger() {
344 $a.trigger( "click" ).trigger( "mouseover" );
347 jQuery( document ).on( events, "#firstp a" );
348 $p.on( events, "a", 2 );
350 trigger();
351 assert.equal( clickCounter, 3, "on" );
352 assert.equal( mouseoverCounter, 3, "on" );
354 $p.off( events, "a" );
356 trigger();
357 assert.equal( clickCounter, 4, "off" );
358 assert.equal( mouseoverCounter, 4, "off" );
360 jQuery( document ).off( events, "#firstp a" );
362 trigger();
363 assert.equal( clickCounter, 4, "off" );
364 assert.equal( mouseoverCounter, 4, "off" );
365 } );
367 QUnit.test( "on immediate propagation", function( assert ) {
368 assert.expect( 2 );
370 var lastClick,
371 $p = jQuery( "#firstp" ),
372 $a = $p.find( "a" ).eq( 0 );
374 lastClick = "";
375 jQuery( document ).on( "click", "#firstp a", function( e ) {
376 lastClick = "click1";
377 e.stopImmediatePropagation();
378 } );
379 jQuery( document ).on( "click", "#firstp a", function() {
380 lastClick = "click2";
381 } );
382 $a.trigger( "click" );
383 assert.equal( lastClick, "click1", "on stopImmediatePropagation" );
384 jQuery( document ).off( "click", "#firstp a" );
386 lastClick = "";
387 $p.on( "click", "a", function( e ) {
388 lastClick = "click1";
389 e.stopImmediatePropagation();
390 } );
391 $p.on( "click", "a", function() {
392 lastClick = "click2";
393 } );
394 $a.trigger( "click" );
395 assert.equal( lastClick, "click1", "on stopImmediatePropagation" );
396 $p.off( "click", "**" );
397 } );
399 QUnit.test( "on bubbling, isDefaultPrevented, stopImmediatePropagation", function( assert ) {
400 assert.expect( 3 );
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 ) {
415 e.preventDefault();
416 } );
417 $main.on( "click", "#foo", function( e ) {
418 assert.equal( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
419 } );
420 fakeClick( $anchor2 );
421 $anchor2.off( "click" );
422 $main.off( "click", "**" );
423 $anchor2.on( "click", function() {
425 // Let the default action occur
426 } );
427 $main.on( "click", "#foo", function( e ) {
428 assert.equal( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
429 } );
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" );
437 } );
438 $anchor2[ 0 ].addEventListener( "click", neverCallMe, false );
439 fakeClick( $anchor2 );
440 $anchor2[ 0 ].removeEventListener( "click", neverCallMe );
441 } );
443 QUnit.test( "triggered events stopPropagation() for natively-bound events", function( assert ) {
444 assert.expect( 1 );
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" );
453 e.stopPropagation();
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 );
461 } );
463 QUnit.test( "trigger() works with events that were previously stopped", function( assert ) {
464 assert.expect( 0 );
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 );
481 } );
484 QUnit.test( "on(), iframes", function( assert ) {
485 assert.expect( 1 );
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" );
493 } );
495 QUnit.test( "on(), trigger change on select", function( assert ) {
496 assert.expect( 5 );
497 var counter = 0;
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" );
504 } );
506 QUnit.test( "on(), namespaced events, cloned events", function( assert ) {
507 assert.expect( 18 );
509 var firstp = jQuery( "#firstp" );
511 firstp.on( "custom.test", function() {
512 assert.ok( false, "Custom event triggered" );
513 } );
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" );
518 } );
520 firstp.on( "click.test", function( e ) {
521 var check = "click";
522 assert.ok( true, "Namespaced click triggered" );
523 if ( e.namespace ) {
524 check += "test";
526 assert.equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
527 } );
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" );
558 } );
560 QUnit.test( "on(), multi-namespaced events", function( assert ) {
561 assert.expect( 6 );
563 var order = [
564 "click.test.abc",
565 "click.test.abc",
566 "click.test",
567 "click.test.abc",
568 "click.test",
569 "custom.test2"
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" );
578 } );
580 jQuery( "#firstp" ).on( "custom.test2", function() {
581 check( "custom.test2", "Custom event triggered" );
582 } );
584 jQuery( "#firstp" ).on( "click.test", function() {
585 check( "click.test", "Normal click triggered" );
586 } );
588 jQuery( "#firstp" ).on( "click.test.abc", function() {
589 check( "click.test.abc", "Namespaced click triggered" );
590 } );
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" );
616 } );
618 QUnit.test( "namespace-only event binding is a no-op", function( assert ) {
619 assert.expect( 2 );
621 jQuery( "#firstp" )
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
629 .off( ".whoops" )
630 .trigger( "whoops" ) // 2
631 .off( "whoops" );
632 } );
634 QUnit.test( "Empty namespace is ignored", function( assert ) {
635 assert.expect( 1 );
637 jQuery( "#firstp" )
638 .on( "meow.", function( e ) {
639 assert.equal( e.namespace, "", "triggered a namespace-less meow event" );
641 .trigger( "meow." )
642 .off( "meow." );
643 } );
645 QUnit.test( "on(), with same function", function( assert ) {
646 assert.expect( 2 );
648 var count = 0, func = function() {
649 count++;
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." );
661 } );
663 QUnit.test( "on(), make sure order is maintained", function( assert ) {
664 assert.expect( 1 );
666 var elem = jQuery( "#firstp" ), log = [], check = [];
668 jQuery.each( new Array( 100 ), function( i ) {
669 elem.on( "click", function() {
670 log.push( i );
671 } );
673 check.push( i );
675 } );
677 elem.trigger( "click" );
679 assert.equal( log.join( "," ), check.join( "," ), "Make sure order was maintained." );
681 elem.off( "click" );
682 } );
684 QUnit.test( "on(), with different this object", function( assert ) {
685 assert.expect( 4 );
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 );
696 jQuery( "#firstp" )
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." );
701 } );
703 QUnit.test( "on(name, false), off(name, false)", function( assert ) {
704 assert.expect( 3 );
706 var main = 0;
707 jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
708 jQuery( "#ap" ).trigger( "click" );
709 assert.equal( main, 1, "Verify that the trigger happened correctly." );
711 main = 0;
712 jQuery( "#ap" ).on( "click", false );
713 jQuery( "#ap" ).trigger( "click" );
714 assert.equal( main, 0, "Verify that no bubble happened." );
716 main = 0;
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" );
723 } );
725 QUnit.test( "on(name, selector, false), off(name, selector, false)", function( assert ) {
726 assert.expect( 3 );
728 var main = 0;
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." );
734 main = 0;
735 jQuery( "#ap" ).on( "click", "#groups", false );
736 jQuery( "#groups" ).trigger( "click" );
737 assert.equal( main, 0, "Verify that no bubble happened." );
739 main = 0;
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" );
744 } );
746 QUnit.test( "on()/trigger()/off() on plain object", function( assert ) {
747 assert.expect( 7 );
749 var events,
750 obj = {};
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" );
758 jQuery( obj ).on( {
759 "test": function() {
760 assert.ok( true, "Custom event run." );
762 "submit": function() {
763 assert.ok( true, "Custom submit event run." );
765 } );
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." );
773 // Should trigger 1
774 jQuery( obj ).trigger( "test" );
775 jQuery( obj ).trigger( "submit" );
777 jQuery( obj ).off( "test" );
778 jQuery( obj ).off( "submit" );
780 // Should trigger 0
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" );
789 } );
791 QUnit.test( "off(type)", function( assert ) {
792 assert.expect( 1 );
794 var message, func,
795 $elem = jQuery( "#firstp" );
797 function error() {
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 )
822 .off()
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" );
828 } );
829 func = function() {};
830 jQuery( document )
831 .on( "click", func )
832 .off( "click", func )
833 .trigger( "click" )
834 .off( "click" );
835 } );
837 QUnit.test( "off(eventObject)", function( assert ) {
838 assert.expect( 4 );
840 var $elem = jQuery( "#firstp" ),
841 num;
843 function check( expected ) {
844 num = 0;
845 $elem.trigger( "foo" ).triggerHandler( "bar" );
846 assert.equal( num, expected, "Check the right handlers are triggered" );
849 $elem
851 // This handler shouldn't be unbound
852 .on( "foo", function() {
853 num += 1;
855 .on( "foo", function( e ) {
856 $elem.off( e );
857 num += 2;
860 // Neither this one
861 .on( "bar", function() {
862 num += 4;
863 } );
865 check( 7 );
866 check( 5 );
868 $elem.off( "bar" );
869 check( 1 );
871 $elem.off();
872 check( 0 );
873 } );
875 QUnit.test( "mouseover triggers mouseenter", function( assert ) {
876 assert.expect( 1 );
878 var count = 0,
879 elem = jQuery( "<a></a>" );
880 elem.on( "mouseenter", function() {
881 count++;
882 } );
883 elem.trigger( "mouseover" );
884 assert.equal( count, 1, "make sure mouseover triggers a mouseenter" );
886 elem.remove();
887 } );
889 QUnit.test( "pointerover triggers pointerenter", function( assert ) {
890 assert.expect( 1 );
892 var count = 0,
893 elem = jQuery( "<a></a>" );
894 elem.on( "pointerenter", function() {
895 count++;
896 } );
897 elem.trigger( "pointerover" );
898 assert.equal( count, 1, "make sure pointerover triggers a pointerenter" );
900 elem.remove();
901 } );
903 QUnit.test( "withinElement implemented with jQuery.contains()", function( assert ) {
905 assert.expect( 1 );
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 );
911 } );
913 jQuery( "#jc-inner" ).trigger( "mouseenter" );
914 } );
916 QUnit.test( "mouseenter, mouseleave don't catch exceptions", function( assert ) {
917 assert.expect( 2 );
919 var elem = jQuery( "#firstp" ).on( "mouseenter mouseleave", function() {
920 throw "an Exception";
921 } );
923 try {
924 elem.trigger( "mouseenter" );
925 } catch ( e ) {
926 assert.equal( e, "an Exception", "mouseenter doesn't catch exceptions" );
929 try {
930 elem.trigger( "mouseleave" );
931 } catch ( e ) {
932 assert.equal( e, "an Exception", "mouseleave doesn't catch exceptions" );
934 } );
936 QUnit.test( "trigger() bubbling", function( assert ) {
937 assert.expect( 18 );
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" );
980 } );
982 QUnit.test( "trigger(type, [data], [fn])", function( assert ) {
983 assert.expect( 16 );
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" );
991 return "test";
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" );
1003 } );
1005 jQuery( document ).on( "mouseleave", "#firstp", function() {
1006 assert.ok( true, "Trigger mouseleave bound by on" );
1007 } );
1009 $elem.trigger( "mouseenter" );
1011 $elem.trigger( "mouseleave" );
1013 jQuery( document ).off( "mouseenter mouseleave", "#firstp" );
1015 // Triggers handlers and native
1016 // Trigger 5
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)
1025 // Triggers 5
1026 assert.equal( $elem.triggerHandler( "click", [ 1, "2", "abc" ] ), "test", "Verify handler response" );
1028 pass = true;
1029 try {
1030 elem2 = jQuery( "#form input" ).eq( 0 );
1031 elem2.get( 0 ).style.display = "none";
1032 elem2.trigger( "focus" );
1033 } catch ( e ) {
1034 pass = false;
1036 assert.ok( pass, "Trigger focus on hidden element" );
1038 pass = true;
1039 try {
1040 jQuery( "#qunit-fixture table" ).eq( 0 ).on( "test:test", function() {} ).trigger( "test:test" );
1041 } catch ( e ) {
1042 pass = false;
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." );
1051 return false;
1052 } );
1054 // Trigger 1
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." );
1061 return false;
1062 } );
1064 // Trigger 1
1065 form.trigger( "submit" );
1067 jQuery( document ).off( "submit" );
1069 form.remove();
1070 } );
1072 QUnit.test( "submit event bubbles on copied forms (trac-11649)", function( assert ) {
1073 assert.expect( 3 );
1075 var $formByClone, $formByHTML,
1076 $testForm = jQuery( "#testForm" ),
1077 $fixture = jQuery( "#qunit-fixture" ),
1078 $wrapperDiv = jQuery( "<div></div>" ).appendTo( $fixture );
1080 function noSubmit( e ) {
1081 e.preventDefault();
1083 function delegatedSubmit() {
1084 assert.ok( true, "Make sure submit event bubbles up." );
1085 return false;
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" );
1102 // Clean up
1103 $wrapperDiv.remove();
1104 $fixture.off( "submit", "form", delegatedSubmit );
1105 $testForm.off( "submit", noSubmit );
1106 } );
1108 QUnit.test( "change event bubbles on copied forms (trac-11796)", function( assert ) {
1109 assert.expect( 3 );
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." );
1118 return false;
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" );
1135 // Clean up
1136 $wrapperDiv.remove();
1137 $fixture.off( "change", "form", delegatedChange );
1138 } );
1140 QUnit.test( "trigger(eventObject, [data], [fn])", function( assert ) {
1141 assert.expect( 28 );
1143 var event,
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 ) {
1169 // Tries bubbling
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" );
1174 } );
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!" } );
1184 $parent.off();
1186 function error() {
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();
1205 return "result";
1206 } );
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" );
1219 $child.off();
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" );
1228 } );
1230 QUnit.test( ".trigger() bubbling on disconnected elements (trac-10489)", function( assert ) {
1231 assert.expect( 2 );
1233 jQuery( window ).on( "click", function() {
1234 assert.ok( false, "click fired on window" );
1235 } );
1237 jQuery( "<div><p>hi</p></div>" )
1238 .on( "click", function() {
1239 assert.ok( true, "click fired on div" );
1241 .find( "p" )
1242 .on( "click", function() {
1243 assert.ok( true, "click fired on p" );
1245 .trigger( "click" )
1246 .off( "click" )
1247 .end()
1248 .off( "click" )
1249 .remove();
1251 jQuery( window ).off( "click" );
1252 } );
1254 QUnit.test( ".trigger() doesn't bubble load event (trac-10717)", function( assert ) {
1255 assert.expect( 1 );
1257 jQuery( window ).on( "load", function() {
1258 assert.ok( false, "load fired on window" );
1259 } );
1261 jQuery( "<img src='" + baseURL + "1x1.jpg' />" )
1262 .appendTo( "body" )
1263 .on( "load", function() {
1264 assert.ok( true, "load fired on img" );
1266 .trigger( "load" )
1267 .remove();
1269 jQuery( window ).off( "load" );
1270 } );
1272 QUnit.test( "Delegated events in SVG (trac-10791; trac-13180)", function( assert ) {
1273 assert.expect( 2 );
1275 var useElem, e,
1276 svg = jQuery(
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>" +
1282 "</svg>"
1285 jQuery( "#qunit-fixture" )
1286 .append( svg )
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']" )
1294 .trigger( "click" )
1295 .end();
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" );
1307 } );
1309 QUnit.test( "Delegated events with malformed selectors (gh-3071)", function( assert ) {
1310 assert.expect( 3 );
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" );
1322 } );
1324 QUnit.test( "Delegated events in forms (trac-10844; trac-11145; trac-8165; trac-11382, trac-11764)", function( assert ) {
1325 assert.expect( 5 );
1327 // Alias names like "id" cause havoc
1328 var form = jQuery(
1329 "<form id='myform'>" +
1330 "<input type='text' name='id' value='secret agent man' />" +
1331 "</form>"
1333 .on( "submit", function( event ) {
1334 event.preventDefault();
1336 .appendTo( "body" );
1338 jQuery( "body" )
1339 .on( "submit", "#myform", function() {
1340 assert.ok( true, "delegated id selector with aliased id" );
1342 .find( "#myform" )
1343 .trigger( "submit" )
1344 .end()
1345 .off( "submit" );
1347 form.append( "<input type='text' name='disabled' value='differently abled' />" );
1348 jQuery( "body" )
1349 .on( "submit", "#myform", function() {
1350 assert.ok( true, "delegated id selector with aliased disabled" );
1352 .find( "#myform" )
1353 .trigger( "submit" )
1354 .end()
1355 .off( "submit" );
1357 form
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" );
1365 .find( "span" )
1366 .trigger( "click" ) // yep
1367 .trigger( "mouseover" ) // yep
1368 .end()
1369 .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
1370 .find( "span" )
1371 .trigger( "click" ) // nope
1372 .trigger( "mouseover" ) // yep
1373 .end()
1374 .off( "click" );
1376 form.remove();
1377 } );
1379 QUnit.test( "Submit event can be stopped (trac-11049)", function( assert ) {
1380 assert.expect( 1 );
1382 // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
1383 var form = jQuery(
1384 "<form id='myform'>" +
1385 "<input type='text' name='sue' value='bawls' />" +
1386 "<input type='submit' />" +
1387 "</form>"
1389 .appendTo( "body" );
1391 jQuery( "body" )
1392 .on( "submit", function() {
1393 assert.ok( true, "submit bubbled on first handler" );
1394 return false;
1396 .find( "#myform input[type=submit]" )
1397 .each( function() { this.click(); } )
1398 .end()
1399 .on( "submit", function() {
1400 assert.ok( false, "submit bubbled on second handler" );
1401 return false;
1403 .find( "#myform input[type=submit]" )
1404 .each( function() {
1405 jQuery( this.form ).on( "submit", function( e ) {
1406 e.preventDefault();
1407 e.stopPropagation();
1408 } );
1409 this.click();
1411 .end()
1412 .off( "submit" );
1414 form.remove();
1415 } );
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 ) {
1422 assert.expect( 1 );
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" );
1431 iframe.remove();
1432 window.onmessage = null;
1433 done();
1436 iframe.appendTo( "#qunit-fixture" );
1437 } );
1439 QUnit.test( "jQuery.Event( type, props )", function( assert ) {
1441 assert.expect( 6 );
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" );
1463 } );
1465 QUnit.test( "jQuery.Event properties", function( assert ) {
1466 assert.expect( 12 );
1468 var handler,
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" );
1487 } );
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" );
1501 } );
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" );
1582 event.button = 1;
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
1593 clicked = 0;
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" );
1609 } );
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" );
1616 } );
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
1652 called = 0;
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." );
1661 called = 0;
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 );
1668 called = 0;
1669 jQuery( "#nothiddendiv" ).trigger( "click" );
1670 assert.equal( called, 1, "Verify that only one click occurred." );
1672 called = 0;
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 );
1680 // Cleanup
1681 jQuery( "#body" ).off( "click", "#nothiddendiv", callback );
1683 called = 0;
1684 jQuery( "#nothiddendiv" ).trigger( "click" );
1685 assert.equal( called, 0, "Verify that no click occurred." );
1687 called = 0;
1688 jQuery( "#nothiddendiv" ).trigger( "foo" );
1689 assert.equal( called, 1, "Verify that one foo occurred." );
1691 // Cleanup
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
1696 livec = 0;
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." );
1706 // Cleanup
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
1711 lived = 0;
1712 livee = 0;
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; } );
1726 lived = 0;
1727 livee = 0;
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." );
1732 // Cleanup
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" );
1741 } );
1743 jQuery( "span#liveSpan1 a" ).trigger( "click" );
1745 jQuery( "#body" ).off( "click", "span#liveSpan1" );
1747 // Work with deep selectors
1748 livee = 0;
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." );
1758 livee = 0;
1759 jQuery( "#nothiddendivchild" ).trigger( "click" );
1760 assert.equal( livee, 2, "Click, deep selector." );
1762 livee = 0;
1763 jQuery( "#nothiddendivchild" ).trigger( "mouseover" );
1764 assert.equal( livee, 1, "Mouseover, deep selector." );
1766 jQuery( "#body" ).off( "mouseover", "#nothiddendiv div" );
1768 livee = 0;
1769 jQuery( "#nothiddendivchild" ).trigger( "click" );
1770 assert.equal( livee, 2, "Click, deep selector." );
1772 livee = 0;
1773 jQuery( "#nothiddendivchild" ).trigger( "mouseover" );
1774 assert.equal( livee, 0, "Mouseover, deep selector." );
1776 jQuery( "#body" ).off( "click", "#nothiddendiv div", clickB );
1778 livee = 0;
1779 jQuery( "#nothiddendivchild" ).trigger( "click" );
1780 assert.equal( livee, 1, "Click, deep selector." );
1782 jQuery( "#body" ).off( "click", "#nothiddendiv div" );
1783 } );
1785 QUnit.test( "jQuery.off using dispatched jQuery.Event", function( assert ) {
1786 assert.expect( 1 );
1788 var markup = jQuery( "<p><a href='#'>target</a></p>" ),
1789 count = 0;
1790 markup
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()
1796 .remove();
1797 } );
1799 QUnit.test( "events with type matching an Object.prototype property (gh-3256)", function( assert ) {
1800 assert.expect( 1 );
1802 var elem = jQuery( "<div></div>" ),
1803 eventFired = false;
1805 elem.appendTo( "#qunit-fixture" );
1807 try {
1808 elem
1809 .one( "hasOwnProperty", function() {
1810 eventFired = true;
1812 .trigger( "hasOwnProperty" );
1813 } finally {
1814 assert.strictEqual( eventFired, true, "trigger fired without crashing" );
1816 } );
1818 QUnit.test( "events with type matching an Object.prototype property, cloned element (gh-3256)",
1819 function( assert ) {
1820 assert.expect( 1 );
1822 var elem = jQuery( "<div></div>" ),
1823 eventFired = false;
1825 elem.appendTo( "#qunit-fixture" );
1827 try {
1828 // Make sure the original element has some event data.
1829 elem.on( "click", function() {} );
1831 elem
1832 .clone( true )
1833 .one( "hasOwnProperty", function() {
1834 eventFired = true;
1836 .trigger( "hasOwnProperty" );
1837 } finally {
1838 assert.strictEqual( eventFired, true, "trigger fired without crashing" );
1840 } );
1842 // selector-native does not support scope-fixing in delegation
1843 QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "delegated event with delegateTarget-relative selector", function( assert ) {
1844 assert.expect( 3 );
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()
1859 .off( "click" );
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" );
1867 .find( "#ul0" )
1868 .on( "click", "li:first>a", function() {
1869 assert.ok( this.id === "a0_0", "first li under #u10 was clicked" );
1871 .end()
1872 .find( "a" ).trigger( "click" ).end()
1873 .find( "#ul0" ).off();
1874 } else {
1875 assert.ok( "skip", "Positional selectors are not supported" );
1876 assert.ok( "skip", "Positional selectors are not supported" );
1879 markup.remove();
1880 } );
1882 QUnit.test( "delegated event with selector matching Object.prototype property (trac-13203)", function( assert ) {
1883 assert.expect( 1 );
1885 var matched = 0;
1887 jQuery( "#foo" ).on( "click", "toString", function() {
1888 matched++;
1889 } );
1891 jQuery( "#anchor2" ).trigger( "click" );
1893 assert.equal( matched, 0, "Nothing matched 'toString'" );
1894 } );
1896 QUnit.test( "delegated event with intermediate DOM manipulation (trac-13208)", function( assert ) {
1897 assert.expect( 1 );
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" );
1903 } );
1904 jQuery( "#anchor2" ).trigger( "click" );
1905 } );
1907 QUnit.test( "ignore comment nodes in event delegation (gh-2055)", function( assert ) {
1908 assert.expect( 1 );
1910 // Test if DOMNodeInserted is supported
1911 // This is a back-up for when DOMNodeInserted support
1912 // is eventually removed from browsers
1913 function test() {
1914 var ret = false;
1915 var $fixture = jQuery( "#qunit-fixture" );
1916 $fixture.on( "DOMNodeInserted", function() {
1917 ret = true;
1918 $fixture.off( "DOMNodeInserted" );
1919 } ).append( "<div></div>" );
1920 return ret;
1923 var $foo = jQuery( "#foo" ).on( "DOMNodeInserted", "[id]", function() {
1924 assert.ok( true, "No error thrown on comment node" );
1925 } ),
1926 $comment = jQuery( document.createComment( "comment" ) )
1927 .appendTo( $foo.find( "#sap" ) );
1929 if ( !test() ) {
1930 fireNative( $comment[ 0 ], "DOMNodeInserted" );
1932 } );
1934 QUnit.test( "stopPropagation() stops directly-bound events on delegated target", function( assert ) {
1935 assert.expect( 1 );
1937 var markup = jQuery( "<div><p><a href=\"#\">target</a></p></div>" );
1938 markup
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()
1947 .remove();
1948 } );
1950 QUnit.test( "off all bound delegated events", function( assert ) {
1951 assert.expect( 2 );
1953 var count = 0,
1954 clicks = 0,
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." );
1968 div.off( "click" );
1969 } );
1971 QUnit.test( "on with multiple delegated events", function( assert ) {
1972 assert.expect( 1 );
1974 var count = 0,
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, "**" );
1985 } );
1987 QUnit.test( "delegated on with change", function( assert ) {
1988 assert.expect( 8 );
1990 var select, checkbox, checkboxFunction,
1991 text, textChange, oldTextVal,
1992 password, passwordChange, oldPasswordVal,
1993 selectChange = 0,
1994 checkboxChange = 0;
1996 select = jQuery( "select[name='S1']" );
1997 jQuery( "#body" ).on( "change", "select[name='S1']", function() {
1998 selectChange++;
1999 } );
2001 checkbox = jQuery( "#check2" );
2002 checkboxFunction = function() {
2003 checkboxChange++;
2005 jQuery( "#body" ).on( "change", "#check2", checkboxFunction );
2007 // test click on select
2009 // second click that changed it
2010 selectChange = 0;
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
2016 selectChange = 0;
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" );
2027 textChange = 0;
2028 oldTextVal = text.val();
2030 jQuery( "#body" ).on( "change", "#name", function() {
2031 textChange++;
2032 } );
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" );
2043 passwordChange = 0;
2044 oldPasswordVal = password.val();
2045 jQuery( "#body" ).on( "change", "#name", function() {
2046 passwordChange++;
2047 } );
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
2058 // die all changes
2059 selectChange = 0;
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." );
2065 selectChange = 0;
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." );
2074 } );
2076 QUnit.test( "delegated on with submit", function( assert ) {
2077 assert.expect( 2 );
2079 var count1 = 0, count2 = 0;
2081 jQuery( "#body" ).on( "submit", "#testForm", function( ev ) {
2082 count1++;
2083 ev.preventDefault();
2084 } );
2086 jQuery( document ).on( "submit", "body", function( ev ) {
2087 count2++;
2088 ev.preventDefault();
2089 } );
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, "**" );
2097 } );
2099 QUnit.test( "delegated off() with only namespaces", function( assert ) {
2100 assert.expect( 2 );
2102 var $delegate = jQuery( "#liveHandlerOrder" ),
2103 count = 0;
2105 $delegate.on( "click.ns", "a", function() {
2106 count++;
2107 } );
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" );
2118 } );
2120 QUnit.test( "Non DOM element events", function( assert ) {
2121 assert.expect( 1 );
2123 var o = {};
2125 jQuery( o ).on( "nonelementobj", function() {
2126 assert.ok( true, "Event on non-DOM object triggered" );
2127 } );
2129 jQuery( o ).trigger( "nonelementobj" ).off( "nonelementobj" );
2130 } );
2132 QUnit.test( "inline handler returning false stops default", function( assert ) {
2133 assert.expect( 1 );
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" );
2138 return false;
2139 } );
2140 markup.find( "a" ).trigger( "click" );
2141 markup.off( "click" );
2142 } );
2144 QUnit.test( "window resize", function( assert ) {
2145 assert.expect( 2 );
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." );
2154 } );
2156 QUnit.test( "focusin bubbles", function( assert ) {
2157 assert.expect( 2 );
2159 var input = jQuery( "<input type='text' />" ).prependTo( "body" ),
2160 order = 0;
2162 // focus the element so DOM focus won't fire
2163 input[ 0 ].focus();
2165 jQuery( "body" ).on( "focusin.focusinBubblesTest", function() {
2166 assert.equal( 1, order++, "focusin on the body second" );
2167 } );
2169 input.on( "focusin.focusinBubblesTest", function() {
2170 assert.equal( 0, order++, "focusin on the element first" );
2171 } );
2173 // Removed since DOM focus is unreliable on test swarm
2174 // DOM focus method
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.
2179 // order = 1;
2180 // jQuery( "#text1" )[ 0 ].focus();
2182 // jQuery trigger, which calls DOM focus
2183 order = 0;
2184 input.trigger( "focus" );
2186 input.remove();
2187 jQuery( "body" ).off( "focusin.focusinBubblesTest" );
2188 } );
2190 QUnit.test( "focus does not bubble", function( assert ) {
2191 assert.expect( 1 );
2193 var done = assert.async(),
2194 input = jQuery( "<input type='text' />" ).prependTo( "body" );
2196 // focus the element so DOM focus won't fire
2197 input[ 0 ].focus();
2199 jQuery( "body" ).on( "focus.focusDoesNotBubbleTest", function() {
2200 assert.ok( false, "focus doesn't fire on body" );
2201 } );
2203 input.on( "focus.focusDoesNotBubbleTest", function() {
2204 assert.ok( true, "focus on the element" );
2205 } );
2207 // Removed since DOM focus is unreliable on test swarm
2208 // DOM focus method
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" );
2218 input.remove();
2219 jQuery( "body" ).off( "focus.focusDoesNotBubbleTest" );
2221 setTimeout( function() {
2222 done();
2223 }, 50 );
2224 } );
2226 QUnit.test( "custom events with colons (trac-3533, trac-8272)", function( assert ) {
2227 assert.expect( 1 );
2229 var tab = jQuery( "<table><tr><td>trigger</td></tr></table>" ).appendTo( "body" );
2230 try {
2231 tab.trigger( "back:forth" );
2232 assert.ok( true, "colon events don't throw" );
2233 } catch ( e ) {
2234 assert.ok( false, "colon events die" );
2236 tab.remove();
2238 } );
2240 QUnit.test( ".on and .off", function( assert ) {
2241 assert.expect( 9 );
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" );
2245 // Simple case
2246 jQuery( "#onandoff" )
2247 .on( "whip", function() {
2248 assert.ok( true, "whipped it good" );
2250 .trigger( "whip" )
2251 .off();
2253 // Direct events only
2254 counter = 0;
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
2262 .trigger( "click" )
2263 .trigger( "click", 17 )
2264 .off( "click" );
2265 assert.equal( counter, 54, "direct event bindings with data" );
2267 // Delegated events only
2268 counter = 0;
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
2276 .find( "em" )
2277 .trigger( "click" )
2278 .trigger( "click", 17 )
2279 .end()
2280 .off( "click", "em" );
2281 assert.equal( counter, 54, "delegated event bindings with data" );
2283 // Mixed event bindings and types
2284 counter = 0;
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 )
2292 .trigger( "what!" )
2293 .each( function() {
2294 assert.equal( counter, 0, "nothing triggered yet" );
2296 .find( "em" )
2297 .one( "cluck", 3, mixfn )
2298 .trigger( "cluck", 8 ) // 3+8 2+8 + 0+8 = 29
2299 .off()
2300 .trigger( "cluck", 9 ) // 2+9 + 0+9 = 20
2301 .end()
2302 .each( function() {
2303 assert.equal( counter, 49, "after triggering em element" );
2305 .off( "cluck", function() {} ) // shouldn't remove anything
2306 .trigger( "cluck", 2 ) // 0+2 = 2
2307 .each( function() {
2308 assert.equal( counter, 51, "after triggering #onandoff cluck" );
2310 .find( "b" )
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" )
2316 .end()
2317 .each( function() {
2318 assert.equal( counter, 51, "after triggering b" );
2320 .trigger( "cluck", 3 ) // 0+3 = 3
2321 .off( "clack", "em", mixfn )
2322 .find( "em" )
2323 .trigger( "clack" ) // 0
2324 .end()
2325 .each( function() {
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" );
2334 $onandoff.remove();
2335 } );
2337 QUnit.test( "special on name mapping", function( assert ) {
2338 assert.expect( 7 );
2340 jQuery.event.special.slap = {
2341 bindType: "click",
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 )
2355 .find( "button" )
2356 .on( "slap", jQuery.noop )
2357 .on( "click", comeback )
2358 .trigger( "click" ) // bindType-slap and click
2359 .off( "slap" )
2360 .trigger( "click" ) // click
2361 .off( "click" )
2362 .trigger( "swing" ) // delegateType-slap and swing
2363 .end()
2364 .off( "slap swing", "button" )
2365 .find( "button" ) // everything should be gone
2366 .trigger( "slap" )
2367 .trigger( "click" )
2368 .trigger( "swing" )
2369 .end()
2370 .remove();
2371 delete jQuery.event.special.slap;
2373 jQuery.event.special.gutfeeling = {
2374 bindType: "click",
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 )
2388 .off( "click" )
2389 .trigger( "gutfeeling" )
2390 .remove();
2392 // Ensure special events are removed when only a namespace is provided
2393 jQuery( "<p>Gut Feeling</p>" )
2394 .on( "gutfeeling.Devo", jQuery.noop )
2395 .off( ".Devo" )
2396 .trigger( "gutfeeling" )
2397 .remove();
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
2404 .remove();
2406 delete jQuery.event.special[ "gutfeeling" ];
2407 } );
2409 QUnit.test( ".on and .off, selective mixed removal (trac-10705)", function( assert ) {
2410 assert.expect( 7 );
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
2429 } );
2431 QUnit.test( "special interference with Object.prototype", function( assert ) {
2432 assert.expect( 1 );
2434 var triggered = false;
2436 Object.prototype.jqfake = {
2437 trigger: function() {
2438 triggered = true;
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" );
2449 } );
2451 QUnit.test( ".on( event-map, null-selector, data ) trac-11130", function( assert ) {
2453 assert.expect( 1 );
2455 var $p = jQuery( "<p>Strange Pursuit</p>" ),
2456 data = "bar",
2457 map = {
2458 "foo": function( event ) {
2459 assert.equal( event.data, "bar", "event.data correctly relayed with null selector" );
2460 $p.remove();
2464 $p.on( map, null, data ).trigger( "foo" );
2465 } );
2467 QUnit.test( "clone() delegated events (trac-11076)", function( assert ) {
2468 assert.expect( 3 );
2470 var counter = { "center": 0, "fold": 0, "centerfold": 0 },
2471 clicked = function() {
2472 counter[ jQuery( this ).text().replace( /\s+/, "" ) ]++;
2474 table =
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" );
2486 table.remove();
2487 clone.remove();
2488 } );
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" );
2500 } );
2501 markup.on( "click", function() {
2502 assert.equal( cb.checked, false, "checkbox is not checked in bubbled event" );
2503 } );
2505 // Native click
2506 cb.checked = true;
2507 assert.equal( cb.checked, true, "native event - checkbox is initially checked" );
2508 cb.click();
2509 assert.equal( cb.checked, false, "native event - checkbox is no longer checked" );
2511 // jQuery click
2512 cb.checked = true;
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)
2522 cb.checked = true;
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" );
2526 } );
2527 markup.on( "click", function( e, data ) {
2528 assert.equal( data, "clicked", "trigger data passed to bubbled handler" );
2529 } );
2530 jQuery( cb ).trigger( "click", [ "clicked" ] );
2531 assert.equal( cb.checked, false, "jQuery event with data - checkbox is no longer checked" );
2532 } );
2534 QUnit.test( "event object properties on natively-triggered event", function( assert ) {
2535 assert.expect( 3 );
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" );
2549 } );
2550 evt.initEvent( "click", true, true );
2551 link.dispatchEvent( evt );
2552 $link.off( "click" ).remove();
2553 } );
2555 QUnit.test( "addProp extensions", function( assert ) {
2556 assert.expect( 2 );
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" );
2563 } );
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" );
2572 } );
2573 fireNative( $fixture[ 0 ], "click" );
2574 $fixture.off( "click" );
2576 $fixture.remove();
2577 } );
2579 QUnit.test( "drag/drop events copy mouse-related event properties (gh-1925, gh-2009)", function( assert ) {
2580 assert.expect( 4 );
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" );
2587 } );
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" );
2593 } );
2595 fireNative( $fixture[ 0 ], "drop" );
2597 $fixture.off( "dragmove drop" ).remove();
2598 } );
2600 QUnit.test( "focusin using non-element targets", function( assert ) {
2601 assert.expect( 2 );
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" );
2611 } );
2613 testIframe(
2614 "focusin from an iframe",
2615 "event/focusinCrossFrame.html",
2616 function( assert, framejQuery, frameWin, frameDoc ) {
2617 assert.expect( 1 );
2619 var done = assert.async(),
2620 focus = false,
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
2629 // assertion in IE.
2630 if ( !document.documentMode ) {
2631 assert.ok( false, "fired a focusin event in the parent document" );
2633 } );
2635 input.on( "focusin", function() {
2636 focus = true;
2637 assert.ok( true, "fired a focusin event in the iframe" );
2638 } );
2640 // Avoid a native event; Chrome can't force focus to another frame
2641 input[ 0 ].focus();
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" );
2653 done();
2654 }, 50 );
2658 QUnit.test( "focusin on document & window", function( assert ) {
2659 assert.expect( 1 );
2661 var counter = 0,
2662 input = jQuery( "<input />" );
2664 function increment() {
2665 counter++;
2668 input.appendTo( "#qunit-fixture" );
2670 input[ 0 ].focus();
2672 jQuery( window ).on( "focusout", increment );
2673 jQuery( document ).on( "focusout", increment );
2675 input[ 0 ].blur();
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 );
2687 } );
2689 QUnit.test( "element removed during focusout (gh-4417)", function( assert ) {
2690 assert.expect( 1 );
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" );
2699 } );
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
2707 // native APIs.
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();
2718 } );
2720 testIframe(
2721 "jQuery.ready promise",
2722 "event/promiseReady.html",
2723 function( assert, jQuery, window, document, isOk ) {
2724 assert.expect( 1 );
2725 assert.ok( isOk, "$.when( $.ready ) works" );
2727 jQuery.when ? QUnit.test : QUnit.skip
2730 // need PHP here to make the incepted IFRAME hang
2731 if ( hasPHP ) {
2732 testIframe(
2733 "jQuery.ready uses interactive",
2734 "event/interactiveReady.html",
2735 function( assert, jQuery, window, document, isOk ) {
2736 assert.expect( 1 );
2737 assert.ok( isOk, "jQuery fires ready when the DOM can truly be interacted with" );
2742 testIframe(
2743 "Focusing iframe element",
2744 "event/focusElem.html",
2745 function( assert, jQuery, window, document, isOk ) {
2746 assert.expect( 1 );
2747 assert.ok( isOk, "Focused an element in an iframe" );
2751 testIframe(
2752 "triggerHandler(onbeforeunload)",
2753 "event/triggerunload.html",
2754 function( assert, jQuery, window, document, isOk ) {
2755 assert.expect( 1 );
2756 assert.ok( isOk, "Triggered onbeforeunload without an error" );
2760 // need PHP here to make the incepted IFRAME hang
2761 if ( hasPHP ) {
2762 testIframe(
2763 "jQuery.ready synchronous load with long loading subresources",
2764 "event/syncReady.html",
2765 function( assert, jQuery, window, document, isOk ) {
2766 assert.expect( 1 );
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 ) {
2773 assert.expect( 2 );
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" );
2788 $fixture.remove();
2790 jQuery.removeEvent = originRemoveEvent;
2791 } );
2793 QUnit.test( "trigger click on checkbox, fires change event", function( assert ) {
2794 assert.expect( 1 );
2796 var check = jQuery( "#check2" );
2797 var done = assert.async();
2799 check.on( "change", function() {
2801 // get it?
2802 check.off( "change" );
2803 assert.ok( true, "Change event fired as a result of triggered click" );
2804 done();
2805 } ).trigger( "click" );
2806 } );
2808 QUnit.test( "Namespace preserved when passed an Event (trac-12739)", function( assert ) {
2809 assert.expect( 4 );
2811 var markup = jQuery(
2812 "<div id='parent'><div id='child'></div></div>"
2814 triggered = 0,
2815 fooEvent;
2817 markup.find( "div" )
2818 .addBack()
2819 .on( "foo.bar", function( e ) {
2820 if ( !e.handled ) {
2821 triggered++;
2822 e.handled = true;
2823 assert.equal( e.namespace, "bar", "namespace is bar" );
2824 jQuery( e.target ).find( "div" ).each( function() {
2825 jQuery( this ).triggerHandler( e );
2826 } );
2829 .on( "foo.bar2", function() {
2830 assert.ok( false, "foo.bar2 called on trigger " + triggered + " id " + this.id );
2831 } );
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 );
2838 markup.remove();
2840 assert.equal( triggered, 3, "foo.bar triggered" );
2841 } );
2843 QUnit.test( "make sure events cloned correctly", function( assert ) {
2844 assert.expect( 18 );
2846 var clone,
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" );
2859 } );
2861 p.on( "click", function() {
2862 assert.ok( true, "Click on original child element is fired" );
2863 } );
2865 checkbox.on( "change", function() {
2866 assert.ok( true, "Change on original child element is fired" );
2867 } );
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
2875 clone.remove();
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
2881 fixture.off();
2882 p.off();
2883 checkbox.off();
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
2890 clone.remove();
2892 clone.find( "p" ).eq( 0 ).trigger( "click" ); // 0 should be fired
2893 clone.find( "#check1" ).trigger( "change" ); // 0 events should fire
2894 } );
2896 QUnit.test( "String.prototype.namespace does not cause trigger() to throw (trac-13360)", function( assert ) {
2897 assert.expect( 1 );
2898 var errored = false;
2900 String.prototype.namespace = function() {};
2902 try {
2903 jQuery( "<p>" ).trigger( "foo.bar" );
2904 } catch ( e ) {
2905 errored = true;
2907 assert.equal( errored, false, "trigger() did not throw exception" );
2908 delete String.prototype.namespace;
2909 } );
2911 QUnit.test( "Inline event result is returned (trac-13993)", function( assert ) {
2912 assert.expect( 1 );
2914 var result = jQuery( "<p onclick='return 42'>hello</p>" ).triggerHandler( "click" );
2916 assert.equal( result, 42, "inline handler returned value" );
2917 } );
2919 QUnit.test( ".off() removes the expando when there's no more data", function( assert ) {
2920 assert.expect( 2 );
2922 var key,
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" );
2928 } );
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 ) ) {
2935 assert.strictEqual(
2936 div[ 0 ][ key ], undefined,
2937 "Expando was not removed when there was no more data"
2941 } );
2943 QUnit.test( "jQuery.Event( src ) does not require a target property", function( assert ) {
2944 assert.expect( 2 );
2946 var event = jQuery.Event( { type: "offtarget" } );
2948 assert.equal( event.type, "offtarget", "correct type" );
2949 assert.equal( event.target, undefined, "no target" );
2950 } );
2952 QUnit.test( "preventDefault() on focusin does not throw exception", function( assert ) {
2953 assert.expect( 1 );
2955 var done = assert.async(),
2956 input = jQuery( "<input/>" ).appendTo( "#form" );
2958 input.on( "focusin", function( event ) {
2959 if ( !done ) {
2960 return;
2963 var exceptionCaught;
2964 try {
2965 event.preventDefault();
2966 } catch ( theException ) {
2967 exceptionCaught = theException;
2970 assert.strictEqual( exceptionCaught, undefined,
2971 "Preventing default on focusin throws no exception" );
2973 done();
2974 done = null;
2975 } );
2976 input.trigger( "focus" );
2978 // DOM focus is unreliable in TestSwarm; set a simulated event workaround timeout
2979 setTimeout( function() {
2980 if ( !done ) {
2981 return;
2983 input[ 0 ].addEventListener( "click", function( nativeEvent ) {
2984 jQuery.event.simulate( "focusin", this, jQuery.event.fix( nativeEvent ) );
2985 } );
2986 input[ 0 ].click();
2987 }, QUnit.config.testTimeout / 4 || 1000 );
2988 } );
2990 QUnit.test( ".on('focus', fn) on a text node doesn't throw", function( assert ) {
2991 assert.expect( 1 );
2993 jQuery( document.createTextNode( "text" ) )
2994 .on( "focus", function() {} );
2996 assert.ok( true, "No crash" );
2997 } );
2999 QUnit.test( "Donor event interference", function( assert ) {
3000 assert.expect( 8 );
3002 var outer = jQuery(
3003 "<div id='donor-outer'>" +
3004 "<form id='donor-form'>" +
3005 "<input id='donor-input' type='checkbox' />" +
3006 "</form>" +
3007 "</div>"
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" );
3016 } );
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" );
3022 } );
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();
3028 } );
3029 input[ 0 ].click();
3030 } );
3032 QUnit.test(
3033 "simulated events shouldn't forward stopPropagation/preventDefault methods",
3034 function( assert ) {
3035 assert.expect( 3 );
3037 var outer = jQuery(
3038 "<div id='donor-outer'>" +
3039 "<form id='donor-form'>" +
3040 "<input id='donor-input' type='checkbox' />" +
3041 "</form>" +
3042 "</div>"
3043 ).appendTo( "#qunit-fixture" ),
3044 input = jQuery( "#donor-input" ),
3045 spy = {};
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" );
3062 } );
3063 outer
3064 .on( "simulated", function( event ) {
3065 assert.ok( false, "simulated event propagation stopped" );
3066 } );
3068 // Force a simulated event
3069 input[ 0 ].addEventListener( "click", function( nativeEvent ) {
3070 jQuery.event.simulate( "simulated", this, jQuery.event.fix( nativeEvent ) );
3071 } );
3072 input[ 0 ].click();
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 ) {
3082 assert.expect( 2 );
3084 var outer = jQuery(
3085 "<div id='donor-outer'>" +
3086 "<form id='donor-form'>" +
3087 "<input id='donor-input' type='text' />" +
3088 "</form>" +
3089 "</div>"
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" );
3098 done();
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 );
3106 } );
3108 input[ 0 ].addEventListener( "click", function( nativeEvent ) {
3109 jQuery.event.simulate( "focusin", this, jQuery.event.fix( nativeEvent ) );
3110 } );
3111 input[ 0 ].click();
3112 } );
3114 QUnit.test( "trigger('click') on radio passes extra params", function( assert ) {
3115 assert.expect( 1 );
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" );
3119 } );
3121 $radio.trigger( "click", [ true ] );
3122 } );
3124 QUnit.test( "focusout/focusin support", function( assert ) {
3125 assert.expect( 6 );
3127 var focus,
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();
3138 parent
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" );
3150 } );
3152 input
3153 .on( "focus", function() {
3154 assert.ok( true, "element: focus fired" );
3156 .on( "focusin", function() {
3157 assert.ok( true, "element: focusin fired" );
3158 focus = true;
3160 .on( "blur", function() {
3161 assert.ok( true, "parent: blur fired" );
3163 .on( "focusout", function() {
3164 assert.ok( true, "element: focusout fired" );
3165 } );
3167 // gain focus
3168 input[ 0 ].focus();
3170 // then lose it
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" );
3183 // cleanup
3184 parent.off();
3185 input.off();
3186 } );
3188 QUnit.test( "focus-blur order (trac-12868)", function( assert ) {
3189 assert.expect( 5 );
3191 var order,
3192 $text = jQuery( "#text1" ),
3193 $radio = jQuery( "#radio1" );
3195 $radio[ 0 ].focus();
3197 $text
3198 .on( "focus", function() {
3199 assert.equal( order++, 1, "text focus" );
3201 .on( "blur", function() {
3202 assert.equal( order++, 0, "text blur" );
3203 } );
3204 $radio
3205 .on( "focus", function() {
3206 assert.equal( order++, 1, "radio focus" );
3208 .on( "blur", function() {
3209 assert.equal( order++, 0, "radio blur" );
3210 } );
3212 // Enabled input getting focus
3213 order = 0;
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
3226 order = 1;
3227 $radio.triggerHandler( "focus" );
3229 // Clean up
3230 $text.off();
3231 $radio.off();
3232 } );
3234 QUnit.test( "Event handling works with multiple async focus events (gh-4350)", function( assert ) {
3235 assert.expect( 3 );
3237 var remaining = 3,
3238 input = jQuery( "#name" ),
3239 done = assert.async();
3241 input
3242 .on( "focus", function() {
3243 remaining--;
3244 assert.ok( true, "received focus event, expecting " + remaining + " more" );
3245 if ( remaining > 0 ) {
3246 input.trigger( "blur" );
3247 } else {
3249 if ( QUnit.isIE ) {
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" );
3259 done();
3262 .on( "blur", function() {
3263 setTimeout( function() {
3264 input.trigger( "focus" );
3265 } );
3266 } );
3268 // gain 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() {
3278 done();
3279 } );
3281 } );
3282 } );
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 ) {
3288 assert.expect( 1 );
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" );
3300 done();
3301 }, 500 );
3302 } );
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 ) {
3308 assert.expect( 1 );
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" );
3319 done();
3320 }, 500 );
3321 } );
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" ],
3332 slice = data.slice;
3334 // click (gh-4139)
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" );
3344 } );
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)" );
3351 // focus (gh-1741)
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" );
3369 } );
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)" );
3378 } );
3380 QUnit.test( "focus change during a focus handler (gh-4382)", function( assert ) {
3381 assert.expect( 2 );
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" )
3388 .append( select )
3389 .append( button );
3391 select.on( "focus", function() {
3392 button.trigger( "focus" );
3393 } );
3395 jQuery( document ).on( "focusin.focusTests", function( ev ) {
3396 // Support: IE 11+
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
3399 // the last one.
3400 if ( ev.target === button[ 0 ] ) {
3401 assert.ok( true, "focusin propagated to document from the button" );
3403 } );
3405 select.trigger( "focus" );
3407 setTimeout( function() {
3408 assert.strictEqual( document.activeElement, button[ 0 ], "Focus redirect worked" );
3409 jQuery( document ).off( ".focusTests" );
3410 done();
3411 } );
3412 } );
3414 QUnit.test( "trigger(focus) works after .on(focus).off(focus) (gh-4867)", function( assert ) {
3415 assert.expect( 1 );
3417 var input = jQuery( "<input />" );
3419 input.appendTo( "#qunit-fixture" );
3421 input
3422 .on( "focus", function() {} )
3423 .off( "focus" );
3425 input.trigger( "focus" );
3427 assert.equal( document.activeElement, input[ 0 ], "input has focus" );
3428 } );
3430 QUnit.test( "trigger(focus) works after focusing when hidden (gh-4950)", function( assert ) {
3431 assert.expect( 1 );
3433 var input = jQuery( "<input />" );
3435 input.appendTo( "#qunit-fixture" );
3437 input
3438 .css( "display", "none" )
3439 .trigger( "focus" )
3440 .css( "display", "" )
3441 .trigger( "focus" );
3443 assert.equal( document.activeElement, input[ 0 ], "input has focus" );
3444 } );
3446 QUnit.test( "trigger(focus) fires native & jQuery handlers (gh-5015)", function( assert ) {
3447 assert.expect( 3 );
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" );
3460 done();
3461 } );
3463 input.on( "focus", function() {
3464 assert.ok( true, "jQuery handler fired" );
3465 done();
3466 } );
3468 input[ 0 ].addEventListener( "focus", function() {
3469 assert.ok( true, "2nd native handler fired" );
3470 done();
3471 } );
3473 input.trigger( "focus" );
3474 } );
3476 // TODO replace with an adaptation of
3477 // https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464
3478 ( function() {
3479 supportjQuery.each(
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 ) {
3493 assert.expect( 2 );
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 );
3512 } );
3514 target.trigger( "click.fired" );
3515 } );
3518 function makeTestForGh5015( type, html ) {
3519 var testName = "trigger(click) fires native & jQuery handlers (gh-5015) - " + type;
3520 QUnit.test( testName, function( assert ) {
3521 assert.expect( 3 );
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" );
3530 } );
3532 input.on( "click", function() {
3533 assert.ok( true, "jQuery handler fired" );
3534 } );
3536 input[ 0 ].addEventListener( "click", function() {
3537 assert.ok( true, "2nd native handler fired" );
3538 } );
3540 input.trigger( "click" );
3541 } );
3543 } )();