1 module("event", { teardown: moduleTeardown });
3 test("null or undefined handler", function() {
5 // Supports Fixes bug #7229
7 jQuery("#firstp").click(null);
8 ok(true, "Passing a null handler will not throw an exception");
12 jQuery("#firstp").click(undefined);
13 ok(true, "Passing an undefined handler will not throw an exception");
17 test("bind(),live(),delegate() with non-null,defined data", function() {
21 var handler = function( event, data ) {
22 equal( data, 0, "non-null, defined data (zero) is correctly passed" );
25 jQuery("#foo").bind("foo", handler);
26 jQuery("#foo").live("foo", handler);
27 jQuery("div").delegate("#foo", "foo", handler);
29 jQuery("#foo").trigger("foo", 0);
31 jQuery("#foo").unbind("foo", handler);
32 jQuery("#foo").die("foo", handler);
33 jQuery("div").undelegate("#foo", "foo");
37 test("Handler changes and .trigger() order", function() {
41 "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
46 .find( "*" ).andSelf().on( "click", function( e ) {
47 path += this.nodeName.toLowerCase() + " ";
49 .filter( "b" ).on( "click", function( e ) {
50 // Removing span should not stop propagation to original parents
51 if ( e.target === this ) {
52 jQuery(this).parent().remove();
56 markup.find( "b" ).trigger( "click" );
58 equal( path, "b p div div ", "Delivered all events" );
63 test("bind(), with data", function() {
65 var handler = function(event) {
66 ok( event.data, "bind() with data, check passed data exists" );
67 equal( event.data["foo"], "bar", "bind() with data, Check value of passed data" );
69 jQuery("#firstp").bind("click", {"foo": "bar"}, handler).click().unbind("click", handler);
71 ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
73 var test = function(){};
74 var handler2 = function(event) {
75 equal( event.data, test, "bind() with function data, Check value of passed data" );
77 jQuery("#firstp").bind("click", test, handler2).click().unbind("click", handler2);
80 test("click(), with data", function() {
82 var handler = function(event) {
83 ok( event.data, "bind() with data, check passed data exists" );
84 equal( event.data["foo"], "bar", "bind() with data, Check value of passed data" );
86 jQuery("#firstp").click({"foo": "bar"}, handler).click().unbind("click", handler);
88 ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
91 test("bind(), with data, trigger with data", function() {
93 var handler = function(event, data) {
94 ok( event.data, "check passed data exists" );
95 equal( event.data.foo, "bar", "Check value of passed data" );
96 ok( data, "Check trigger data" );
97 equal( data.bar, "foo", "Check value of trigger data" );
99 jQuery("#firstp").bind("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]).unbind("click", handler);
102 test("bind(), multiple events at once", function() {
104 var clickCounter = 0,
105 mouseoverCounter = 0;
106 var handler = function(event) {
107 if (event.type == "click") {
110 else if (event.type == "mouseover") {
111 mouseoverCounter += 1;
115 jQuery("#firstp").bind("click mouseover", handler).trigger("click").trigger("mouseover");
116 equal( clickCounter, 1, "bind() with multiple events at once" );
117 equal( mouseoverCounter, 1, "bind() with multiple events at once" );
120 test("bind(), five events at once", function() {
124 handler = function(event) {
128 jQuery("#firstp").bind("click mouseover foo bar baz", handler)
129 .trigger("click").trigger("mouseover")
130 .trigger("foo").trigger("bar")
133 equal( count, 5, "bind() five events at once" );
136 test("bind(), multiple events at once and namespaces", function() {
141 var div = jQuery("<div/>").bind("focusin.a", function(e) {
142 equal( e.type, cur, "Verify right single event was fired." );
146 div.trigger("focusin.a");
148 // manually clean up detached elements
151 div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
152 equal( e.type, cur, "Verify right multi event was fired." );
153 equal( e.data, obj, "Make sure the data came in correctly." );
157 div.trigger("click");
160 div.trigger("mouseover");
162 // manually clean up detached elements
165 div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
166 equal( e.type, cur, "Verify right multi event was fired." );
170 div.trigger("focusin.a");
173 div.trigger("focusout.b");
175 // manually clean up detached elements
179 test("bind(), namespace with special add", function() {
182 var div = jQuery("<div/>").bind("test", function(e) {
183 ok( true, "Test event fired." );
188 jQuery.event.special["test"] = {
189 _default: function(e, data) {
190 equal( this, document, "Make sure we're at the top of the chain." );
191 equal( e.type, "test", "And that we're still dealing with a test event." );
192 equal( e.target, div[0], "And that the target is correct." );
193 ok( data !== undefined , "And that trigger data was passed." );
196 teardown: function(){
197 ok(true, "Teardown called.");
199 add: function( handleObj ) {
200 var handler = handleObj.handler;
201 handleObj.handler = function(e) {
203 handler.apply( this, arguments );
207 ok(true, "Remove called.");
211 div.bind("test.a", {"x": 1}, function(e) {
212 ok( !!e.xyz, "Make sure that the data is getting passed through." );
213 equal( e.data["x"], 1, "Make sure data is attached properly." );
216 div.bind("test.b", {"x": 2}, function(e) {
217 ok( !!e.xyz, "Make sure that the data is getting passed through." );
218 equal( e.data["x"], 2, "Make sure data is attached properly." );
222 div.trigger("test", 33.33);
225 div.trigger("test.a", "George Harrison");
228 div.trigger("test.b", { year: 1982 });
233 div = jQuery("<div/>").bind("test", function(e) {
234 ok( true, "Test event fired." );
238 div.appendTo("#qunit-fixture").remove();
240 delete jQuery.event.special["test"];
243 test("bind(), no data", function() {
245 var handler = function(event) {
246 ok ( !event.data, "Check that no data is added to the event object" );
248 jQuery("#firstp").bind("click", handler).trigger("click");
251 test("bind/one/unbind(Object)", function(){
254 var clickCounter = 0, mouseoverCounter = 0;
255 function handler(event) {
256 if (event.type == "click") {
260 else if (event.type == "mouseover") {
266 function handlerWithData(event) {
267 if (event.type == "click") {
268 clickCounter += event.data;
270 else if (event.type == "mouseover") {
271 mouseoverCounter += event.data;
276 $elem.trigger("click").trigger("mouseover");
279 var $elem = jQuery("#firstp")
287 "click":handlerWithData,
288 "mouseover":handlerWithData
293 equal( clickCounter, 3, "bind(Object)" );
294 equal( mouseoverCounter, 3, "bind(Object)" );
297 equal( clickCounter, 4, "bind(Object)" );
298 equal( mouseoverCounter, 4, "bind(Object)" );
300 jQuery("#firstp").unbind({
306 equal( clickCounter, 4, "bind(Object)" );
307 equal( mouseoverCounter, 4, "bind(Object)" );
310 test("live/die(Object), delegate/undelegate(String, Object)", function() {
313 var clickCounter = 0, mouseoverCounter = 0,
314 $p = jQuery("#firstp"), $a = $p.find("a:first");
317 "click": function( event ) {
318 clickCounter += ( event.data || 1 );
320 "mouseover": function( event ) {
321 mouseoverCounter += ( event.data || 1 );
326 $a.trigger("click").trigger("mouseover");
330 $p.delegate( "a", events, 2 );
333 equal( clickCounter, 3, "live/delegate" );
334 equal( mouseoverCounter, 3, "live/delegate" );
336 $p.undelegate( "a", events );
339 equal( clickCounter, 4, "undelegate" );
340 equal( mouseoverCounter, 4, "undelegate" );
345 equal( clickCounter, 4, "die" );
346 equal( mouseoverCounter, 4, "die" );
349 test("live/delegate immediate propagation", function() {
352 var $p = jQuery("#firstp"), $a = $p.find("a:first"), lastClick;
355 $a.live( "click", function(e) {
356 lastClick = "click1";
357 e.stopImmediatePropagation();
359 $a.live( "click", function(e) {
360 lastClick = "click2";
362 $a.trigger( "click" );
363 equal( lastClick, "click1", "live stopImmediatePropagation" );
367 $p.delegate( "a", "click", function(e) {
368 lastClick = "click1";
369 e.stopImmediatePropagation();
371 $p.delegate( "a", "click", function(e) {
372 lastClick = "click2";
374 $a.trigger( "click" );
375 equal( lastClick, "click1", "delegate stopImmediatePropagation" );
376 $p.undelegate( "click" );
379 test("bind/delegate bubbling, isDefaultPrevented", function() {
381 var $anchor2 = jQuery( "#anchor2" ),
382 $main = jQuery( "#qunit-fixture" ),
383 fakeClick = function($jq) {
384 // Use a native click so we don't get jQuery simulated bubbling
385 if ( document.createEvent ) {
386 var e = document.createEvent( "MouseEvents" );
387 e.initEvent( "click", true, true );
388 $jq[0].dispatchEvent(e);
390 else if ( $jq[0].click ) {
391 $jq[0].click(); // IE
394 $anchor2.click(function(e) {
397 $main.delegate("#foo", "click", function(e) {
398 var orig = e.originalEvent;
400 if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig["getPreventDefault"] ) {
401 equal( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
404 // Opera < 11 doesn't implement any interface we can use, so give it a pass
405 ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
408 fakeClick( $anchor2 );
409 $anchor2.unbind( "click" );
410 $main.undelegate( "click" );
411 $anchor2.click(function(e) {
412 // Let the default action occur
414 $main.delegate("#foo", "click", function(e) {
415 equal( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
417 fakeClick( $anchor2 );
418 $anchor2.unbind( "click" );
419 $main.undelegate( "click" );
422 test("bind(), iframes", function() {
425 // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
426 var doc = jQuery("#loadediframe").contents();
428 jQuery("div", doc).bind("click", function() {
429 ok( true, "Binding to element inside iframe" );
430 }).click().unbind("click");
433 test("bind(), trigger change on select", function() {
436 function selectOnChange(event) {
437 equal( event.data, counter++, "Event.data is not a global event object" );
439 jQuery("#form select").each(function(i){
440 jQuery(this).bind("change", i, selectOnChange);
441 }).trigger("change");
444 test("bind(), namespaced events, cloned events", 18, function() {
445 var firstp = jQuery( "#firstp" );
447 firstp.bind("custom.test",function(e){
448 ok(false, "Custom event triggered");
451 firstp.bind("click",function(e){
452 ok(true, "Normal click triggered");
453 equal( e.type + e.namespace, "click", "Check that only click events trigger this fn" );
456 firstp.bind("click.test",function(e){
458 ok( true, "Namespaced click triggered" );
462 equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
465 //clone(true) element to verify events are cloned correctly
466 firstp = firstp.add( firstp.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp ) );
468 // Trigger both bound fn (8)
469 firstp.trigger("click");
471 // Trigger one bound fn (4)
472 firstp.trigger("click.test");
474 // Remove only the one fn
475 firstp.unbind("click.test");
477 // Trigger the remaining fn (4)
478 firstp.trigger("click");
480 // Remove the remaining namespaced fn
481 firstp.unbind(".test");
483 // Try triggering the custom event (0)
484 firstp.trigger("custom");
486 // using contents will get comments regular, text, and comment nodes
487 jQuery("#nonnodes").contents().bind("tester", function () {
488 equal(this.nodeType, 1, "Check node,textnode,comment bind just does real nodes" );
489 }).trigger("tester");
491 // Make sure events stick with appendTo'd elements (which are cloned) #2027
492 jQuery("<a href='#fail' class='test'>test</a>").click(function(){ return false; }).appendTo("#qunit-fixture");
493 ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" );
496 test("bind(), multi-namespaced events", function() {
508 function check(name, msg){
509 deepEqual(name, order.shift(), msg);
512 jQuery("#firstp").bind("custom.test",function(e){
513 check("custom.test", "Custom event triggered");
516 jQuery("#firstp").bind("custom.test2",function(e){
517 check("custom.test2", "Custom event triggered");
520 jQuery("#firstp").bind("click.test",function(e){
521 check("click.test", "Normal click triggered");
524 jQuery("#firstp").bind("click.test.abc",function(e){
525 check("click.test.abc", "Namespaced click triggered");
528 // Those would not trigger/unbind (#5303)
529 jQuery("#firstp").trigger("click.a.test");
530 jQuery("#firstp").unbind("click.a.test");
532 // Trigger both bound fn (1)
533 jQuery("#firstp").trigger("click.test.abc");
535 // Trigger one bound fn (1)
536 jQuery("#firstp").trigger("click.abc");
538 // Trigger two bound fn (2)
539 jQuery("#firstp").trigger("click.test");
541 // Remove only the one fn
542 jQuery("#firstp").unbind("click.abc");
544 // Trigger the remaining fn (1)
545 jQuery("#firstp").trigger("click");
547 // Remove the remaining fn
548 jQuery("#firstp").unbind(".test");
550 // Trigger the remaining fn (1)
551 jQuery("#firstp").trigger("custom");
554 test("bind(), with same function", function() {
557 var count = 0, func = function(){
561 jQuery("#liveHandlerOrder").bind("foo.bar", func).bind("foo.zar", func);
562 jQuery("#liveHandlerOrder").trigger("foo.bar");
564 equal(count, 1, "Verify binding function with multiple namespaces." );
566 jQuery("#liveHandlerOrder").unbind("foo.bar", func).unbind("foo.zar", func);
567 jQuery("#liveHandlerOrder").trigger("foo.bar");
569 equal(count, 1, "Verify that removing events still work." );
572 test("bind(), make sure order is maintained", function() {
575 var elem = jQuery("#firstp"), log = [], check = [];
577 jQuery.each( new Array(100), function( i ) {
578 elem.bind( "click", function(){
586 elem.trigger("click");
588 equal( log.join(","), check.join(","), "Make sure order was maintained." );
590 elem.unbind("click");
593 test("bind(), with different this object", function() {
595 var thisObject = { myThis: true },
596 data = { myData: true },
597 handler1 = function( event ) {
598 equal( this, thisObject, "bind() with different this object" );
600 handler2 = function( event ) {
601 equal( this, thisObject, "bind() with different this object and data" );
602 equal( event.data, data, "bind() with different this object and data" );
606 .bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
607 .bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2);
609 ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
612 test("bind(name, false), unbind(name, false)", function() {
616 jQuery("#qunit-fixture").bind("click", function(e){ main++; });
617 jQuery("#ap").trigger("click");
618 equal( main, 1, "Verify that the trigger happened correctly." );
621 jQuery("#ap").bind("click", false);
622 jQuery("#ap").trigger("click");
623 equal( main, 0, "Verify that no bubble happened." );
626 jQuery("#ap").unbind("click", false);
627 jQuery("#ap").trigger("click");
628 equal( main, 1, "Verify that the trigger happened correctly." );
630 // manually clean up events from elements outside the fixture
631 jQuery("#qunit-fixture").unbind("click");
634 test("live(name, false), die(name, false)", function() {
638 jQuery("#qunit-fixture").live("click", function(e){ main++; });
639 jQuery("#ap").trigger("click");
640 equal( main, 1, "Verify that the trigger happened correctly." );
643 jQuery("#ap").live("click", false);
644 jQuery("#ap").trigger("click");
645 equal( main, 0, "Verify that no bubble happened." );
648 jQuery("#ap").die("click", false);
649 jQuery("#ap").trigger("click");
650 equal( main, 1, "Verify that the trigger happened correctly." );
651 jQuery("#qunit-fixture").die("click");
654 test("delegate(selector, name, false), undelegate(selector, name, false)", function() {
659 jQuery("#qunit-fixture").delegate("#ap", "click", function(e){ main++; });
660 jQuery("#ap").trigger("click");
661 equal( main, 1, "Verify that the trigger happened correctly." );
664 jQuery("#ap").delegate("#groups", "click", false);
665 jQuery("#groups").trigger("click");
666 equal( main, 0, "Verify that no bubble happened." );
669 jQuery("#ap").undelegate("#groups", "click", false);
670 jQuery("#groups").trigger("click");
671 equal( main, 1, "Verify that the trigger happened correctly." );
672 jQuery("#qunit-fixture").undelegate("#ap", "click");
675 test("bind()/trigger()/unbind() on plain object", function() {
680 // Make sure it doesn't complain when no events are found
681 jQuery(obj).trigger("test");
683 // Make sure it doesn't complain when no events are found
684 jQuery(obj).unbind("test");
688 ok( true, "Custom event run." );
690 "submit": function() {
691 ok( true, "Custom submit event run." );
695 var events = jQuery._data(obj, "events");
696 ok( events, "Object has events bound." );
697 equal( obj["events"], undefined, "Events object on plain objects is not events" );
698 equal( obj["test"], undefined, "Make sure that test event is not on the plain object." );
699 equal( obj["handle"], undefined, "Make sure that the event handler is not on the plain object." );
702 jQuery(obj).trigger("test");
703 jQuery(obj).trigger("submit");
705 jQuery(obj).unbind("test");
706 jQuery(obj).unbind("submit");
709 jQuery(obj).trigger("test");
711 // Make sure it doesn't complain when no events are found
712 jQuery(obj).unbind("test");
714 equal( obj && obj[ jQuery.expando ] &&
715 obj[ jQuery.expando ][ jQuery.expando ] &&
716 obj[ jQuery.expando ][ jQuery.expando ]["events"], undefined, "Make sure events object is removed" );
719 test("unbind(type)", function() {
722 var $elem = jQuery("#firstp"),
726 ok( false, message );
729 message = "unbind passing function";
730 $elem.bind("error1", error).unbind("error1", error).triggerHandler("error1");
732 message = "unbind all from event";
733 $elem.bind("error1", error).unbind("error1").triggerHandler("error1");
735 message = "unbind all";
736 $elem.bind("error1", error).unbind().triggerHandler("error1");
738 message = "unbind many with function";
739 $elem.bind("error1 error2",error)
740 .unbind("error1 error2", error )
741 .trigger("error1").triggerHandler("error2");
743 message = "unbind many"; // #3538
744 $elem.bind("error1 error2", error)
745 .unbind("error1 error2")
746 .trigger("error1").triggerHandler("error2");
748 message = "unbind without a type or handler";
749 $elem.bind("error1 error2.test",error)
751 .trigger("error1").triggerHandler("error2");
753 // Should only unbind the specified function
754 jQuery( document ).bind( "click", function(){
755 ok( true, "called handler after selective removal");
757 var func = function(){ };
759 .bind( "click", func )
760 .unbind( "click", func )
765 test("unbind(eventObject)", function() {
768 var $elem = jQuery("#firstp"),
771 function assert( expected ){
773 $elem.trigger("foo").triggerHandler("bar");
774 equal( num, expected, "Check the right handlers are triggered" );
778 // This handler shouldn't be unbound
779 .bind("foo", function(){
782 .bind("foo", function(e){
787 .bind("bar", function(){
801 test("hover() mouseenter mouseleave", function() {
805 handler1 = function( event ) { ++times; },
806 handler2 = function( event ) { ++times; };
809 .hover(handler1, handler2)
810 .mouseenter().mouseleave()
811 .unbind("mouseenter", handler1)
812 .unbind("mouseleave", handler2)
814 .mouseenter().mouseleave()
815 .unbind("mouseenter mouseleave", handler1)
816 .mouseenter().mouseleave();
818 equal( times, 4, "hover handlers fired" );
822 test("mouseover triggers mouseenter", function() {
826 elem = jQuery("<a />");
827 elem.mouseenter(function () {
830 elem.trigger("mouseover");
831 equal(count, 1, "make sure mouseover triggers a mouseenter" );
836 test("withinElement implemented with jQuery.contains()", function() {
840 jQuery("#qunit-fixture").append("<div id='jc-outer'><div id='jc-inner'></div></div>");
842 jQuery("#jc-outer").bind("mouseenter mouseleave", function( event ) {
844 equal( this.id, "jc-outer", this.id + " " + event.type );
846 }).trigger("mouseenter");
848 jQuery("#jc-inner").trigger("mousenter");
850 jQuery("#jc-outer").unbind("mouseenter mouseleave").remove();
851 jQuery("#jc-inner").remove();
855 test("mouseenter, mouseleave don't catch exceptions", function() {
858 var elem = jQuery("#firstp").hover(function() { throw "an Exception"; });
863 equal( e, "an Exception", "mouseenter doesn't catch exceptions" );
869 equal( e, "an Exception", "mouseleave doesn't catch exceptions" );
873 test("trigger() shortcuts", function() {
876 var elem = jQuery("<li><a href='#'>Change location</a></li>").prependTo("#firstUL");
877 elem.find("a").bind("click", function() {
878 var close = jQuery("spanx", this); // same with jQuery(this).find("span");
879 equal( close.length, 0, "Context element does not exist, length must be zero" );
880 ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
884 // manually clean up detached elements
887 jQuery("#check1").click(function() {
888 ok( true, "click event handler for checkbox gets fired twice, see #815" );
892 jQuery("#firstp")[0].onclick = function(event) {
895 jQuery("#firstp").click();
896 equal( counter, 1, "Check that click, triggers onclick event handler also" );
898 var clickCounter = 0;
899 jQuery("#simon1")[0].onclick = function(event) {
902 jQuery("#simon1").click();
903 equal( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
905 elem = jQuery("<img />").load(function(){
906 ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
909 // manually clean up detached elements
912 // test that special handlers do not blow up with VML elements (#7071)
913 jQuery("<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />").appendTo("head");
914 jQuery("<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>").appendTo("#form");
915 jQuery("#oval").click().keydown();
918 test("trigger() bubbling", function() {
921 var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
923 jQuery(window).bind("click", function(e){ win++; });
924 jQuery(document).bind("click", function(e){ if ( e.target !== document) { doc++; } });
925 jQuery("html").bind("click", function(e){ html++; });
926 jQuery("body").bind("click", function(e){ body++; });
927 jQuery("#qunit-fixture").bind("click", function(e){ main++; });
928 jQuery("#ap").bind("click", function(){ ap++; return false; });
930 jQuery("html").trigger("click");
931 equal( win, 1, "HTML bubble" );
932 equal( doc, 1, "HTML bubble" );
933 equal( html, 1, "HTML bubble" );
935 jQuery("body").trigger("click");
936 equal( win, 2, "Body bubble" );
937 equal( doc, 2, "Body bubble" );
938 equal( html, 2, "Body bubble" );
939 equal( body, 1, "Body bubble" );
941 jQuery("#qunit-fixture").trigger("click");
942 equal( win, 3, "Main bubble" );
943 equal( doc, 3, "Main bubble" );
944 equal( html, 3, "Main bubble" );
945 equal( body, 2, "Main bubble" );
946 equal( main, 1, "Main bubble" );
948 jQuery("#ap").trigger("click");
949 equal( doc, 3, "ap bubble" );
950 equal( html, 3, "ap bubble" );
951 equal( body, 2, "ap bubble" );
952 equal( main, 1, "ap bubble" );
953 equal( ap, 1, "ap bubble" );
955 jQuery( document ).trigger("click");
956 equal( win, 4, "doc bubble" );
958 // manually clean up events from elements outside the fixture
959 jQuery(document).unbind("click");
960 jQuery("html, body, #qunit-fixture").unbind("click");
963 test("trigger(type, [data], [fn])", function() {
966 var handler = function(event, a, b, c) {
967 equal( event.type, "click", "check passed data" );
968 equal( a, 1, "check passed data" );
969 equal( b, "2", "check passed data" );
970 equal( c, "abc", "check passed data" );
974 var $elem = jQuery("#firstp");
976 // Simulate a "native" click
977 $elem[0].click = function(){
978 ok( true, "Native call was triggered" );
982 $elem.live("mouseenter", function(){
983 ok( true, "Trigger mouseenter bound by live" );
986 $elem.live("mouseleave", function(){
987 ok( true, "Trigger mouseleave bound by live" );
990 $elem.trigger("mouseenter");
992 $elem.trigger("mouseleave");
994 $elem.die("mouseenter");
996 $elem.die("mouseleave");
998 // Triggers handlrs and native
1000 $elem.bind("click", handler).trigger("click", [1, "2", "abc"]);
1002 // Simulate a "native" click
1003 $elem[0].click = function(){
1004 ok( false, "Native call was triggered" );
1007 // Trigger only the handlers (no native)
1009 equal( $elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
1011 var pass = true, elem2;
1013 elem2 = jQuery("#form input:first");
1014 elem2.get(0).style.display = "none";
1015 elem2.trigger("focus");
1019 ok( pass, "Trigger focus on hidden element" );
1023 jQuery("#qunit-fixture table:first").bind("test:test", function(){}).trigger("test:test");
1027 ok( pass, "Trigger on a table with a colon in the even type, see #3533" );
1029 var form = jQuery("<form action=''></form>").appendTo("body");
1031 // Make sure it can be prevented locally
1032 form.submit(function(){
1033 ok( true, "Local bind still works." );
1038 form.trigger("submit");
1040 form.unbind("submit");
1042 jQuery(document).submit(function(){
1043 ok( true, "Make sure bubble works up to document." );
1048 form.trigger("submit");
1050 jQuery(document).unbind("submit");
1055 test( "submit event bubbles on copied forms (#11649)", function(){
1058 var $formByClone, $formByHTML,
1059 $testForm = jQuery("#testForm"),
1060 $fixture = jQuery("#qunit-fixture"),
1061 $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
1063 function noSubmit( e ) {
1066 function delegatedSubmit() {
1067 ok( true, "Make sure submit event bubbles up." );
1071 // Attach a delegated submit handler to the parent element
1072 $fixture.on( "submit", "form", delegatedSubmit );
1074 // Trigger form submission to introduce the _submit_attached property
1075 $testForm.on( "submit", noSubmit ).find("input[name=sub1]").click();
1077 // Copy the form via .clone() and .html()
1078 $formByClone = $testForm.clone( true, true ).removeAttr("id");
1079 $formByHTML = jQuery( $fixture.html() ).filter("#testForm").removeAttr("id");
1080 $wrapperDiv.append( $formByClone, $formByHTML );
1082 // Check submit bubbling on the copied forms
1083 $wrapperDiv.find("form").on( "submit", noSubmit ).find("input[name=sub1]").click();
1086 $wrapperDiv.remove();
1087 $fixture.off( "submit", "form", delegatedSubmit );
1088 $testForm.off( "submit", noSubmit );
1091 test( "change event bubbles on copied forms (#11796)", function(){
1094 var $formByClone, $formByHTML,
1095 $form = jQuery("#form"),
1096 $fixture = jQuery("#qunit-fixture"),
1097 $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
1099 function delegatedChange() {
1100 ok( true, "Make sure change event bubbles up." );
1104 // Attach a delegated change handler to the form
1105 $fixture.on( "change", "form", delegatedChange );
1107 // Trigger change event to introduce the _change_attached property
1108 $form.find("select[name=select1]").val("1").change();
1110 // Copy the form via .clone() and .html()
1111 $formByClone = $form.clone( true, true ).removeAttr("id");
1112 $formByHTML = jQuery( $fixture.html() ).filter("#form").removeAttr("id");
1113 $wrapperDiv.append( $formByClone, $formByHTML );
1115 // Check change bubbling on the copied forms
1116 $wrapperDiv.find("form select[name=select1]").val("2").change();
1119 $wrapperDiv.remove();
1120 $fixture.off( "change", "form", delegatedChange );
1123 test("trigger(eventObject, [data], [fn])", function() {
1126 var $parent = jQuery("<div id='par' />").appendTo("body"),
1127 $child = jQuery("<p id='child'>foo</p>").appendTo( $parent );
1129 $parent.get( 0 ).style.display = "none";
1131 var event = jQuery.Event("noNew");
1132 ok( event != window, "Instantiate jQuery.Event without the 'new' keyword" );
1133 equal( event.type, "noNew", "Verify its type" );
1135 equal( event.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1136 equal( event.isPropagationStopped(), false, "Verify isPropagationStopped" );
1137 equal( event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1139 event.preventDefault();
1140 equal( event.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
1141 event.stopPropagation();
1142 equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
1144 event.isPropagationStopped = function(){ return false; };
1145 event.stopImmediatePropagation();
1146 equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
1147 equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
1149 $parent.bind("foo",function(e){
1151 equal( e.type, "foo", "Verify event type when passed passing an event object" );
1152 equal( e.target.id, "child", "Verify event.target when passed passing an event object" );
1153 equal( e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object" );
1154 equal( e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object" );
1157 // test with an event object
1158 event = new jQuery.Event("foo");
1159 event.secret = "boo!";
1160 $child.trigger(event);
1162 // test with a literal object
1163 $child.trigger({"type": "foo", "secret": "boo!"});
1168 ok( false, "This assertion shouldn't be reached");
1171 $parent.bind("foo", error );
1173 $child.bind("foo",function(e, a, b, c ){
1174 equal( arguments.length, 4, "Check arguments length");
1175 equal( a, 1, "Check first custom argument");
1176 equal( b, 2, "Check second custom argument");
1177 equal( c, 3, "Check third custom argument");
1179 equal( e.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
1180 equal( e.isPropagationStopped(), false, "Verify isPropagationStopped" );
1181 equal( e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
1183 // Skips both errors
1184 e.stopImmediatePropagation();
1189 // We should add this back in when we want to test the order
1190 // in which event handlers are iterated.
1191 //$child.bind("foo", error );
1193 event = new jQuery.Event("foo");
1194 $child.trigger( event, [1,2,3] ).unbind();
1195 equal( event.result, "result", "Check event.result attribute");
1197 // Will error if it bubbles
1198 $child.triggerHandler("foo");
1201 $parent.unbind().remove();
1203 // Ensure triggerHandler doesn't molest its event object (#xxx)
1204 event = jQuery.Event( "zowie" );
1205 jQuery( document ).triggerHandler( event );
1206 equal( event.type, "zowie", "Verify its type" );
1207 equal( event.isPropagationStopped(), false, "propagation not stopped" );
1208 equal( event.isDefaultPrevented(), false, "default not prevented" );
1211 test(".trigger() bubbling on disconnected elements (#10489)", function() {
1214 jQuery( window ).on( "click", function(){
1215 ok( false, "click fired on window" );
1218 jQuery( "<div><p>hi</p></div>" )
1219 .on( "click", function() {
1220 ok( true, "click fired on div" );
1223 .on( "click", function() {
1224 ok( true, "click fired on p" );
1232 jQuery( window ).off( "click" );
1235 test(".trigger() doesn't bubble load event (#10717)", function() {
1238 jQuery( window ).on( "load", function(){
1239 ok( false, "load fired on window" );
1242 // It's not an image, but as long as it fires load...
1243 jQuery("<img src='index.html' />")
1245 .on( "load", function() {
1246 ok( true, "load fired on img" );
1251 jQuery( window ).off( "load" );
1254 test("Delegated events in SVG (#10791)", function() {
1258 "<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>" +
1259 "<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1260 "<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
1262 ).appendTo( "body" );
1265 .on( "click", "#svg-by-id", function() {
1266 ok( true, "delegated id selector" );
1268 .on( "click", "[class~='svg-by-class']", function() {
1269 ok( true, "delegated class selector" );
1271 .find( "#svg-by-id, [class~='svg-by-class']" )
1279 test("Delegated events in forms (#10844; #11145; #8165; #11382, #11764)", function() {
1282 // Alias names like "id" cause havoc
1284 "<form id='myform'>" +
1285 "<input type='text' name='id' value='secret agent man' />" +
1288 .on( "submit", function( event ) {
1289 event.preventDefault();
1294 .on( "submit", "#myform", function() {
1295 ok( true, "delegated id selector with aliased id" );
1302 form.append("<input type='text' name='disabled' value='differently abled' />");
1304 .on( "submit", "#myform", function() {
1305 ok( true, "delegated id selector with aliased disabled" );
1313 .append( "<button id='nestyDisabledBtn'><span>Zing</span></button>" )
1314 .on( "click", "#nestyDisabledBtn", function() {
1315 ok( true, "click on enabled/disabled button with nesty elements" );
1317 .on( "mouseover", "#nestyDisabledBtn", function() {
1318 ok( true, "mouse on enabled/disabled button with nesty elements" );
1321 .trigger( "click" ) // yep
1322 .trigger( "mouseover" ) // yep
1324 .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
1326 .trigger( "click" ) // nope
1327 .trigger( "mouseover" ) // yep
1334 test("Submit event can be stopped (#11049)", function() {
1337 // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
1339 "<form id='myform'>" +
1340 "<input type='text' name='sue' value='bawls' />" +
1341 "<input type='submit' />" +
1347 .on( "submit", function() {
1348 ok( true, "submit bubbled on first handler" );
1351 .find( "#myform input[type=submit]" )
1352 .each( function(){ this.click(); } )
1354 .on( "submit", function() {
1355 ok( false, "submit bubbled on second handler" );
1358 .find( "#myform input[type=submit]" )
1360 jQuery( this.form ).on( "submit", function( e ) {
1362 e.stopPropagation();
1372 test("on(beforeunload) creates/deletes window property instead of adding/removing event listener", function() {
1375 equal( window.onbeforeunload, null, "window property is null/undefined up until now" );
1377 var handle = function () {};
1378 jQuery(window).on( "beforeunload", handle );
1380 equal( typeof window.onbeforeunload, "function", "window property is set to a function");
1382 jQuery(window).off( "beforeunload", handle );
1384 equal( window.onbeforeunload, null, "window property has been unset to null/undefined" );
1387 test("jQuery.Event( type, props )", function() {
1391 var event = jQuery.Event( "keydown", { keyCode: 64 }),
1392 handler = function( event ) {
1393 ok( "keyCode" in event, "Special property 'keyCode' exists" );
1394 equal( event.keyCode, 64, "event.keyCode has explicit value '64'" );
1397 // Supports jQuery.Event implementation
1398 equal( event.type, "keydown", "Verify type" );
1400 // ensure "type" in props won't clobber the one set by constructor
1401 equal( jQuery.inArray("type", jQuery.event.props), -1, "'type' property not in props (#10375)" );
1403 ok( "keyCode" in event, "Special 'keyCode' property exists" );
1405 jQuery("body").bind( "keydown", handler ).trigger( event );
1407 jQuery("body").unbind( "keydown" );
1411 test("jQuery.Event.currentTarget", function(){
1414 jQuery("<div><p><button>shiny</button></p></div>")
1415 .on( "click", "p", function( e ){
1416 equal( e.currentTarget, this, "Check delegated currentTarget on event" );
1419 .on( "click", function( e ){
1420 equal( e.currentTarget, this, "Check currentTarget on event" );
1428 test(".live()/.die()", function() {
1431 var submit = 0, div = 0, livea = 0, liveb = 0;
1433 jQuery("div").live("submit", function(){ submit++; return false; });
1434 jQuery("div").live("click", function(){ div++; });
1435 jQuery("div#nothiddendiv").live("click", function(){ livea++; });
1436 jQuery("div#nothiddendivchild").live("click", function(){ liveb++; });
1438 // Nothing should trigger on the body
1439 jQuery("body").trigger("click");
1440 equal( submit, 0, "Click on body" );
1441 equal( div, 0, "Click on body" );
1442 equal( livea, 0, "Click on body" );
1443 equal( liveb, 0, "Click on body" );
1445 // This should trigger two events
1446 submit = 0; div = 0; livea = 0; liveb = 0;
1447 jQuery("div#nothiddendiv").trigger("click");
1448 equal( submit, 0, "Click on div" );
1449 equal( div, 1, "Click on div" );
1450 equal( livea, 1, "Click on div" );
1451 equal( liveb, 0, "Click on div" );
1453 // This should trigger three events (w/ bubbling)
1454 submit = 0; div = 0; livea = 0; liveb = 0;
1455 jQuery("div#nothiddendivchild").trigger("click");
1456 equal( submit, 0, "Click on inner div" );
1457 equal( div, 2, "Click on inner div" );
1458 equal( livea, 1, "Click on inner div" );
1459 equal( liveb, 1, "Click on inner div" );
1461 // This should trigger one submit
1462 submit = 0; div = 0; livea = 0; liveb = 0;
1463 jQuery("div#nothiddendivchild").trigger("submit");
1464 equal( submit, 1, "Submit on div" );
1465 equal( div, 0, "Submit on div" );
1466 equal( livea, 0, "Submit on div" );
1467 equal( liveb, 0, "Submit on div" );
1469 // Make sure no other events were removed in the process
1470 submit = 0; div = 0; livea = 0; liveb = 0;
1471 jQuery("div#nothiddendivchild").trigger("click");
1472 equal( submit, 0, "die Click on inner div" );
1473 equal( div, 2, "die Click on inner div" );
1474 equal( livea, 1, "die Click on inner div" );
1475 equal( liveb, 1, "die Click on inner div" );
1477 // Now make sure that the removal works
1478 submit = 0; div = 0; livea = 0; liveb = 0;
1479 jQuery("div#nothiddendivchild").die("click");
1480 jQuery("div#nothiddendivchild").trigger("click");
1481 equal( submit, 0, "die Click on inner div" );
1482 equal( div, 2, "die Click on inner div" );
1483 equal( livea, 1, "die Click on inner div" );
1484 equal( liveb, 0, "die Click on inner div" );
1486 // Make sure that the click wasn't removed too early
1487 submit = 0; div = 0; livea = 0; liveb = 0;
1488 jQuery("div#nothiddendiv").trigger("click");
1489 equal( submit, 0, "die Click on inner div" );
1490 equal( div, 1, "die Click on inner div" );
1491 equal( livea, 1, "die Click on inner div" );
1492 equal( liveb, 0, "die Click on inner div" );
1494 // Make sure that stopPropgation doesn't stop live events
1495 submit = 0; div = 0; livea = 0; liveb = 0;
1496 jQuery("div#nothiddendivchild").live("click", function(e){ liveb++; e.stopPropagation(); });
1497 jQuery("div#nothiddendivchild").trigger("click");
1498 equal( submit, 0, "stopPropagation Click on inner div" );
1499 equal( div, 1, "stopPropagation Click on inner div" );
1500 equal( livea, 0, "stopPropagation Click on inner div" );
1501 equal( liveb, 1, "stopPropagation Click on inner div" );
1503 // Make sure click events only fire with primary click
1504 submit = 0; div = 0; livea = 0; liveb = 0;
1505 var event = jQuery.Event("click");
1507 jQuery("div#nothiddendiv").trigger(event);
1509 equal( livea, 0, "live secondary click" );
1511 jQuery("div#nothiddendivchild").die("click");
1512 jQuery("div#nothiddendiv").die("click");
1513 jQuery("div").die("click");
1514 jQuery("div").die("submit");
1516 // Test binding with a different context
1517 var clicked = 0, container = jQuery("#qunit-fixture")[0];
1518 jQuery("#foo", container).live("click", function(e){ clicked++; });
1519 jQuery("div").trigger("click");
1520 jQuery("#foo").trigger("click");
1521 jQuery("#qunit-fixture").trigger("click");
1522 jQuery("body").trigger("click");
1523 equal( clicked, 2, "live with a context" );
1525 // Test unbinding with a different context
1526 jQuery("#foo", container).die("click");
1527 jQuery("#foo").trigger("click");
1528 equal( clicked, 2, "die with a context");
1530 // Test binding with event data
1531 jQuery("#foo").live("click", true, function(e){ equal( e.data, true, "live with event data" ); });
1532 jQuery("#foo").trigger("click").die("click");
1534 // Test binding with trigger data
1535 jQuery("#foo").live("click", function(e, data){ equal( data, true, "live with trigger data" ); });
1536 jQuery("#foo").trigger("click", true).die("click");
1538 // Test binding with different this object
1539 jQuery("#foo").live("click", jQuery.proxy(function(e){ equal( this.foo, "bar", "live with event scope" ); }, { foo: "bar" }));
1540 jQuery("#foo").trigger("click").die("click");
1542 // Test binding with different this object, event data, and trigger data
1543 jQuery("#foo").live("click", true, jQuery.proxy(function(e, data){
1544 equal( e.data, true, "live with with different this object, event data, and trigger data" );
1545 equal( this["foo"], "bar", "live with with different this object, event data, and trigger data" );
1546 equal( data, true, "live with with different this object, event data, and trigger data");
1547 }, { "foo": "bar" }));
1548 jQuery("#foo").trigger("click", true).die("click");
1550 // Verify that return false prevents default action
1551 jQuery("#anchor2").live("click", function(){ return false; });
1552 var hash = window.location.hash;
1553 jQuery("#anchor2").trigger("click");
1554 equal( window.location.hash, hash, "return false worked" );
1555 jQuery("#anchor2").die("click");
1557 // Verify that .preventDefault() prevents default action
1558 jQuery("#anchor2").live("click", function(e){ e.preventDefault(); });
1559 hash = window.location.hash;
1560 jQuery("#anchor2").trigger("click");
1561 equal( window.location.hash, hash, "e.preventDefault() worked" );
1562 jQuery("#anchor2").die("click");
1564 // Test binding the same handler to multiple points
1566 function callback(){ called++; return false; }
1568 jQuery("#nothiddendiv").live("click", callback);
1569 jQuery("#anchor2").live("click", callback);
1571 jQuery("#nothiddendiv").trigger("click");
1572 equal( called, 1, "Verify that only one click occurred." );
1575 jQuery("#anchor2").trigger("click");
1576 equal( called, 1, "Verify that only one click occurred." );
1578 // Make sure that only one callback is removed
1579 jQuery("#anchor2").die("click", callback);
1582 jQuery("#nothiddendiv").trigger("click");
1583 equal( called, 1, "Verify that only one click occurred." );
1586 jQuery("#anchor2").trigger("click");
1587 equal( called, 0, "Verify that no click occurred." );
1589 // Make sure that it still works if the selector is the same,
1590 // but the event type is different
1591 jQuery("#nothiddendiv").live("foo", callback);
1594 jQuery("#nothiddendiv").die("click", callback);
1597 jQuery("#nothiddendiv").trigger("click");
1598 equal( called, 0, "Verify that no click occurred." );
1601 jQuery("#nothiddendiv").trigger("foo");
1602 equal( called, 1, "Verify that one foo occurred." );
1605 jQuery("#nothiddendiv").die("foo", callback);
1607 // Make sure we don't loose the target by DOM modifications
1608 // after the bubble already reached the liveHandler
1609 var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("<span></span>").get(0);
1611 jQuery("#nothiddendivchild").live("click", function(e){ jQuery("#nothiddendivchild").html(""); });
1612 jQuery("#nothiddendivchild").live("click", function(e){ if(e.target) {livec++;} });
1614 jQuery("#nothiddendiv span").click();
1615 equal( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
1616 equal( livec, 1, "Verify that second handler occurred even with nuked target." );
1619 jQuery("#nothiddendivchild").die("click");
1621 // Verify that .live() ocurs and cancel buble in the same order as
1622 // we would expect .bind() and .click() without delegation
1623 var lived = 0, livee = 0;
1625 // bind one pair in one order
1626 jQuery("span#liveSpan1 a").live("click", function(){ lived++; return false; });
1627 jQuery("span#liveSpan1").live("click", function(){ livee++; });
1629 jQuery("span#liveSpan1 a").click();
1630 equal( lived, 1, "Verify that only one first handler occurred." );
1631 equal( livee, 0, "Verify that second handler doesn't." );
1633 // and one pair in inverse
1634 jQuery("span#liveSpan2").live("click", function(){ livee++; });
1635 jQuery("span#liveSpan2 a").live("click", function(){ lived++; return false; });
1639 jQuery("span#liveSpan2 a").click();
1640 equal( lived, 1, "Verify that only one first handler occurred." );
1641 equal( livee, 0, "Verify that second handler doesn't." );
1644 jQuery("span#liveSpan1 a").die("click");
1645 jQuery("span#liveSpan1").die("click");
1646 jQuery("span#liveSpan2 a").die("click");
1647 jQuery("span#liveSpan2").die("click");
1649 // Test this, target and currentTarget are correct
1650 jQuery("span#liveSpan1").live("click", function(e){
1651 equal( this.id, "liveSpan1", "Check the this within a live handler" );
1652 equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a live handler" );
1653 equal( e.delegateTarget, document, "Check the event.delegateTarget within a live handler" );
1654 equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a live handler" );
1657 jQuery("span#liveSpan1 a").click();
1659 jQuery("span#liveSpan1").die("click");
1661 // Work with deep selectors
1664 function clickB(){ livee++; }
1666 jQuery("#nothiddendiv div").live("click", function(){ livee++; });
1667 jQuery("#nothiddendiv div").live("click", clickB);
1668 jQuery("#nothiddendiv div").live("mouseover", function(){ livee++; });
1670 equal( livee, 0, "No clicks, deep selector." );
1673 jQuery("#nothiddendivchild").trigger("click");
1674 equal( livee, 2, "Click, deep selector." );
1677 jQuery("#nothiddendivchild").trigger("mouseover");
1678 equal( livee, 1, "Mouseover, deep selector." );
1680 jQuery("#nothiddendiv div").die("mouseover");
1683 jQuery("#nothiddendivchild").trigger("click");
1684 equal( livee, 2, "Click, deep selector." );
1687 jQuery("#nothiddendivchild").trigger("mouseover");
1688 equal( livee, 0, "Mouseover, deep selector." );
1690 jQuery("#nothiddendiv div").die("click", clickB);
1693 jQuery("#nothiddendivchild").trigger("click");
1694 equal( livee, 1, "Click, deep selector." );
1696 jQuery("#nothiddendiv div").die("click");
1698 // blur a non-input element, we should force-fire its handlers
1699 // regardless of whether it's burring or not (unlike browsers)
1700 jQuery("#nothiddendiv div")
1701 .live("blur", function(){
1702 ok( true, "Live div trigger blur." );
1708 test("die all bound events", function(){
1712 var div = jQuery("div#nothiddendivchild");
1714 div.live("click submit", function(){ count++; });
1717 div.trigger("click");
1718 div.trigger("submit");
1720 equal( count, 0, "Make sure no events were triggered." );
1723 test("live with multiple events", function(){
1727 var div = jQuery("div#nothiddendivchild");
1729 div.live("click submit", function(){ count++; });
1731 div.trigger("click");
1732 div.trigger("submit");
1734 equal( count, 2, "Make sure both the click and submit were triggered." );
1736 // manually clean up events from elements outside the fixture
1740 test("live with namespaces", function(){
1743 var count1 = 0, count2 = 0;
1745 jQuery("#liveSpan1").live("foo.bar", function(e){
1746 equal( e.namespace, "bar", "namespace is bar" );
1750 jQuery("#liveSpan1").live("foo.zed", function(e){
1751 equal( e.namespace, "zed", "namespace is zed" );
1755 jQuery("#liveSpan1").trigger("foo.bar");
1756 equal( count1, 1, "Got live foo.bar" );
1757 equal( count2, 0, "Got live foo.bar" );
1759 count1 = 0; count2 = 0;
1761 jQuery("#liveSpan1").trigger("foo.zed");
1762 equal( count1, 0, "Got live foo.zed" );
1763 equal( count2, 1, "Got live foo.zed" );
1766 count1 = 0; count2 = 0;
1768 jQuery("#liveSpan1").die("foo.zed");
1769 jQuery("#liveSpan1").trigger("foo.bar");
1771 equal( count1, 1, "Got live foo.bar after dieing foo.zed" );
1772 equal( count2, 0, "Got live foo.bar after dieing foo.zed" );
1774 count1 = 0; count2 = 0;
1776 jQuery("#liveSpan1").trigger("foo.zed");
1777 equal( count1, 0, "Got live foo.zed" );
1778 equal( count2, 0, "Got live foo.zed" );
1781 jQuery("#liveSpan1").die("foo.bar");
1783 count1 = 0; count2 = 0;
1785 jQuery("#liveSpan1").trigger("foo.bar");
1786 equal( count1, 0, "Did not respond to foo.bar after dieing it" );
1787 equal( count2, 0, "Did not respond to foo.bar after dieing it" );
1789 jQuery("#liveSpan1").trigger("foo.zed");
1790 equal( count1, 0, "Did not trigger foo.zed again" );
1791 equal( count2, 0, "Did not trigger foo.zed again" );
1794 test("live with change", function(){
1797 var selectChange = 0, checkboxChange = 0;
1799 var select = jQuery("select[name='S1']");
1800 select.live("change", function() {
1804 var checkbox = jQuery("#check2"),
1805 checkboxFunction = function(){
1808 checkbox.live("change", checkboxFunction);
1810 // test click on select
1812 // second click that changed it
1814 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1815 select.trigger("change");
1816 equal( selectChange, 1, "Change on click." );
1818 // test keys on select
1820 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1821 select.trigger("change");
1822 equal( selectChange, 1, "Change on keyup." );
1824 // test click on checkbox
1825 checkbox.trigger("change");
1826 equal( checkboxChange, 1, "Change on checkbox." );
1828 // test blur/focus on text
1829 var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
1830 text.live("change", function() {
1834 text.val(oldTextVal+"foo");
1835 text.trigger("change");
1836 equal( textChange, 1, "Change on text input." );
1838 text.val(oldTextVal);
1841 // test blur/focus on password
1842 var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
1843 password.live("change", function() {
1847 password.val(oldPasswordVal + "foo");
1848 password.trigger("change");
1849 equal( passwordChange, 1, "Change on password input." );
1851 password.val(oldPasswordVal);
1852 password.die("change");
1854 // make sure die works
1858 select.die("change");
1859 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1860 select.trigger("change");
1861 equal( selectChange, 0, "Die on click works." );
1864 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
1865 select.trigger("change");
1866 equal( selectChange, 0, "Die on keyup works." );
1868 // die specific checkbox
1869 checkbox.die("change", checkboxFunction);
1870 checkbox.trigger("change");
1871 equal( checkboxChange, 1, "Die on checkbox." );
1874 test("live with submit", function() {
1877 var count1 = 0, count2 = 0;
1879 jQuery("#testForm").live("submit", function(ev) {
1881 ev.preventDefault();
1884 jQuery("body").live("submit", function(ev) {
1886 ev.preventDefault();
1889 jQuery("#testForm input[name=sub1]").submit();
1890 equal( count1, 1, "Verify form submit." );
1891 equal( count2, 1, "Verify body submit." );
1893 jQuery("#testForm input[name=sub1]").live("click", function(ev) {
1894 ok( true, "cancelling submit still calls click handler" );
1897 jQuery("#testForm input[name=sub1]")[0].click();
1898 equal( count1, 2, "Verify form submit." );
1899 equal( count2, 2, "Verify body submit." );
1901 jQuery("#testForm button[name=sub4]")[0].click();
1902 equal( count1, 3, "Verify form submit." );
1903 equal( count2, 3, "Verify body submit." );
1905 jQuery("#testForm").die("submit");
1906 jQuery("#testForm input[name=sub1]").die("click");
1907 jQuery("body").die("submit");
1910 test("live with special events", function() {
1913 jQuery.event.special["foo"] = {
1914 setup: function( data, namespaces, handler ) {
1915 ok( true, "Setup run." );
1917 teardown: function( namespaces ) {
1918 ok( true, "Teardown run." );
1920 add: function( handleObj ) {
1921 ok( true, "Add run." );
1923 remove: function( handleObj ) {
1924 ok( true, "Remove run." );
1926 _default: function( event, arg ) {
1927 ok( event.type === "foo" && arg == 42, "Default run with correct args." );
1932 jQuery("#liveSpan1").live("foo.a", function(e){
1933 ok( true, "Handler 1 run." );
1937 jQuery("#liveSpan1").live("foo.b", function(e){
1938 ok( true, "Handler 2 run." );
1941 // Run: Handler 1, Handler 2, Default
1942 jQuery("#liveSpan1").trigger("foo", 42);
1944 // Run: Handler 1, Default
1945 jQuery("#liveSpan1").trigger("foo.a", 42);
1948 jQuery("#liveSpan1").die("foo.a");
1950 // Run: Handler 2, Default
1951 jQuery("#liveSpan1").trigger("foo", 42);
1953 // Run: remove, teardown
1954 jQuery("#liveSpan1").die("foo");
1956 delete jQuery.event.special["foo"];
1959 test(".delegate()/.undelegate()", function() {
1962 var submit = 0, div = 0, livea = 0, liveb = 0;
1964 jQuery("#body").delegate("div", "submit", function(){ submit++; return false; });
1965 jQuery("#body").delegate("div", "click", function(){ div++; });
1966 jQuery("#body").delegate("div#nothiddendiv", "click", function(){ livea++; });
1967 jQuery("#body").delegate("div#nothiddendivchild", "click", function(){ liveb++; });
1969 // Nothing should trigger on the body
1970 jQuery("body").trigger("click");
1971 equal( submit, 0, "Click on body" );
1972 equal( div, 0, "Click on body" );
1973 equal( livea, 0, "Click on body" );
1974 equal( liveb, 0, "Click on body" );
1976 // This should trigger two events
1977 submit = 0; div = 0; livea = 0; liveb = 0;
1978 jQuery("div#nothiddendiv").trigger("click");
1979 equal( submit, 0, "Click on div" );
1980 equal( div, 1, "Click on div" );
1981 equal( livea, 1, "Click on div" );
1982 equal( liveb, 0, "Click on div" );
1984 // This should trigger three events (w/ bubbling)
1985 submit = 0; div = 0; livea = 0; liveb = 0;
1986 jQuery("div#nothiddendivchild").trigger("click");
1987 equal( submit, 0, "Click on inner div" );
1988 equal( div, 2, "Click on inner div" );
1989 equal( livea, 1, "Click on inner div" );
1990 equal( liveb, 1, "Click on inner div" );
1992 // This should trigger one submit
1993 submit = 0; div = 0; livea = 0; liveb = 0;
1994 jQuery("div#nothiddendivchild").trigger("submit");
1995 equal( submit, 1, "Submit on div" );
1996 equal( div, 0, "Submit on div" );
1997 equal( livea, 0, "Submit on div" );
1998 equal( liveb, 0, "Submit on div" );
2000 // Make sure no other events were removed in the process
2001 submit = 0; div = 0; livea = 0; liveb = 0;
2002 jQuery("div#nothiddendivchild").trigger("click");
2003 equal( submit, 0, "undelegate Click on inner div" );
2004 equal( div, 2, "undelegate Click on inner div" );
2005 equal( livea, 1, "undelegate Click on inner div" );
2006 equal( liveb, 1, "undelegate Click on inner div" );
2008 // Now make sure that the removal works
2009 submit = 0; div = 0; livea = 0; liveb = 0;
2010 jQuery("#body").undelegate("div#nothiddendivchild", "click");
2011 jQuery("div#nothiddendivchild").trigger("click");
2012 equal( submit, 0, "undelegate Click on inner div" );
2013 equal( div, 2, "undelegate Click on inner div" );
2014 equal( livea, 1, "undelegate Click on inner div" );
2015 equal( liveb, 0, "undelegate Click on inner div" );
2017 // Make sure that the click wasn't removed too early
2018 submit = 0; div = 0; livea = 0; liveb = 0;
2019 jQuery("div#nothiddendiv").trigger("click");
2020 equal( submit, 0, "undelegate Click on inner div" );
2021 equal( div, 1, "undelegate Click on inner div" );
2022 equal( livea, 1, "undelegate Click on inner div" );
2023 equal( liveb, 0, "undelegate Click on inner div" );
2025 // Make sure that stopPropgation doesn't stop live events
2026 submit = 0; div = 0; livea = 0; liveb = 0;
2027 jQuery("#body").delegate("div#nothiddendivchild", "click", function(e){ liveb++; e.stopPropagation(); });
2028 jQuery("div#nothiddendivchild").trigger("click");
2029 equal( submit, 0, "stopPropagation Click on inner div" );
2030 equal( div, 1, "stopPropagation Click on inner div" );
2031 equal( livea, 0, "stopPropagation Click on inner div" );
2032 equal( liveb, 1, "stopPropagation Click on inner div" );
2034 // Make sure click events only fire with primary click
2035 submit = 0; div = 0; livea = 0; liveb = 0;
2036 var event = jQuery.Event("click");
2038 jQuery("div#nothiddendiv").trigger(event);
2040 equal( livea, 0, "delegate secondary click" );
2042 jQuery("#body").undelegate("div#nothiddendivchild", "click");
2043 jQuery("#body").undelegate("div#nothiddendiv", "click");
2044 jQuery("#body").undelegate("div", "click");
2045 jQuery("#body").undelegate("div", "submit");
2047 // Test binding with a different context
2048 var clicked = 0, container = jQuery("#qunit-fixture")[0];
2049 jQuery("#qunit-fixture").delegate("#foo", "click", function(e){ clicked++; });
2050 jQuery("div").trigger("click");
2051 jQuery("#foo").trigger("click");
2052 jQuery("#qunit-fixture").trigger("click");
2053 jQuery("body").trigger("click");
2054 equal( clicked, 2, "delegate with a context" );
2056 // Test unbinding with a different context
2057 jQuery("#qunit-fixture").undelegate("#foo", "click");
2058 jQuery("#foo").trigger("click");
2059 equal( clicked, 2, "undelegate with a context");
2061 // Test binding with event data
2062 jQuery("#body").delegate("#foo", "click", true, function(e){ equal( e.data, true, "delegate with event data" ); });
2063 jQuery("#foo").trigger("click");
2064 jQuery("#body").undelegate("#foo", "click");
2066 // Test binding with trigger data
2067 jQuery("#body").delegate("#foo", "click", function(e, data){ equal( data, true, "delegate with trigger data" ); });
2068 jQuery("#foo").trigger("click", true);
2069 jQuery("#body").undelegate("#foo", "click");
2071 // Test binding with different this object
2072 jQuery("#body").delegate("#foo", "click", jQuery.proxy(function(e){ equal( this["foo"], "bar", "delegate with event scope" ); }, { "foo": "bar" }));
2073 jQuery("#foo").trigger("click");
2074 jQuery("#body").undelegate("#foo", "click");
2076 // Test binding with different this object, event data, and trigger data
2077 jQuery("#body").delegate("#foo", "click", true, jQuery.proxy(function(e, data){
2078 equal( e.data, true, "delegate with with different this object, event data, and trigger data" );
2079 equal( this.foo, "bar", "delegate with with different this object, event data, and trigger data" );
2080 equal( data, true, "delegate with with different this object, event data, and trigger data");
2081 }, { "foo": "bar" }));
2082 jQuery("#foo").trigger("click", true);
2083 jQuery("#body").undelegate("#foo", "click");
2085 // Verify that return false prevents default action
2086 jQuery("#body").delegate("#anchor2", "click", function(){ return false; });
2087 var hash = window.location.hash;
2088 jQuery("#anchor2").trigger("click");
2089 equal( window.location.hash, hash, "return false worked" );
2090 jQuery("#body").undelegate("#anchor2", "click");
2092 // Verify that .preventDefault() prevents default action
2093 jQuery("#body").delegate("#anchor2", "click", function(e){ e.preventDefault(); });
2094 hash = window.location.hash;
2095 jQuery("#anchor2").trigger("click");
2096 equal( window.location.hash, hash, "e.preventDefault() worked" );
2097 jQuery("#body").undelegate("#anchor2", "click");
2099 // Test binding the same handler to multiple points
2101 function callback(){ called++; return false; }
2103 jQuery("#body").delegate("#nothiddendiv", "click", callback);
2104 jQuery("#body").delegate("#anchor2", "click", callback);
2106 jQuery("#nothiddendiv").trigger("click");
2107 equal( called, 1, "Verify that only one click occurred." );
2110 jQuery("#anchor2").trigger("click");
2111 equal( called, 1, "Verify that only one click occurred." );
2113 // Make sure that only one callback is removed
2114 jQuery("#body").undelegate("#anchor2", "click", callback);
2117 jQuery("#nothiddendiv").trigger("click");
2118 equal( called, 1, "Verify that only one click occurred." );
2121 jQuery("#anchor2").trigger("click");
2122 equal( called, 0, "Verify that no click occurred." );
2124 // Make sure that it still works if the selector is the same,
2125 // but the event type is different
2126 jQuery("#body").delegate("#nothiddendiv", "foo", callback);
2129 jQuery("#body").undelegate("#nothiddendiv", "click", callback);
2132 jQuery("#nothiddendiv").trigger("click");
2133 equal( called, 0, "Verify that no click occurred." );
2136 jQuery("#nothiddendiv").trigger("foo");
2137 equal( called, 1, "Verify that one foo occurred." );
2140 jQuery("#body").undelegate("#nothiddendiv", "foo", callback);
2142 // Make sure we don't loose the target by DOM modifications
2143 // after the bubble already reached the liveHandler
2144 var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("<span></span>").get(0);
2146 jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ jQuery("#nothiddendivchild").html(""); });
2147 jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ if(e.target) {livec++;} });
2149 jQuery("#nothiddendiv span").click();
2150 equal( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
2151 equal( livec, 1, "Verify that second handler occurred even with nuked target." );
2154 jQuery("#body").undelegate("#nothiddendivchild", "click");
2156 // Verify that .live() ocurs and cancel buble in the same order as
2157 // we would expect .bind() and .click() without delegation
2158 var lived = 0, livee = 0;
2160 // bind one pair in one order
2161 jQuery("#body").delegate("span#liveSpan1 a", "click", function(){ lived++; return false; });
2162 jQuery("#body").delegate("span#liveSpan1", "click", function(){ livee++; });
2164 jQuery("span#liveSpan1 a").click();
2165 equal( lived, 1, "Verify that only one first handler occurred." );
2166 equal( livee, 0, "Verify that second handler doesn't." );
2168 // and one pair in inverse
2169 jQuery("#body").delegate("span#liveSpan2", "click", function(){ livee++; });
2170 jQuery("#body").delegate("span#liveSpan2 a", "click", function(){ lived++; return false; });
2174 jQuery("span#liveSpan2 a").click();
2175 equal( lived, 1, "Verify that only one first handler occurred." );
2176 equal( livee, 0, "Verify that second handler doesn't." );
2179 jQuery("#body").undelegate("click");
2181 // Test this, target and currentTarget are correct
2182 jQuery("#body").delegate("span#liveSpan1", "click", function(e){
2183 equal( this.id, "liveSpan1", "Check the this within a delegate handler" );
2184 equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a delegate handler" );
2185 equal( e.delegateTarget, document.body, "Check the event.delegateTarget within a delegate handler" );
2186 equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a delegate handler" );
2189 jQuery("span#liveSpan1 a").click();
2191 jQuery("#body").undelegate("span#liveSpan1", "click");
2193 // Work with deep selectors
2196 function clickB(){ livee++; }
2198 jQuery("#body").delegate("#nothiddendiv div", "click", function(){ livee++; });
2199 jQuery("#body").delegate("#nothiddendiv div", "click", clickB);
2200 jQuery("#body").delegate("#nothiddendiv div", "mouseover", function(){ livee++; });
2202 equal( livee, 0, "No clicks, deep selector." );
2205 jQuery("#nothiddendivchild").trigger("click");
2206 equal( livee, 2, "Click, deep selector." );
2209 jQuery("#nothiddendivchild").trigger("mouseover");
2210 equal( livee, 1, "Mouseover, deep selector." );
2212 jQuery("#body").undelegate("#nothiddendiv div", "mouseover");
2215 jQuery("#nothiddendivchild").trigger("click");
2216 equal( livee, 2, "Click, deep selector." );
2219 jQuery("#nothiddendivchild").trigger("mouseover");
2220 equal( livee, 0, "Mouseover, deep selector." );
2222 jQuery("#body").undelegate("#nothiddendiv div", "click", clickB);
2225 jQuery("#nothiddendivchild").trigger("click");
2226 equal( livee, 1, "Click, deep selector." );
2228 jQuery("#body").undelegate("#nothiddendiv div", "click");
2231 test("jQuery.off using dispatched jQuery.Event", function() {
2234 var markup = jQuery("<p><a href='#'>target</a></p>"),
2237 .on( "click.name", "a", function( event ) {
2238 equal( ++count, 1, "event called once before removal" );
2239 jQuery().off( event );
2241 .find("a").click().click().end()
2245 test( "delegated event with delegateTarget-relative selector", function() {
2247 var markup = jQuery("<ul><li><a id=\"a0\"></a><ul id=\"ul0\"><li class=test><a id=\"a0_0\"></a></li><li><a id=\"a0_1\"></a></li></ul></li></ul>").appendTo("#qunit-fixture");
2249 // Positional selector (#11315)
2251 .on( "click", ">li>a", function() {
2252 ok( this.id === "a0", "child li was clicked" );
2255 .on( "click", "li:first>a", function() {
2256 ok( this.id === "a0_0" , "first li under #u10 was clicked" );
2259 .find("a").click().end()
2260 .find("#ul0").off();
2262 // Non-positional selector (#12383)
2263 markup = markup.wrap("<div />").parent();
2266 .on( "click", "div li a", function() {
2267 ok( false, "div is ABOVE the delegation point!" );
2269 .on( "click", "ul a", function() {
2270 ok( false, "ul is the delegation point!" );
2272 .on( "click", "li.test a", function() {
2273 ok( true, "li.test is below the delegation point." );
2275 .find("#a0_0").click();
2280 test("stopPropagation() stops directly-bound events on delegated target", function() {
2283 var markup = jQuery("<div><p><a href=\"#\">target</a></p></div>");
2285 .on( "click", function() {
2286 ok( false, "directly-bound event on delegate target was called" );
2288 .on( "click", "a", function( e ) {
2289 e.stopPropagation();
2290 ok( true, "delegated handler was called" );
2292 .find("a").click().end()
2296 test("undelegate all bound events", function(){
2301 div = jQuery("#body");
2303 div.delegate( "div#nothiddendivchild", "click submit", function(){ count++; } );
2304 div.bind( "click", function(){ clicks++; } );
2307 jQuery("div#nothiddendivchild").trigger("click");
2308 jQuery("div#nothiddendivchild").trigger("submit");
2310 equal( count, 0, "Make sure no events were triggered." );
2312 div.trigger("click");
2313 equal( clicks, 2, "Make sure delegated and directly bound event occurred." );
2314 div.unbind("click");
2317 test("delegate with multiple events", function(){
2321 var div = jQuery("#body");
2323 div.delegate("div#nothiddendivchild", "click submit", function(){ count++; });
2325 jQuery("div#nothiddendivchild").trigger("click");
2326 jQuery("div#nothiddendivchild").trigger("submit");
2328 equal( count, 2, "Make sure both the click and submit were triggered." );
2330 jQuery("#body").undelegate();
2333 test("delegate with change", function(){
2336 var selectChange = 0, checkboxChange = 0;
2338 var select = jQuery("select[name='S1']");
2339 jQuery("#body").delegate("select[name='S1']", "change", function() {
2343 var checkbox = jQuery("#check2"),
2344 checkboxFunction = function(){
2347 jQuery("#body").delegate("#check2", "change", checkboxFunction);
2349 // test click on select
2351 // second click that changed it
2353 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2354 select.trigger("change");
2355 equal( selectChange, 1, "Change on click." );
2357 // test keys on select
2359 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2360 select.trigger("change");
2361 equal( selectChange, 1, "Change on keyup." );
2363 // test click on checkbox
2364 checkbox.trigger("change");
2365 equal( checkboxChange, 1, "Change on checkbox." );
2367 // test blur/focus on text
2368 var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
2369 jQuery("#body").delegate("#name", "change", function() {
2373 text.val(oldTextVal+"foo");
2374 text.trigger("change");
2375 equal( textChange, 1, "Change on text input." );
2377 text.val(oldTextVal);
2378 jQuery("#body").die("change");
2380 // test blur/focus on password
2381 var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
2382 jQuery("#body").delegate("#name", "change", function() {
2386 password.val(oldPasswordVal + "foo");
2387 password.trigger("change");
2388 equal( passwordChange, 1, "Change on password input." );
2390 password.val(oldPasswordVal);
2391 jQuery("#body").undelegate("#name", "change");
2393 // make sure die works
2397 jQuery("#body").undelegate("select[name='S1']", "change");
2398 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2399 select.trigger("change");
2400 equal( selectChange, 0, "Die on click works." );
2403 select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
2404 select.trigger("change");
2405 equal( selectChange, 0, "Die on keyup works." );
2407 // die specific checkbox
2408 jQuery("#body").undelegate("#check2", "change", checkboxFunction);
2409 checkbox.trigger("change");
2410 equal( checkboxChange, 1, "Die on checkbox." );
2413 test("delegate with submit", function() {
2416 var count1 = 0, count2 = 0;
2418 jQuery("#body").delegate("#testForm", "submit", function(ev) {
2420 ev.preventDefault();
2423 jQuery(document).delegate("body", "submit", function(ev) {
2425 ev.preventDefault();
2428 jQuery("#testForm input[name=sub1]").submit();
2429 equal( count1, 1, "Verify form submit." );
2430 equal( count2, 1, "Verify body submit." );
2432 jQuery("#body").undelegate();
2433 jQuery(document).undelegate();
2436 test("undelegate() with only namespaces", function() {
2439 var $delegate = jQuery("#liveHandlerOrder"),
2442 $delegate.delegate("a", "click.ns", function(e) {
2446 jQuery("a", $delegate).eq(0).trigger("click.ns");
2448 equal( count, 1, "delegated click.ns");
2450 $delegate.undelegate(".ns");
2452 jQuery("a", $delegate).eq(1).trigger("click.ns");
2454 equal( count, 1, "no more .ns after undelegate");
2457 test("Non DOM element events", function() {
2462 jQuery(o).bind("nonelementobj", function(e) {
2463 ok( true, "Event on non-DOM object triggered" );
2466 jQuery(o).trigger("nonelementobj");
2469 test("inline handler returning false stops default", function() {
2472 var markup = jQuery("<div><a href=\"#\" onclick=\"return false\">x</a></div>");
2473 markup.click(function(e) {
2474 ok( e.isDefaultPrevented(), "inline handler prevented default");
2477 markup.find("a").click();
2478 markup.off("click");
2481 test("window resize", function() {
2484 jQuery(window).unbind();
2486 jQuery(window).bind("resize", function(){
2487 ok( true, "Resize event fired." );
2488 }).resize().unbind("resize");
2490 ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." );
2493 test("focusin bubbles", function() {
2496 var input = jQuery( "<input type='text' />" ).prependTo( "body" ),
2499 // focus the element so DOM focus won't fire
2502 jQuery( "body" ).bind( "focusin.focusinBubblesTest", function(){
2503 equal( 1, order++, "focusin on the body second" );
2506 input.bind( "focusin.focusinBubblesTest", function(){
2507 equal( 0, order++, "focusin on the element first" );
2510 // Removed since DOM focus is unreliable on test swarm
2512 // input[0].focus();
2514 // To make the next focus test work, we need to take focus off the input.
2515 // This will fire another focusin event, so set order to reflect that.
2517 // jQuery("#text1")[0].focus();
2519 // jQuery trigger, which calls DOM focus
2521 input.trigger( "focus" );
2524 jQuery( "body" ).unbind( "focusin.focusinBubblesTest" );
2527 test("custom events with colons (#3533, #8272)", function() {
2530 var tab = jQuery("<table><tr><td>trigger</td></tr></table>").appendTo("body");
2532 tab.trigger("back:forth");
2533 ok( true, "colon events don't throw" );
2535 ok( false, "colon events die" );
2541 test(".on and .off", function() {
2545 var $onandoff = jQuery("<div id=\"onandoff\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>").appendTo("body");
2548 jQuery( "#onandoff" )
2549 .on( "whip", function() {
2550 ok( true, "whipped it good" );
2555 // Direct events only
2557 jQuery( "#onandoff b" )
2558 .on( "click", 5, function( e, trig ) {
2559 counter += e.data + (trig || 9); // twice, 5+9+5+17=36
2561 .one( "click", 7, function( e, trig ) {
2562 counter += e.data + (trig || 11); // once, 7+11=18
2565 .trigger( "click", 17 )
2567 equal( counter, 54, "direct event bindings with data" );
2569 // Delegated events only
2571 jQuery( "#onandoff" )
2572 .on( "click", "em", 5, function( e, trig ) {
2573 counter += e.data + (trig || 9); // twice, 5+9+5+17=36
2575 .one( "click", "em", 7, function( e, trig ) {
2576 counter += e.data + (trig || 11); // once, 7+11=18
2580 .trigger( "click", 17 )
2582 .off( "click", "em" );
2583 equal( counter, 54, "delegated event bindings with data" );
2586 // Mixed event bindings and types
2588 mixfn = function(e, trig) {
2589 counter += (e.data || 0) + (trig || 1);
2591 jQuery( "#onandoff" )
2592 .on( "click clack cluck", "em", 2, mixfn )
2593 .on( "cluck", "b", 7, mixfn )
2594 .on( "cluck", mixfn )
2597 equal( counter, 0, "nothing triggered yet" );
2600 .one( "cluck", 3, mixfn )
2601 .trigger( "cluck", 8 ) // 3+8 2+8 + 0+8 = 29
2603 .trigger( "cluck", 9 ) // 2+9 + 0+9 = 20
2606 equal( counter, 49, "after triggering em element" );
2608 .off( "cluck", function(){} ) // shouldn't remove anything
2609 .trigger( "cluck", 2 ) // 0+2 = 2
2611 equal( counter, 51, "after triggering #onandoff cluck" );
2614 .on( "click", 95, mixfn )
2615 .on( "clack", "p", 97, mixfn )
2616 .one( "cluck", 3, mixfn )
2617 .trigger( "quack", 19 ) // 0
2618 .off( "click clack cluck" )
2621 equal( counter, 51, "after triggering b" );
2623 .trigger( "cluck", 3 ) // 0+3 = 3
2624 .off( "clack", "em", mixfn )
2626 .trigger( "clack" ) // 0
2629 equal( counter, 54, "final triggers" );
2631 .off( "click cluck" );
2633 // We should have removed all the event handlers ... kinda hacky way to check this
2634 var data = jQuery.data[ jQuery( "#onandoff" )[0].expando ] || {};
2635 equal( data["events"], undefined, "no events left" );
2640 test("special bind/delegate name mapping", function() {
2643 jQuery.event.special["slap"] = {
2645 delegateType: "swing",
2646 handle: function( event ) {
2647 equal( event.handleObj.origType, "slap", "slapped your mammy, " + event.type );
2651 var comeback = function( event ) {
2652 ok( true, "event " + event.type + " triggered" );
2655 jQuery("<div><button id=\"mammy\">Are We Not Men?</button></div>")
2656 .on( "slap", "button", jQuery.noop )
2657 .on( "swing", "button", comeback )
2659 .on( "slap", jQuery.noop )
2660 .on( "click", comeback )
2661 .trigger( "click" ) // bindType-slap and click
2663 .trigger( "click" ) // click
2665 .trigger( "swing" ) // delegateType-slap and swing
2667 .off( "slap swing", "button" )
2668 .find( "button" ) // everything should be gone
2674 delete jQuery.event.special["slap"];
2676 jQuery.event.special["gutfeeling"] = {
2678 delegateType: "click",
2679 handle: function( event ) {
2680 equal( event.handleObj.origType, "gutfeeling", "got a gutfeeling" );
2681 // Need to call the handler since .one() uses it to unbind
2682 return event.handleObj.handler.call( this , event );
2686 // Ensure a special event isn't removed by its mapped type
2687 jQuery( "<p>Gut Feeling</p>" )
2688 .on( "click", jQuery.noop )
2689 .on( "gutfeeling", jQuery.noop )
2691 .trigger( "gutfeeling" )
2694 // Ensure special events are removed when only a namespace is provided
2695 jQuery( "<p>Gut Feeling</p>" )
2696 .on( "gutfeeling.Devo", jQuery.noop )
2698 .trigger( "gutfeeling" )
2701 // Ensure .one() events are removed after their maiden voyage
2702 jQuery( "<p>Gut Feeling</p>" )
2703 .one( "gutfeeling", jQuery.noop )
2704 .trigger( "gutfeeling" ) // This one should
2705 .trigger( "gutfeeling" ) // This one should not
2708 delete jQuery.event.special["gutfeeling"];
2711 test(".on and .off, selective mixed removal (#10705)", function() {
2715 timingx = function( e ) {
2716 ok( true, "triggered " + e.type );
2719 jQuery( "<p>Strange Pursuit</p>" )
2720 .on( "click", timingx )
2721 .on( "click.duty", timingx )
2722 .on( "click.now", timingx )
2723 .on( "devo", timingx )
2724 .on( "future", timingx )
2725 .trigger( "click" ) // 3
2726 .trigger( "devo" ) // 1
2727 .off( ".duty devo " ) // trailing space
2728 .trigger( "future" ) // 1
2729 .trigger( "click" ) // 2
2730 .off( "future click" )
2731 .trigger( "click" ); // 0
2734 test(".on( event-map, null-selector, data ) #11130", function() {
2738 var $p = jQuery("<p>Strange Pursuit</p>"),
2741 "foo": function( event ) {
2742 equal( event.data, "bar", "event.data correctly relayed with null selector" );
2747 $p.on( map, null, data ).trigger("foo");
2750 test("clone() delegated events (#11076)", function() {
2753 var counter = { "center": 0, "fold": 0, "centerfold": 0 },
2754 clicked = function( event ) {
2755 counter[ jQuery(this).text().replace(/\s+/, "") ]++;
2758 jQuery( "<table><tr><td>center</td><td>fold</td></tr></table>" )
2759 .on( "click", "tr", clicked )
2760 .on( "click", "td:first-child", clicked )
2761 .on( "click", "td:last-child", clicked ),
2762 clone = table.clone( true );
2764 clone.find("td").click();
2765 equal( counter["center"], 1, "first child" );
2766 equal( counter["fold"], 1, "last child" );
2767 equal( counter["centerfold"], 2, "all children" );
2773 test("fixHooks extensions", function() {
2776 // IE requires focusable elements to be visible, so append to body
2777 var $fixture = jQuery( "<input type='text' id='hook-fixture' />" ).appendTo( "body" ),
2778 saved = jQuery.event.fixHooks.click;
2780 // Ensure the property doesn't exist
2781 $fixture.bind( "click", function( event ) {
2782 ok( !("blurrinessLevel" in event), "event.blurrinessLevel does not exist" );
2784 fireNative( $fixture[0], "click" );
2785 $fixture.unbind( "click" );
2787 jQuery.event.fixHooks.click = {
2788 filter: function( event, originalEvent ) {
2789 event.blurrinessLevel = 42;
2794 // Trigger a native click and ensure the property is set
2795 $fixture.bind( "click", function( event ) {
2796 equal( event.blurrinessLevel, 42, "event.blurrinessLevel was set" );
2798 fireNative( $fixture[0], "click" );
2800 delete jQuery.event.fixHooks.click;
2801 $fixture.unbind( "click" ).remove();
2802 jQuery.event.fixHooks.click = saved;
2805 testIframeWithCallback( "jQuery.ready promise", "event/promiseReady.html", function( isOk ) {
2807 ok( isOk, "$.when( $.ready ) works" );
2810 // need PHP here to make the incepted IFRAME hang
2812 testIframeWithCallback( "jQuery.ready synchronous load with long loading subresources", "event/syncReady.html", function( isOk ) {
2814 ok( isOk, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
2819 // This code must be run before DOM ready!
2820 var notYetReady, noEarlyExecution,
2824 notYetReady = !jQuery.isReady;
2826 test("jQuery.isReady", function() {
2829 equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready");
2830 equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready");
2833 // Create an event handler.
2834 function makeHandler( testId ) {
2835 // When returned function is executed, push testId onto `order` array
2836 // to ensure execution order. Also, store event handler arg to ensure
2837 // the correct arg is being passed into the event handler.
2838 return function( arg ) {
2844 // Bind to the ready event in every possible way.
2845 jQuery(makeHandler("a"));
2846 jQuery(document).ready(makeHandler("b"));
2847 jQuery(document).bind("ready.readytest", makeHandler("c"));
2849 // Do it twice, just to be sure.
2850 jQuery(makeHandler("d"));
2851 jQuery(document).ready(makeHandler("e"));
2852 jQuery(document).bind("ready.readytest", makeHandler("f"));
2854 noEarlyExecution = order.length === 0;
2856 // This assumes that QUnit tests are run on DOM ready!
2857 test("jQuery ready", function() {
2860 ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready");
2862 // Ensure execution order.
2863 deepEqual(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in bind-order, but those bound with jQuery(document).bind( 'ready', fn ) will always execute last");
2865 // Ensure handler argument is correct.
2866 equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
2867 equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
2868 ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).bind( 'ready', fn ) should be an event object");
2872 // Now that the ready event has fired, again bind to the ready event
2873 // in every possible way. These event handlers should execute immediately.
2874 jQuery(makeHandler("g"));
2875 equal(order.pop(), "g", "Event handler should execute immediately");
2876 equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
2878 jQuery(document).ready(makeHandler("h"));
2879 equal(order.pop(), "h", "Event handler should execute immediately");
2880 equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
2882 jQuery(document).bind("ready.readytest", makeHandler("never"));
2883 equal(order.length, 0, "Event handler should never execute since DOM ready has already passed");
2886 jQuery(document).unbind("ready.readytest");
2891 test("change handler should be detached from element", function() {
2894 var $fixture = jQuery( "<input type='text' id='change-ie-leak' />" ).appendTo( "body" );
2896 var originRemoveEvent = jQuery.removeEvent;
2898 var wrapperRemoveEvent = function(elem, type, handle){
2899 equal("change", type, "Event handler for 'change' event should be removed");
2900 equal("change-ie-leak", jQuery(elem).attr("id"), "Event handler for 'change' event should be removed from appropriate element");
2901 originRemoveEvent(elem, type, handle);
2904 jQuery.removeEvent = wrapperRemoveEvent ;
2906 $fixture.bind( "change", function( event ) {});
2907 $fixture.unbind( "change" );
2911 jQuery.removeEvent = originRemoveEvent;
2914 asyncTest("trigger click on checkbox, fires change event", function() {
2917 var check = jQuery("#check2");
2919 check.on( "change", function() {
2921 check.off("change");
2922 ok( true, "Change event fired as a result of triggered click" );
2924 }).trigger("click");