event.js 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690
  1. module("event", { teardown: moduleTeardown });
  2. test("null or undefined handler", function() {
  3. expect(2);
  4. // Supports Fixes bug #7229
  5. try {
  6. jQuery("#firstp").on( "click", null );
  7. ok(true, "Passing a null handler will not throw an exception");
  8. } catch (e) {}
  9. try {
  10. jQuery("#firstp").on( "click", undefined );
  11. ok(true, "Passing an undefined handler will not throw an exception");
  12. } catch (e) {}
  13. });
  14. test("bind(),on(),delegate() with non-null,defined data", function() {
  15. expect(3);
  16. var handler = function( event, data ) {
  17. equal( data, 0, "non-null, defined data (zero) is correctly passed" );
  18. };
  19. jQuery("#foo").bind("foo.bind", handler);
  20. jQuery("#foo").on("foo.on", handler);
  21. jQuery("div").delegate("#foo", "foo.delegate", handler);
  22. jQuery("#foo").trigger("foo", 0);
  23. jQuery("#foo").unbind("foo.bind", handler);
  24. jQuery("#foo").off("foo.on", handler);
  25. jQuery("div").undelegate("#foo", "foo.delegate");
  26. });
  27. test("Handler changes and .trigger() order", function() {
  28. expect(1);
  29. var markup = jQuery(
  30. "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
  31. ),
  32. path = "";
  33. markup
  34. .find( "*" ).andSelf().on( "click", function( e ) {
  35. path += this.nodeName.toLowerCase() + " ";
  36. })
  37. .filter( "b" ).on( "click", function( e ) {
  38. // Removing span should not stop propagation to original parents
  39. if ( e.target === this ) {
  40. jQuery(this).parent().remove();
  41. }
  42. });
  43. markup.find( "b" ).trigger( "click" );
  44. equal( path, "b p div div ", "Delivered all events" );
  45. markup.remove();
  46. });
  47. test("bind(), with data", function() {
  48. expect(4);
  49. var handler = function(event) {
  50. ok( event.data, "bind() with data, check passed data exists" );
  51. equal( event.data["foo"], "bar", "bind() with data, Check value of passed data" );
  52. };
  53. jQuery("#firstp").bind("click", {"foo": "bar"}, handler).trigger("click").unbind("click", handler);
  54. ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
  55. var test = function(){};
  56. var handler2 = function(event) {
  57. equal( event.data, test, "bind() with function data, Check value of passed data" );
  58. };
  59. jQuery("#firstp").bind("click", test, handler2).trigger("click").unbind("click", handler2);
  60. });
  61. test("click(), with data", function() {
  62. expect(3);
  63. var handler = function(event) {
  64. ok( event.data, "bind() with data, check passed data exists" );
  65. equal( event.data["foo"], "bar", "bind() with data, Check value of passed data" );
  66. };
  67. jQuery("#firstp").on( "click", {"foo": "bar"}, handler).trigger("click").unbind("click", handler);
  68. ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
  69. });
  70. test("bind(), with data, trigger with data", function() {
  71. expect(4);
  72. var handler = function(event, data) {
  73. ok( event.data, "check passed data exists" );
  74. equal( event.data.foo, "bar", "Check value of passed data" );
  75. ok( data, "Check trigger data" );
  76. equal( data.bar, "foo", "Check value of trigger data" );
  77. };
  78. jQuery("#firstp").bind("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]).unbind("click", handler);
  79. });
  80. test("bind(), multiple events at once", function() {
  81. expect(2);
  82. var clickCounter = 0,
  83. mouseoverCounter = 0;
  84. var handler = function(event) {
  85. if (event.type == "click") {
  86. clickCounter += 1;
  87. }
  88. else if (event.type == "mouseover") {
  89. mouseoverCounter += 1;
  90. }
  91. };
  92. jQuery("#firstp").bind("click mouseover", handler).trigger("click").trigger("mouseover");
  93. equal( clickCounter, 1, "bind() with multiple events at once" );
  94. equal( mouseoverCounter, 1, "bind() with multiple events at once" );
  95. });
  96. test("bind(), five events at once", function() {
  97. expect(1);
  98. var count = 0,
  99. handler = function(event) {
  100. count++;
  101. };
  102. jQuery("#firstp").bind("click mouseover foo bar baz", handler)
  103. .trigger("click").trigger("mouseover")
  104. .trigger("foo").trigger("bar")
  105. .trigger("baz");
  106. equal( count, 5, "bind() five events at once" );
  107. });
  108. test("bind(), multiple events at once and namespaces", function() {
  109. expect(7);
  110. var cur, obj = {};
  111. var div = jQuery("<div/>").bind("focusin.a", function(e) {
  112. equal( e.type, cur, "Verify right single event was fired." );
  113. });
  114. cur = "focusin";
  115. div.trigger("focusin.a");
  116. // manually clean up detached elements
  117. div.remove();
  118. div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
  119. equal( e.type, cur, "Verify right multi event was fired." );
  120. equal( e.data, obj, "Make sure the data came in correctly." );
  121. });
  122. cur = "click";
  123. div.trigger("click");
  124. cur = "mouseover";
  125. div.trigger("mouseover");
  126. // manually clean up detached elements
  127. div.remove();
  128. div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
  129. equal( e.type, cur, "Verify right multi event was fired." );
  130. });
  131. cur = "focusin";
  132. div.trigger("focusin.a");
  133. cur = "focusout";
  134. div.trigger("focusout.b");
  135. // manually clean up detached elements
  136. div.remove();
  137. });
  138. test("bind(), namespace with special add", function() {
  139. expect(27);
  140. var div = jQuery("<div/>").bind("test", function(e) {
  141. ok( true, "Test event fired." );
  142. });
  143. var i = 0;
  144. jQuery.event.special["test"] = {
  145. _default: function(e, data) {
  146. equal( this, document, "Make sure we're at the top of the chain." );
  147. equal( e.type, "test", "And that we're still dealing with a test event." );
  148. equal( e.target, div[0], "And that the target is correct." );
  149. ok( data !== undefined , "And that trigger data was passed." );
  150. },
  151. setup: function(){},
  152. teardown: function(){
  153. ok(true, "Teardown called.");
  154. },
  155. add: function( handleObj ) {
  156. var handler = handleObj.handler;
  157. handleObj.handler = function(e) {
  158. e.xyz = ++i;
  159. handler.apply( this, arguments );
  160. };
  161. },
  162. remove: function() {
  163. ok(true, "Remove called.");
  164. }
  165. };
  166. div.bind("test.a", {"x": 1}, function(e) {
  167. ok( !!e.xyz, "Make sure that the data is getting passed through." );
  168. equal( e.data["x"], 1, "Make sure data is attached properly." );
  169. });
  170. div.bind("test.b", {"x": 2}, function(e) {
  171. ok( !!e.xyz, "Make sure that the data is getting passed through." );
  172. equal( e.data["x"], 2, "Make sure data is attached properly." );
  173. });
  174. // Should trigger 5
  175. div.trigger("test", 33.33);
  176. // Should trigger 2
  177. div.trigger("test.a", "George Harrison");
  178. // Should trigger 2
  179. div.trigger("test.b", { year: 1982 });
  180. // Should trigger 4
  181. div.unbind("test");
  182. div = jQuery("<div/>").bind("test", function(e) {
  183. ok( true, "Test event fired." );
  184. });
  185. // Should trigger 2
  186. div.appendTo("#qunit-fixture").remove();
  187. delete jQuery.event.special["test"];
  188. });
  189. test("bind(), no data", function() {
  190. expect(1);
  191. var handler = function(event) {
  192. ok ( !event.data, "Check that no data is added to the event object" );
  193. };
  194. jQuery("#firstp").bind("click", handler).trigger("click");
  195. });
  196. test("bind/one/unbind(Object)", function(){
  197. expect(6);
  198. var clickCounter = 0, mouseoverCounter = 0;
  199. function handler(event) {
  200. if (event.type == "click") {
  201. clickCounter++;
  202. }
  203. else if (event.type == "mouseover") {
  204. mouseoverCounter++;
  205. }
  206. }
  207. function handlerWithData(event) {
  208. if (event.type == "click") {
  209. clickCounter += event.data;
  210. }
  211. else if (event.type == "mouseover") {
  212. mouseoverCounter += event.data;
  213. }
  214. }
  215. function trigger(){
  216. $elem.trigger("click").trigger("mouseover");
  217. }
  218. var $elem = jQuery("#firstp")
  219. // Regular bind
  220. .bind({
  221. "click":handler,
  222. "mouseover":handler
  223. })
  224. // Bind with data
  225. .one({
  226. "click":handlerWithData,
  227. "mouseover":handlerWithData
  228. }, 2 );
  229. trigger();
  230. equal( clickCounter, 3, "bind(Object)" );
  231. equal( mouseoverCounter, 3, "bind(Object)" );
  232. trigger();
  233. equal( clickCounter, 4, "bind(Object)" );
  234. equal( mouseoverCounter, 4, "bind(Object)" );
  235. jQuery("#firstp").unbind({
  236. "click":handler,
  237. "mouseover":handler
  238. });
  239. trigger();
  240. equal( clickCounter, 4, "bind(Object)" );
  241. equal( mouseoverCounter, 4, "bind(Object)" );
  242. });
  243. test("on/off(Object), delegate/undelegate(String, Object)", function() {
  244. expect(6);
  245. var clickCounter = 0, mouseoverCounter = 0,
  246. $p = jQuery("#firstp"), $a = $p.find("a:first");
  247. var events = {
  248. "click": function( event ) {
  249. clickCounter += ( event.data || 1 );
  250. },
  251. "mouseover": function( event ) {
  252. mouseoverCounter += ( event.data || 1 );
  253. }
  254. };
  255. function trigger() {
  256. $a.trigger("click").trigger("mouseover");
  257. }
  258. jQuery( document ).on( events, "#firstp a:first" );
  259. $p.delegate( "a", events, 2 );
  260. trigger();
  261. equal( clickCounter, 3, "on/delegate" );
  262. equal( mouseoverCounter, 3, "on/delegate" );
  263. $p.undelegate( "a", events );
  264. trigger();
  265. equal( clickCounter, 4, "undelegate" );
  266. equal( mouseoverCounter, 4, "undelegate" );
  267. jQuery( document ).off( events, "#firstp a:first" );
  268. trigger();
  269. equal( clickCounter, 4, "off" );
  270. equal( mouseoverCounter, 4, "off" );
  271. });
  272. test("on/delegate immediate propagation", function() {
  273. expect(2);
  274. var $p = jQuery("#firstp"), $a = $p.find("a:first"), lastClick;
  275. lastClick = "";
  276. jQuery( document ).on( "click", "#firstp a:first", function(e) {
  277. lastClick = "click1";
  278. e.stopImmediatePropagation();
  279. });
  280. jQuery( document ).on( "click", "#firstp a:first", function(e) {
  281. lastClick = "click2";
  282. });
  283. $a.trigger( "click" );
  284. equal( lastClick, "click1", "on stopImmediatePropagation" );
  285. jQuery( document ).off( "click", "#firstp a:first" );
  286. lastClick = "";
  287. $p.delegate( "a", "click", function(e) {
  288. lastClick = "click1";
  289. e.stopImmediatePropagation();
  290. });
  291. $p.delegate( "a", "click", function(e) {
  292. lastClick = "click2";
  293. });
  294. $a.trigger( "click" );
  295. equal( lastClick, "click1", "delegate stopImmediatePropagation" );
  296. $p.undelegate( "click" );
  297. });
  298. test("bind/delegate bubbling, isDefaultPrevented", function() {
  299. expect(2);
  300. var $anchor2 = jQuery( "#anchor2" ),
  301. $main = jQuery( "#qunit-fixture" ),
  302. fakeClick = function($jq) {
  303. // Use a native click so we don't get jQuery simulated bubbling
  304. if ( document.createEvent ) {
  305. var e = document.createEvent( "MouseEvents" );
  306. e.initEvent( "click", true, true );
  307. $jq[0].dispatchEvent(e);
  308. }
  309. else if ( $jq[0].click ) {
  310. $jq[0].click(); // IE
  311. }
  312. };
  313. $anchor2.on( "click", function(e) {
  314. e.preventDefault();
  315. });
  316. $main.delegate("#foo", "click", function(e) {
  317. var orig = e.originalEvent;
  318. if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig["getPreventDefault"] ) {
  319. equal( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
  320. } else {
  321. // Opera < 11 doesn't implement any interface we can use, so give it a pass
  322. ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
  323. }
  324. });
  325. fakeClick( $anchor2 );
  326. $anchor2.unbind( "click" );
  327. $main.undelegate( "click" );
  328. $anchor2.on( "click", function(e) {
  329. // Let the default action occur
  330. });
  331. $main.delegate("#foo", "click", function(e) {
  332. equal( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
  333. });
  334. fakeClick( $anchor2 );
  335. $anchor2.unbind( "click" );
  336. $main.undelegate( "click" );
  337. });
  338. test("bind(), iframes", function() {
  339. expect( 1 );
  340. // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
  341. var doc = jQuery("#loadediframe").contents();
  342. jQuery("div", doc).bind("click", function() {
  343. ok( true, "Binding to element inside iframe" );
  344. }).trigger("click").unbind("click");
  345. });
  346. test("bind(), trigger change on select", function() {
  347. expect(5);
  348. var counter = 0;
  349. function selectOnChange(event) {
  350. equal( event.data, counter++, "Event.data is not a global event object" );
  351. }
  352. jQuery("#form select").each(function(i){
  353. jQuery(this).bind("change", i, selectOnChange);
  354. }).trigger("change");
  355. });
  356. test("bind(), namespaced events, cloned events", 18, function() {
  357. var firstp = jQuery( "#firstp" );
  358. firstp.bind("custom.test",function(e){
  359. ok(false, "Custom event triggered");
  360. });
  361. firstp.bind("click",function(e){
  362. ok(true, "Normal click triggered");
  363. equal( e.type + e.namespace, "click", "Check that only click events trigger this fn" );
  364. });
  365. firstp.bind("click.test",function(e){
  366. var check = "click";
  367. ok( true, "Namespaced click triggered" );
  368. if ( e.namespace ) {
  369. check += "test";
  370. }
  371. equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
  372. });
  373. //clone(true) element to verify events are cloned correctly
  374. firstp = firstp.add( firstp.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp ) );
  375. // Trigger both bound fn (8)
  376. firstp.trigger("click");
  377. // Trigger one bound fn (4)
  378. firstp.trigger("click.test");
  379. // Remove only the one fn
  380. firstp.unbind("click.test");
  381. // Trigger the remaining fn (4)
  382. firstp.trigger("click");
  383. // Remove the remaining namespaced fn
  384. firstp.unbind(".test");
  385. // Try triggering the custom event (0)
  386. firstp.trigger("custom");
  387. // using contents will get comments regular, text, and comment nodes
  388. jQuery("#nonnodes").contents().bind("tester", function () {
  389. equal(this.nodeType, 1, "Check node,textnode,comment bind just does real nodes" );
  390. }).trigger("tester");
  391. // Make sure events stick with appendTo'd elements (which are cloned) #2027
  392. jQuery("<a href='#fail' class='test'>test</a>").on( "click", function(){ return false; }).appendTo("#qunit-fixture");
  393. ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" );
  394. });
  395. test("bind(), multi-namespaced events", function() {
  396. expect(6);
  397. var order = [
  398. "click.test.abc",
  399. "click.test.abc",
  400. "click.test",
  401. "click.test.abc",
  402. "click.test",
  403. "custom.test2"
  404. ];
  405. function check(name, msg){
  406. deepEqual(name, order.shift(), msg);
  407. }
  408. jQuery("#firstp").bind("custom.test",function(e){
  409. check("custom.test", "Custom event triggered");
  410. });
  411. jQuery("#firstp").bind("custom.test2",function(e){
  412. check("custom.test2", "Custom event triggered");
  413. });
  414. jQuery("#firstp").bind("click.test",function(e){
  415. check("click.test", "Normal click triggered");
  416. });
  417. jQuery("#firstp").bind("click.test.abc",function(e){
  418. check("click.test.abc", "Namespaced click triggered");
  419. });
  420. // Those would not trigger/unbind (#5303)
  421. jQuery("#firstp").trigger("click.a.test");
  422. jQuery("#firstp").unbind("click.a.test");
  423. // Trigger both bound fn (1)
  424. jQuery("#firstp").trigger("click.test.abc");
  425. // Trigger one bound fn (1)
  426. jQuery("#firstp").trigger("click.abc");
  427. // Trigger two bound fn (2)
  428. jQuery("#firstp").trigger("click.test");
  429. // Remove only the one fn
  430. jQuery("#firstp").unbind("click.abc");
  431. // Trigger the remaining fn (1)
  432. jQuery("#firstp").trigger("click");
  433. // Remove the remaining fn
  434. jQuery("#firstp").unbind(".test");
  435. // Trigger the remaining fn (1)
  436. jQuery("#firstp").trigger("custom");
  437. });
  438. test("bind(), with same function", function() {
  439. expect(2);
  440. var count = 0, func = function(){
  441. count++;
  442. };
  443. jQuery("#liveHandlerOrder").bind("foo.bar", func).bind("foo.zar", func);
  444. jQuery("#liveHandlerOrder").trigger("foo.bar");
  445. equal(count, 1, "Verify binding function with multiple namespaces." );
  446. jQuery("#liveHandlerOrder").unbind("foo.bar", func).unbind("foo.zar", func);
  447. jQuery("#liveHandlerOrder").trigger("foo.bar");
  448. equal(count, 1, "Verify that removing events still work." );
  449. });
  450. test("bind(), make sure order is maintained", function() {
  451. expect(1);
  452. var elem = jQuery("#firstp"), log = [], check = [];
  453. jQuery.each( new Array(100), function( i ) {
  454. elem.bind( "click", function(){
  455. log.push( i );
  456. });
  457. check.push( i );
  458. });
  459. elem.trigger("click");
  460. equal( log.join(","), check.join(","), "Make sure order was maintained." );
  461. elem.unbind("click");
  462. });
  463. test("bind(), with different this object", function() {
  464. expect(4);
  465. var thisObject = { myThis: true },
  466. data = { myData: true },
  467. handler1 = function( event ) {
  468. equal( this, thisObject, "bind() with different this object" );
  469. },
  470. handler2 = function( event ) {
  471. equal( this, thisObject, "bind() with different this object and data" );
  472. equal( event.data, data, "bind() with different this object and data" );
  473. };
  474. jQuery("#firstp")
  475. .bind("click", jQuery.proxy(handler1, thisObject)).trigger("click").unbind("click", handler1)
  476. .bind("click", data, jQuery.proxy(handler2, thisObject)).trigger("click").unbind("click", handler2);
  477. ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
  478. });
  479. test("bind(name, false), unbind(name, false)", function() {
  480. expect(3);
  481. var main = 0;
  482. jQuery("#qunit-fixture").bind("click", function(e){ main++; });
  483. jQuery("#ap").trigger("click");
  484. equal( main, 1, "Verify that the trigger happened correctly." );
  485. main = 0;
  486. jQuery("#ap").bind("click", false);
  487. jQuery("#ap").trigger("click");
  488. equal( main, 0, "Verify that no bubble happened." );
  489. main = 0;
  490. jQuery("#ap").unbind("click", false);
  491. jQuery("#ap").trigger("click");
  492. equal( main, 1, "Verify that the trigger happened correctly." );
  493. // manually clean up events from elements outside the fixture
  494. jQuery("#qunit-fixture").unbind("click");
  495. });
  496. test("delegate(selector, name, false), undelegate(selector, name, false)", function() {
  497. expect(3);
  498. var main = 0;
  499. jQuery("#qunit-fixture").delegate("#ap", "click", function(e){ main++; });
  500. jQuery("#ap").trigger("click");
  501. equal( main, 1, "Verify that the trigger happened correctly." );
  502. main = 0;
  503. jQuery("#ap").delegate("#groups", "click", false);
  504. jQuery("#groups").trigger("click");
  505. equal( main, 0, "Verify that no bubble happened." );
  506. main = 0;
  507. jQuery("#ap").undelegate("#groups", "click", false);
  508. jQuery("#groups").trigger("click");
  509. equal( main, 1, "Verify that the trigger happened correctly." );
  510. jQuery("#qunit-fixture").undelegate("#ap", "click");
  511. });
  512. test("bind()/trigger()/unbind() on plain object", function() {
  513. expect( 7 );
  514. var obj = {};
  515. // Make sure it doesn't complain when no events are found
  516. jQuery(obj).trigger("test");
  517. // Make sure it doesn't complain when no events are found
  518. jQuery(obj).unbind("test");
  519. jQuery(obj).bind({
  520. "test": function() {
  521. ok( true, "Custom event run." );
  522. },
  523. "submit": function() {
  524. ok( true, "Custom submit event run." );
  525. }
  526. });
  527. var events = jQuery._data(obj, "events");
  528. ok( events, "Object has events bound." );
  529. equal( obj["events"], undefined, "Events object on plain objects is not events" );
  530. equal( obj["test"], undefined, "Make sure that test event is not on the plain object." );
  531. equal( obj["handle"], undefined, "Make sure that the event handler is not on the plain object." );
  532. // Should trigger 1
  533. jQuery(obj).trigger("test");
  534. jQuery(obj).trigger("submit");
  535. jQuery(obj).unbind("test");
  536. jQuery(obj).unbind("submit");
  537. // Should trigger 0
  538. jQuery(obj).trigger("test");
  539. // Make sure it doesn't complain when no events are found
  540. jQuery(obj).unbind("test");
  541. equal( obj && obj[ jQuery.expando ] &&
  542. obj[ jQuery.expando ][ jQuery.expando ] &&
  543. obj[ jQuery.expando ][ jQuery.expando ]["events"], undefined, "Make sure events object is removed" );
  544. });
  545. test("unbind(type)", function() {
  546. expect( 1 );
  547. var $elem = jQuery("#firstp"),
  548. message;
  549. function error(){
  550. ok( false, message );
  551. }
  552. message = "unbind passing function";
  553. $elem.bind("error1", error).unbind("error1", error).triggerHandler("error1");
  554. message = "unbind all from event";
  555. $elem.bind("error1", error).unbind("error1").triggerHandler("error1");
  556. message = "unbind all";
  557. $elem.bind("error1", error).unbind().triggerHandler("error1");
  558. message = "unbind many with function";
  559. $elem.bind("error1 error2",error)
  560. .unbind("error1 error2", error )
  561. .trigger("error1").triggerHandler("error2");
  562. message = "unbind many"; // #3538
  563. $elem.bind("error1 error2", error)
  564. .unbind("error1 error2")
  565. .trigger("error1").triggerHandler("error2");
  566. message = "unbind without a type or handler";
  567. $elem.bind("error1 error2.test",error)
  568. .unbind()
  569. .trigger("error1").triggerHandler("error2");
  570. // Should only unbind the specified function
  571. jQuery( document ).bind( "click", function(){
  572. ok( true, "called handler after selective removal");
  573. });
  574. var func = function(){ };
  575. jQuery( document )
  576. .bind( "click", func )
  577. .unbind( "click", func )
  578. .trigger("click")
  579. .unbind( "click" );
  580. });
  581. test("unbind(eventObject)", function() {
  582. expect(4);
  583. var $elem = jQuery("#firstp"),
  584. num;
  585. function assert( expected ){
  586. num = 0;
  587. $elem.trigger("foo").triggerHandler("bar");
  588. equal( num, expected, "Check the right handlers are triggered" );
  589. }
  590. $elem
  591. // This handler shouldn't be unbound
  592. .bind("foo", function(){
  593. num += 1;
  594. })
  595. .bind("foo", function(e){
  596. $elem.unbind( e );
  597. num += 2;
  598. })
  599. // Neither this one
  600. .bind("bar", function(){
  601. num += 4;
  602. });
  603. assert( 7 );
  604. assert( 5 );
  605. $elem.unbind("bar");
  606. assert( 1 );
  607. $elem.unbind();
  608. assert( 0 );
  609. });
  610. if ( jQuery.fn.hover ) {
  611. test("hover() mouseenter mouseleave", function() {
  612. expect(1);
  613. var times = 0,
  614. handler1 = function( event ) { ++times; },
  615. handler2 = function( event ) { ++times; };
  616. jQuery("#firstp")
  617. .hover(handler1, handler2)
  618. .mouseenter().mouseleave()
  619. .unbind("mouseenter", handler1)
  620. .unbind("mouseleave", handler2)
  621. .hover(handler1)
  622. .mouseenter().mouseleave()
  623. .unbind("mouseenter mouseleave", handler1)
  624. .mouseenter().mouseleave();
  625. equal( times, 4, "hover handlers fired" );
  626. });
  627. }
  628. test("mouseover triggers mouseenter", function() {
  629. expect(1);
  630. var count = 0,
  631. elem = jQuery("<a />");
  632. elem.on( "mouseenter", function () {
  633. count++;
  634. });
  635. elem.trigger("mouseover");
  636. equal(count, 1, "make sure mouseover triggers a mouseenter" );
  637. elem.remove();
  638. });
  639. test("withinElement implemented with jQuery.contains()", function() {
  640. expect(1);
  641. jQuery("#qunit-fixture").append("<div id='jc-outer'><div id='jc-inner'></div></div>");
  642. jQuery("#jc-outer").bind("mouseenter mouseleave", function( event ) {
  643. equal( this.id, "jc-outer", this.id + " " + event.type );
  644. }).trigger("mouseenter");
  645. jQuery("#jc-inner").trigger("mousenter");
  646. jQuery("#jc-outer").unbind("mouseenter mouseleave").remove();
  647. jQuery("#jc-inner").remove();
  648. });
  649. test("mouseenter, mouseleave don't catch exceptions", function() {
  650. expect(2);
  651. var elem = jQuery("#firstp").on( "mouseenter mouseleave", function() {
  652. throw "an Exception";
  653. });
  654. try {
  655. elem.trigger("mouseenter");
  656. } catch (e) {
  657. equal( e, "an Exception", "mouseenter doesn't catch exceptions" );
  658. }
  659. try {
  660. elem.trigger("mouseleave");
  661. } catch (e) {
  662. equal( e, "an Exception", "mouseleave doesn't catch exceptions" );
  663. }
  664. });
  665. if ( jQuery.fn.click ) {
  666. test("trigger() shortcuts", function() {
  667. expect(6);
  668. var elem = jQuery("<li><a href='#'>Change location</a></li>").prependTo("#firstUL");
  669. elem.find("a").bind("click", function() {
  670. var close = jQuery("spanx", this); // same with jQuery(this).find("span");
  671. equal( close.length, 0, "Context element does not exist, length must be zero" );
  672. ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
  673. return false;
  674. }).click();
  675. // manually clean up detached elements
  676. elem.remove();
  677. jQuery("#check1").click(function() {
  678. ok( true, "click event handler for checkbox gets fired twice, see #815" );
  679. }).click();
  680. var counter = 0;
  681. jQuery("#firstp")[0].onclick = function(event) {
  682. counter++;
  683. };
  684. jQuery("#firstp").click();
  685. equal( counter, 1, "Check that click, triggers onclick event handler also" );
  686. var clickCounter = 0;
  687. jQuery("#simon1")[0].onclick = function(event) {
  688. clickCounter++;
  689. };
  690. jQuery("#simon1").click();
  691. equal( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
  692. elem = jQuery("<img />").load(function(){
  693. ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
  694. }).load();
  695. // manually clean up detached elements
  696. elem.remove();
  697. // test that special handlers do not blow up with VML elements (#7071)
  698. jQuery("<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />").appendTo("head");
  699. jQuery("<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>").appendTo("#form");
  700. jQuery("#oval").click().keydown();
  701. });
  702. }
  703. test("trigger() bubbling", function() {
  704. expect(18);
  705. var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
  706. jQuery(window).bind("click", function(e){ win++; });
  707. jQuery(document).bind("click", function(e){ if ( e.target !== document) { doc++; } });
  708. jQuery("html").bind("click", function(e){ html++; });
  709. jQuery("body").bind("click", function(e){ body++; });
  710. jQuery("#qunit-fixture").bind("click", function(e){ main++; });
  711. jQuery("#ap").bind("click", function(){ ap++; return false; });
  712. jQuery("html").trigger("click");
  713. equal( win, 1, "HTML bubble" );
  714. equal( doc, 1, "HTML bubble" );
  715. equal( html, 1, "HTML bubble" );
  716. jQuery("body").trigger("click");
  717. equal( win, 2, "Body bubble" );
  718. equal( doc, 2, "Body bubble" );
  719. equal( html, 2, "Body bubble" );
  720. equal( body, 1, "Body bubble" );
  721. jQuery("#qunit-fixture").trigger("click");
  722. equal( win, 3, "Main bubble" );
  723. equal( doc, 3, "Main bubble" );
  724. equal( html, 3, "Main bubble" );
  725. equal( body, 2, "Main bubble" );
  726. equal( main, 1, "Main bubble" );
  727. jQuery("#ap").trigger("click");
  728. equal( doc, 3, "ap bubble" );
  729. equal( html, 3, "ap bubble" );
  730. equal( body, 2, "ap bubble" );
  731. equal( main, 1, "ap bubble" );
  732. equal( ap, 1, "ap bubble" );
  733. jQuery( document ).trigger("click");
  734. equal( win, 4, "doc bubble" );
  735. // manually clean up events from elements outside the fixture
  736. jQuery(document).unbind("click");
  737. jQuery("html, body, #qunit-fixture").unbind("click");
  738. });
  739. test("trigger(type, [data], [fn])", function() {
  740. expect(16);
  741. var handler = function(event, a, b, c) {
  742. equal( event.type, "click", "check passed data" );
  743. equal( a, 1, "check passed data" );
  744. equal( b, "2", "check passed data" );
  745. equal( c, "abc", "check passed data" );
  746. return "test";
  747. };
  748. var $elem = jQuery("#firstp");
  749. // Simulate a "native" click
  750. $elem[0].click = function(){
  751. ok( true, "Native call was triggered" );
  752. };
  753. jQuery( document ).on("mouseenter", "#firstp", function(){
  754. ok( true, "Trigger mouseenter bound by on" );
  755. });
  756. jQuery( document ).on("mouseleave", "#firstp", function(){
  757. ok( true, "Trigger mouseleave bound by on" );
  758. });
  759. $elem.trigger("mouseenter");
  760. $elem.trigger("mouseleave");
  761. jQuery( document ).off( "mouseenter mouseleave", "#firstp");
  762. // Triggers handlrs and native
  763. // Trigger 5
  764. $elem.bind("click", handler).trigger("click", [1, "2", "abc"]);
  765. // Simulate a "native" click
  766. $elem[0].click = function(){
  767. ok( false, "Native call was triggered" );
  768. };
  769. // Trigger only the handlers (no native)
  770. // Triggers 5
  771. equal( $elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
  772. var pass = true, elem2;
  773. try {
  774. elem2 = jQuery("#form input:first");
  775. elem2.get(0).style.display = "none";
  776. elem2.trigger("focus");
  777. } catch(e) {
  778. pass = false;
  779. }
  780. ok( pass, "Trigger focus on hidden element" );
  781. pass = true;
  782. try {
  783. jQuery("#qunit-fixture table:first").bind("test:test", function(){}).trigger("test:test");
  784. } catch (e) {
  785. pass = false;
  786. }
  787. ok( pass, "Trigger on a table with a colon in the even type, see #3533" );
  788. var form = jQuery("<form action=''></form>").appendTo("body");
  789. // Make sure it can be prevented locally
  790. form.on( "submit", function(){
  791. ok( true, "Local bind still works." );
  792. return false;
  793. });
  794. // Trigger 1
  795. form.trigger("submit");
  796. form.unbind("submit");
  797. jQuery(document).on( "submit", function(){
  798. ok( true, "Make sure bubble works up to document." );
  799. return false;
  800. });
  801. // Trigger 1
  802. form.trigger("submit");
  803. jQuery(document).unbind("submit");
  804. form.remove();
  805. });
  806. test( "submit event bubbles on copied forms (#11649)", function() {
  807. expect( 3 );
  808. var $formByClone, $formByHTML,
  809. $testForm = jQuery("#testForm"),
  810. $fixture = jQuery("#qunit-fixture"),
  811. $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
  812. function noSubmit( e ) {
  813. e.preventDefault();
  814. }
  815. function delegatedSubmit() {
  816. ok( true, "Make sure submit event bubbles up." );
  817. return false;
  818. }
  819. // Attach a delegated submit handler to the parent element
  820. $fixture.on( "submit", "form", delegatedSubmit );
  821. // Trigger form submission to introduce the _submit_attached property
  822. $testForm.on( "submit", noSubmit ).find("input[name=sub1]").trigger("click");
  823. // Copy the form via .clone() and .html()
  824. $formByClone = $testForm.clone( true, true ).removeAttr("id");
  825. $formByHTML = jQuery( jQuery.parseHTML($fixture.html()) ).filter("#testForm").removeAttr("id");
  826. $wrapperDiv.append( $formByClone, $formByHTML );
  827. // Check submit bubbling on the copied forms
  828. $wrapperDiv.find("form").on( "submit", noSubmit ).find("input[name=sub1]").trigger("click");
  829. // Clean up
  830. $wrapperDiv.remove();
  831. $fixture.off( "submit", "form", delegatedSubmit );
  832. $testForm.off( "submit", noSubmit );
  833. });
  834. test( "change event bubbles on copied forms (#11796)", function(){
  835. expect( 3 );
  836. var $formByClone, $formByHTML,
  837. $form = jQuery("#form"),
  838. $fixture = jQuery("#qunit-fixture"),
  839. $wrapperDiv = jQuery("<div/>").appendTo( $fixture );
  840. function delegatedChange() {
  841. ok( true, "Make sure change event bubbles up." );
  842. return false;
  843. }
  844. // Attach a delegated change handler to the form
  845. $fixture.on( "change", "form", delegatedChange );
  846. // Trigger change event to introduce the _change_attached property
  847. $form.find("select[name=select1]").val("1").trigger("change");
  848. // Copy the form via .clone() and .html()
  849. $formByClone = $form.clone( true, true ).removeAttr("id");
  850. $formByHTML = jQuery( jQuery.parseHTML($fixture.html()) ).filter("#form").removeAttr("id");
  851. $wrapperDiv.append( $formByClone, $formByHTML );
  852. // Check change bubbling on the copied forms
  853. $wrapperDiv.find("form select[name=select1]").val("2").trigger("change");
  854. // Clean up
  855. $wrapperDiv.remove();
  856. $fixture.off( "change", "form", delegatedChange );
  857. });
  858. test("trigger(eventObject, [data], [fn])", function() {
  859. expect(28);
  860. var $parent = jQuery("<div id='par' />").appendTo("body"),
  861. $child = jQuery("<p id='child'>foo</p>").appendTo( $parent );
  862. $parent.get( 0 ).style.display = "none";
  863. var event = jQuery.Event("noNew");
  864. ok( event != window, "Instantiate jQuery.Event without the 'new' keyword" );
  865. equal( event.type, "noNew", "Verify its type" );
  866. equal( event.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
  867. equal( event.isPropagationStopped(), false, "Verify isPropagationStopped" );
  868. equal( event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
  869. event.preventDefault();
  870. equal( event.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
  871. event.stopPropagation();
  872. equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
  873. event.isPropagationStopped = function(){ return false; };
  874. event.stopImmediatePropagation();
  875. equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
  876. equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
  877. $parent.bind("foo",function(e){
  878. // Tries bubbling
  879. equal( e.type, "foo", "Verify event type when passed passing an event object" );
  880. equal( e.target.id, "child", "Verify event.target when passed passing an event object" );
  881. equal( e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object" );
  882. equal( e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object" );
  883. });
  884. // test with an event object
  885. event = new jQuery.Event("foo");
  886. event.secret = "boo!";
  887. $child.trigger(event);
  888. // test with a literal object
  889. $child.trigger({"type": "foo", "secret": "boo!"});
  890. $parent.unbind();
  891. function error(){
  892. ok( false, "This assertion shouldn't be reached");
  893. }
  894. $parent.bind("foo", error );
  895. $child.bind("foo",function(e, a, b, c ){
  896. equal( arguments.length, 4, "Check arguments length");
  897. equal( a, 1, "Check first custom argument");
  898. equal( b, 2, "Check second custom argument");
  899. equal( c, 3, "Check third custom argument");
  900. equal( e.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
  901. equal( e.isPropagationStopped(), false, "Verify isPropagationStopped" );
  902. equal( e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
  903. // Skips both errors
  904. e.stopImmediatePropagation();
  905. return "result";
  906. });
  907. // We should add this back in when we want to test the order
  908. // in which event handlers are iterated.
  909. //$child.bind("foo", error );
  910. event = new jQuery.Event("foo");
  911. $child.trigger( event, [1,2,3] ).unbind();
  912. equal( event.result, "result", "Check event.result attribute");
  913. // Will error if it bubbles
  914. $child.triggerHandler("foo");
  915. $child.unbind();
  916. $parent.unbind().remove();
  917. // Ensure triggerHandler doesn't molest its event object (#xxx)
  918. event = jQuery.Event( "zowie" );
  919. jQuery( document ).triggerHandler( event );
  920. equal( event.type, "zowie", "Verify its type" );
  921. equal( event.isPropagationStopped(), false, "propagation not stopped" );
  922. equal( event.isDefaultPrevented(), false, "default not prevented" );
  923. });
  924. // Explicitly introduce global variable for oldIE so QUnit doesn't complain if checking globals
  925. window.onclick = undefined;
  926. test(".trigger() bubbling on disconnected elements (#10489)", function() {
  927. expect(2);
  928. jQuery( window ).on( "click", function(){
  929. ok( false, "click fired on window" );
  930. });
  931. jQuery( "<div><p>hi</p></div>" )
  932. .on( "click", function() {
  933. ok( true, "click fired on div" );
  934. })
  935. .find( "p" )
  936. .on( "click", function() {
  937. ok( true, "click fired on p" );
  938. })
  939. .trigger("click")
  940. .off( "click" )
  941. .end()
  942. .off( "click" )
  943. .remove();
  944. jQuery( window ).off( "click" );
  945. });
  946. test(".trigger() doesn't bubble load event (#10717)", function() {
  947. expect(1);
  948. jQuery( window ).on( "load", function(){
  949. ok( false, "load fired on window" );
  950. });
  951. // It's not an image, but as long as it fires load...
  952. jQuery("<img src='index.html' />")
  953. .appendTo( "body" )
  954. .on( "load", function() {
  955. ok( true, "load fired on img" );
  956. })
  957. .trigger( "load" )
  958. .remove();
  959. jQuery( window ).off( "load" );
  960. });
  961. test("Delegated events in SVG (#10791; #13180)", function() {
  962. expect(2);
  963. var useElem, e,
  964. svg = jQuery(
  965. "<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>" +
  966. "<defs><rect id='ref' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect></defs>" +
  967. "<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
  968. "<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
  969. "<use id='use' xlink:href='#ref'></use>" +
  970. "</svg>"
  971. );
  972. jQuery("#qunit-fixture")
  973. .append( svg )
  974. .on( "click", "#svg-by-id", function() {
  975. ok( true, "delegated id selector" );
  976. })
  977. .on( "click", "[class~='svg-by-class']", function() {
  978. ok( true, "delegated class selector" );
  979. })
  980. .find( "#svg-by-id, [class~='svg-by-class']" )
  981. .trigger("click")
  982. .end();
  983. // Fire a native click on an SVGElementInstance (the instance tree of an SVG <use>)
  984. // to confirm that it doesn't break our event delegation handling (#13180)
  985. useElem = svg.find("#use")[0];
  986. if ( document.createEvent && useElem && useElem.instanceRoot ) {
  987. e = document.createEvent("MouseEvents");
  988. e.initEvent( "click", true, true );
  989. useElem.instanceRoot.dispatchEvent( e );
  990. }
  991. jQuery("#qunit-fixture").off("click");
  992. });
  993. test("Delegated events in forms (#10844; #11145; #8165; #11382, #11764)", function() {
  994. expect(5);
  995. // Alias names like "id" cause havoc
  996. var form = jQuery(
  997. "<form id='myform'>" +
  998. "<input type='text' name='id' value='secret agent man' />" +
  999. "</form>"
  1000. )
  1001. .on( "submit", function( event ) {
  1002. event.preventDefault();
  1003. })
  1004. .appendTo("body");
  1005. jQuery("body")
  1006. .on( "submit", "#myform", function() {
  1007. ok( true, "delegated id selector with aliased id" );
  1008. })
  1009. .find("#myform")
  1010. .trigger("submit")
  1011. .end()
  1012. .off("submit");
  1013. form.append("<input type='text' name='disabled' value='differently abled' />");
  1014. jQuery("body")
  1015. .on( "submit", "#myform", function() {
  1016. ok( true, "delegated id selector with aliased disabled" );
  1017. })
  1018. .find("#myform")
  1019. .trigger("submit")
  1020. .end()
  1021. .off("submit");
  1022. form
  1023. .append( "<button id='nestyDisabledBtn'><span>Zing</span></button>" )
  1024. .on( "click", "#nestyDisabledBtn", function() {
  1025. ok( true, "click on enabled/disabled button with nesty elements" );
  1026. })
  1027. .on( "mouseover", "#nestyDisabledBtn", function() {
  1028. ok( true, "mouse on enabled/disabled button with nesty elements" );
  1029. })
  1030. .find( "span" )
  1031. .trigger( "click" ) // yep
  1032. .trigger( "mouseover" ) // yep
  1033. .end()
  1034. .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
  1035. .find( "span" )
  1036. .trigger( "click" ) // nope
  1037. .trigger( "mouseover" ) // yep
  1038. .end()
  1039. .off( "click" );
  1040. form.remove();
  1041. });
  1042. test("Submit event can be stopped (#11049)", function() {
  1043. expect(1);
  1044. // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
  1045. var form = jQuery(
  1046. "<form id='myform'>" +
  1047. "<input type='text' name='sue' value='bawls' />" +
  1048. "<input type='submit' />" +
  1049. "</form>"
  1050. )
  1051. .appendTo("body");
  1052. jQuery( "body" )
  1053. .on( "submit", function() {
  1054. ok( true, "submit bubbled on first handler" );
  1055. return false;
  1056. })
  1057. .find( "#myform input[type=submit]" )
  1058. .each( function(){ this.click(); } )
  1059. .end()
  1060. .on( "submit", function() {
  1061. ok( false, "submit bubbled on second handler" );
  1062. return false;
  1063. })
  1064. .find( "#myform input[type=submit]" )
  1065. .each( function(){
  1066. jQuery( this.form ).on( "submit", function( e ) {
  1067. e.preventDefault();
  1068. e.stopPropagation();
  1069. });
  1070. this.click();
  1071. })
  1072. .end()
  1073. .off( "submit" );
  1074. form.remove();
  1075. });
  1076. // Test beforeunload event only if it supported (i.e. not Opera)
  1077. if ( window.onbeforeunload === null ) {
  1078. asyncTest("on(beforeunload)", 4, function() {
  1079. var win,
  1080. forIE6 = 0,
  1081. fired = false,
  1082. iframe = jQuery("<iframe src='data/iframe.html' />");
  1083. iframe.appendTo("#qunit-fixture").one( "load", function() {
  1084. win = this.contentWindow || this.contentDocument;
  1085. jQuery( win ).on( "beforeunload", function() {
  1086. fired = true;
  1087. ok( true, "beforeunload event is fired" );
  1088. });
  1089. strictEqual( win.onbeforeunload, null, "onbeforeunload property on window object still equals null" );
  1090. // In old Safari beforeunload event will not fire on iframes
  1091. jQuery( win ).on( "unload", function() {
  1092. if ( !fired ) {
  1093. ok( true, "This is suppose to be true only in old Safari" );
  1094. checker();
  1095. }
  1096. });
  1097. jQuery( win ).on( "beforeunload", function() {
  1098. // On iframe in IE6 beforeunload event will not fire if event is binded through window object,
  1099. // nevertheless, test should continue
  1100. window.setTimeout(function() {
  1101. if ( !forIE6 ) {
  1102. checker();
  1103. }
  1104. });
  1105. });
  1106. win.onbeforeunload = function() {
  1107. if ( !forIE6 ) {
  1108. forIE6++;
  1109. checker();
  1110. }
  1111. };
  1112. function checker() {
  1113. ok( true, "window.onbeforeunload handler is called" );
  1114. iframe = jQuery("<iframe src='data/iframe.html' />");
  1115. iframe.appendTo("#qunit-fixture").one( "load", function() {
  1116. win = iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument;
  1117. jQuery( win ).on( "beforeunload", function() {
  1118. strictEqual( win.onbeforeunload, null, "Event handler is fired, even when onbeforeunload property on window is nulled" );
  1119. start();
  1120. });
  1121. jQuery( win ).on( "unload", function() {
  1122. if ( !fired ) {
  1123. jQuery( win ).trigger("beforeunload");
  1124. }
  1125. });
  1126. win.onbeforeunload = null;
  1127. win.location.reload();
  1128. });
  1129. }
  1130. win.location.reload();
  1131. });
  1132. });
  1133. }
  1134. test("jQuery.Event( type, props )", function() {
  1135. expect(5);
  1136. var event = jQuery.Event( "keydown", { keyCode: 64 }),
  1137. handler = function( event ) {
  1138. ok( "keyCode" in event, "Special property 'keyCode' exists" );
  1139. equal( event.keyCode, 64, "event.keyCode has explicit value '64'" );
  1140. };
  1141. // Supports jQuery.Event implementation
  1142. equal( event.type, "keydown", "Verify type" );
  1143. // ensure "type" in props won't clobber the one set by constructor
  1144. equal( jQuery.inArray("type", jQuery.event.props), -1, "'type' property not in props (#10375)" );
  1145. ok( "keyCode" in event, "Special 'keyCode' property exists" );
  1146. jQuery("body").bind( "keydown", handler ).trigger( event );
  1147. jQuery("body").unbind( "keydown" );
  1148. });
  1149. test("jQuery.Event.currentTarget", function(){
  1150. expect(2);
  1151. jQuery("<div><p><button>shiny</button></p></div>")
  1152. .on( "click", "p", function( e ){
  1153. equal( e.currentTarget, this, "Check delegated currentTarget on event" );
  1154. })
  1155. .find( "button" )
  1156. .on( "click", function( e ){
  1157. equal( e.currentTarget, this, "Check currentTarget on event" );
  1158. })
  1159. .trigger("click")
  1160. .off( "click" )
  1161. .end()
  1162. .off( "click" );
  1163. });
  1164. test(".delegate()/.undelegate()", function() {
  1165. expect(65);
  1166. var submit = 0, div = 0, livea = 0, liveb = 0;
  1167. jQuery("#body").delegate("#qunit-fixture div", "submit", function(){ submit++; return false; });
  1168. jQuery("#body").delegate("#qunit-fixture div", "click", function(){ div++; });
  1169. jQuery("#body").delegate("div#nothiddendiv", "click", function(){ livea++; });
  1170. jQuery("#body").delegate("div#nothiddendivchild", "click", function(){ liveb++; });
  1171. // Nothing should trigger on the body
  1172. jQuery("body").trigger("click");
  1173. equal( submit, 0, "Click on body" );
  1174. equal( div, 0, "Click on body" );
  1175. equal( livea, 0, "Click on body" );
  1176. equal( liveb, 0, "Click on body" );
  1177. // This should trigger two events
  1178. submit = 0; div = 0; livea = 0; liveb = 0;
  1179. jQuery("div#nothiddendiv").trigger("click");
  1180. equal( submit, 0, "Click on div" );
  1181. equal( div, 1, "Click on div" );
  1182. equal( livea, 1, "Click on div" );
  1183. equal( liveb, 0, "Click on div" );
  1184. // This should trigger three events (w/ bubbling)
  1185. submit = 0; div = 0; livea = 0; liveb = 0;
  1186. jQuery("div#nothiddendivchild").trigger("click");
  1187. equal( submit, 0, "Click on inner div" );
  1188. equal( div, 2, "Click on inner div" );
  1189. equal( livea, 1, "Click on inner div" );
  1190. equal( liveb, 1, "Click on inner div" );
  1191. // This should trigger one submit
  1192. submit = 0; div = 0; livea = 0; liveb = 0;
  1193. jQuery("div#nothiddendivchild").trigger("submit");
  1194. equal( submit, 1, "Submit on div" );
  1195. equal( div, 0, "Submit on div" );
  1196. equal( livea, 0, "Submit on div" );
  1197. equal( liveb, 0, "Submit on div" );
  1198. // Make sure no other events were removed in the process
  1199. submit = 0; div = 0; livea = 0; liveb = 0;
  1200. jQuery("div#nothiddendivchild").trigger("click");
  1201. equal( submit, 0, "undelegate Click on inner div" );
  1202. equal( div, 2, "undelegate Click on inner div" );
  1203. equal( livea, 1, "undelegate Click on inner div" );
  1204. equal( liveb, 1, "undelegate Click on inner div" );
  1205. // Now make sure that the removal works
  1206. submit = 0; div = 0; livea = 0; liveb = 0;
  1207. jQuery("#body").undelegate("div#nothiddendivchild", "click");
  1208. jQuery("div#nothiddendivchild").trigger("click");
  1209. equal( submit, 0, "undelegate Click on inner div" );
  1210. equal( div, 2, "undelegate Click on inner div" );
  1211. equal( livea, 1, "undelegate Click on inner div" );
  1212. equal( liveb, 0, "undelegate Click on inner div" );
  1213. // Make sure that the click wasn't removed too early
  1214. submit = 0; div = 0; livea = 0; liveb = 0;
  1215. jQuery("div#nothiddendiv").trigger("click");
  1216. equal( submit, 0, "undelegate Click on inner div" );
  1217. equal( div, 1, "undelegate Click on inner div" );
  1218. equal( livea, 1, "undelegate Click on inner div" );
  1219. equal( liveb, 0, "undelegate Click on inner div" );
  1220. // Make sure that stopPropgation doesn't stop live events
  1221. submit = 0; div = 0; livea = 0; liveb = 0;
  1222. jQuery("#body").delegate("div#nothiddendivchild", "click", function(e){ liveb++; e.stopPropagation(); });
  1223. jQuery("div#nothiddendivchild").trigger("click");
  1224. equal( submit, 0, "stopPropagation Click on inner div" );
  1225. equal( div, 1, "stopPropagation Click on inner div" );
  1226. equal( livea, 0, "stopPropagation Click on inner div" );
  1227. equal( liveb, 1, "stopPropagation Click on inner div" );
  1228. // Make sure click events only fire with primary click
  1229. submit = 0; div = 0; livea = 0; liveb = 0;
  1230. var event = jQuery.Event("click");
  1231. event.button = 1;
  1232. jQuery("div#nothiddendiv").trigger(event);
  1233. equal( livea, 0, "delegate secondary click" );
  1234. jQuery("#body").undelegate("div#nothiddendivchild", "click");
  1235. jQuery("#body").undelegate("div#nothiddendiv", "click");
  1236. jQuery("#body").undelegate("#qunit-fixture div", "click");
  1237. jQuery("#body").undelegate("#qunit-fixture div", "submit");
  1238. // Test binding with a different context
  1239. var clicked = 0, container = jQuery("#qunit-fixture")[0];
  1240. jQuery("#qunit-fixture").delegate("#foo", "click", function(e){ clicked++; });
  1241. jQuery("#qunit-fixture div").trigger("click");
  1242. jQuery("#foo").trigger("click");
  1243. jQuery("#qunit-fixture").trigger("click");
  1244. jQuery("body").trigger("click");
  1245. equal( clicked, 2, "delegate with a context" );
  1246. // Test unbinding with a different context
  1247. jQuery("#qunit-fixture").undelegate("#foo", "click");
  1248. jQuery("#foo").trigger("click");
  1249. equal( clicked, 2, "undelegate with a context");
  1250. // Test binding with event data
  1251. jQuery("#body").delegate("#foo", "click", true, function(e){ equal( e.data, true, "delegate with event data" ); });
  1252. jQuery("#foo").trigger("click");
  1253. jQuery("#body").undelegate("#foo", "click");
  1254. // Test binding with trigger data
  1255. jQuery("#body").delegate("#foo", "click", function(e, data){ equal( data, true, "delegate with trigger data" ); });
  1256. jQuery("#foo").trigger("click", true);
  1257. jQuery("#body").undelegate("#foo", "click");
  1258. // Test binding with different this object
  1259. jQuery("#body").delegate("#foo", "click", jQuery.proxy(function(e){ equal( this["foo"], "bar", "delegate with event scope" ); }, { "foo": "bar" }));
  1260. jQuery("#foo").trigger("click");
  1261. jQuery("#body").undelegate("#foo", "click");
  1262. // Test binding with different this object, event data, and trigger data
  1263. jQuery("#body").delegate("#foo", "click", true, jQuery.proxy(function(e, data){
  1264. equal( e.data, true, "delegate with with different this object, event data, and trigger data" );
  1265. equal( this.foo, "bar", "delegate with with different this object, event data, and trigger data" );
  1266. equal( data, true, "delegate with with different this object, event data, and trigger data");
  1267. }, { "foo": "bar" }));
  1268. jQuery("#foo").trigger("click", true);
  1269. jQuery("#body").undelegate("#foo", "click");
  1270. // Verify that return false prevents default action
  1271. jQuery("#body").delegate("#anchor2", "click", function(){ return false; });
  1272. var hash = window.location.hash;
  1273. jQuery("#anchor2").trigger("click");
  1274. equal( window.location.hash, hash, "return false worked" );
  1275. jQuery("#body").undelegate("#anchor2", "click");
  1276. // Verify that .preventDefault() prevents default action
  1277. jQuery("#body").delegate("#anchor2", "click", function(e){ e.preventDefault(); });
  1278. hash = window.location.hash;
  1279. jQuery("#anchor2").trigger("click");
  1280. equal( window.location.hash, hash, "e.preventDefault() worked" );
  1281. jQuery("#body").undelegate("#anchor2", "click");
  1282. // Test binding the same handler to multiple points
  1283. var called = 0;
  1284. function callback(){ called++; return false; }
  1285. jQuery("#body").delegate("#nothiddendiv", "click", callback);
  1286. jQuery("#body").delegate("#anchor2", "click", callback);
  1287. jQuery("#nothiddendiv").trigger("click");
  1288. equal( called, 1, "Verify that only one click occurred." );
  1289. called = 0;
  1290. jQuery("#anchor2").trigger("click");
  1291. equal( called, 1, "Verify that only one click occurred." );
  1292. // Make sure that only one callback is removed
  1293. jQuery("#body").undelegate("#anchor2", "click", callback);
  1294. called = 0;
  1295. jQuery("#nothiddendiv").trigger("click");
  1296. equal( called, 1, "Verify that only one click occurred." );
  1297. called = 0;
  1298. jQuery("#anchor2").trigger("click");
  1299. equal( called, 0, "Verify that no click occurred." );
  1300. // Make sure that it still works if the selector is the same,
  1301. // but the event type is different
  1302. jQuery("#body").delegate("#nothiddendiv", "foo", callback);
  1303. // Cleanup
  1304. jQuery("#body").undelegate("#nothiddendiv", "click", callback);
  1305. called = 0;
  1306. jQuery("#nothiddendiv").trigger("click");
  1307. equal( called, 0, "Verify that no click occurred." );
  1308. called = 0;
  1309. jQuery("#nothiddendiv").trigger("foo");
  1310. equal( called, 1, "Verify that one foo occurred." );
  1311. // Cleanup
  1312. jQuery("#body").undelegate("#nothiddendiv", "foo", callback);
  1313. // Make sure we don't loose the target by DOM modifications
  1314. // after the bubble already reached the liveHandler
  1315. var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("<span></span>").get(0);
  1316. jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ jQuery("#nothiddendivchild").html(""); });
  1317. jQuery("#body").delegate("#nothiddendivchild", "click", function(e){ if(e.target) {livec++;} });
  1318. jQuery("#nothiddendiv span").trigger("click");
  1319. equal( jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM." );
  1320. equal( livec, 1, "Verify that second handler occurred even with nuked target." );
  1321. // Cleanup
  1322. jQuery("#body").undelegate("#nothiddendivchild", "click");
  1323. // Verify that .live() ocurs and cancel buble in the same order as
  1324. // we would expect .bind() and .click() without delegation
  1325. var lived = 0, livee = 0;
  1326. // bind one pair in one order
  1327. jQuery("#body").delegate("span#liveSpan1 a", "click", function(){ lived++; return false; });
  1328. jQuery("#body").delegate("span#liveSpan1", "click", function(){ livee++; });
  1329. jQuery("span#liveSpan1 a").trigger("click");
  1330. equal( lived, 1, "Verify that only one first handler occurred." );
  1331. equal( livee, 0, "Verify that second handler doesn't." );
  1332. // and one pair in inverse
  1333. jQuery("#body").delegate("span#liveSpan2", "click", function(){ livee++; });
  1334. jQuery("#body").delegate("span#liveSpan2 a", "click", function(){ lived++; return false; });
  1335. lived = 0;
  1336. livee = 0;
  1337. jQuery("span#liveSpan2 a").trigger("click");
  1338. equal( lived, 1, "Verify that only one first handler occurred." );
  1339. equal( livee, 0, "Verify that second handler doesn't." );
  1340. // Cleanup
  1341. jQuery("#body").undelegate("click");
  1342. // Test this, target and currentTarget are correct
  1343. jQuery("#body").delegate("span#liveSpan1", "click", function(e){
  1344. equal( this.id, "liveSpan1", "Check the this within a delegate handler" );
  1345. equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a delegate handler" );
  1346. equal( e.delegateTarget, document.body, "Check the event.delegateTarget within a delegate handler" );
  1347. equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a delegate handler" );
  1348. });
  1349. jQuery("span#liveSpan1 a").trigger("click");
  1350. jQuery("#body").undelegate("span#liveSpan1", "click");
  1351. // Work with deep selectors
  1352. livee = 0;
  1353. function clickB(){ livee++; }
  1354. jQuery("#body").delegate("#nothiddendiv div", "click", function(){ livee++; });
  1355. jQuery("#body").delegate("#nothiddendiv div", "click", clickB);
  1356. jQuery("#body").delegate("#nothiddendiv div", "mouseover", function(){ livee++; });
  1357. equal( livee, 0, "No clicks, deep selector." );
  1358. livee = 0;
  1359. jQuery("#nothiddendivchild").trigger("click");
  1360. equal( livee, 2, "Click, deep selector." );
  1361. livee = 0;
  1362. jQuery("#nothiddendivchild").trigger("mouseover");
  1363. equal( livee, 1, "Mouseover, deep selector." );
  1364. jQuery("#body").undelegate("#nothiddendiv div", "mouseover");
  1365. livee = 0;
  1366. jQuery("#nothiddendivchild").trigger("click");
  1367. equal( livee, 2, "Click, deep selector." );
  1368. livee = 0;
  1369. jQuery("#nothiddendivchild").trigger("mouseover");
  1370. equal( livee, 0, "Mouseover, deep selector." );
  1371. jQuery("#body").undelegate("#nothiddendiv div", "click", clickB);
  1372. livee = 0;
  1373. jQuery("#nothiddendivchild").trigger("click");
  1374. equal( livee, 1, "Click, deep selector." );
  1375. jQuery("#body").undelegate("#nothiddendiv div", "click");
  1376. });
  1377. test("jQuery.off using dispatched jQuery.Event", function() {
  1378. expect(1);
  1379. var markup = jQuery("<p><a href='#'>target</a></p>"),
  1380. count = 0;
  1381. markup
  1382. .on( "click.name", "a", function( event ) {
  1383. equal( ++count, 1, "event called once before removal" );
  1384. jQuery().off( event );
  1385. })
  1386. .find("a").trigger("click").trigger("click").end()
  1387. .remove();
  1388. });
  1389. test( "delegated event with delegateTarget-relative selector", function() {
  1390. expect(3);
  1391. 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");
  1392. // Positional selector (#11315)
  1393. markup
  1394. .on( "click", ">li>a", function() {
  1395. ok( this.id === "a0", "child li was clicked" );
  1396. })
  1397. .find("#ul0")
  1398. .on( "click", "li:first>a", function() {
  1399. ok( this.id === "a0_0" , "first li under #u10 was clicked" );
  1400. })
  1401. .end()
  1402. .find("a").trigger("click").end()
  1403. .find("#ul0").off();
  1404. // Non-positional selector (#12383)
  1405. markup = markup.wrap("<div />").parent();
  1406. markup
  1407. .find("#ul0")
  1408. .on( "click", "div li a", function() {
  1409. ok( false, "div is ABOVE the delegation point!" );
  1410. })
  1411. .on( "click", "ul a", function() {
  1412. ok( false, "ul is the delegation point!" );
  1413. })
  1414. .on( "click", "li.test a", function() {
  1415. ok( true, "li.test is below the delegation point." );
  1416. })
  1417. .find("#a0_0").trigger("click");
  1418. markup.remove();
  1419. });
  1420. test( "delegated event with selector matching Object.prototype property (#13203)", function() {
  1421. expect(1);
  1422. var matched = 0;
  1423. jQuery("#foo").on( "click", "toString", function( e ) {
  1424. matched++;
  1425. });
  1426. jQuery("#anchor2").trigger("click");
  1427. equal( matched, 0, "Nothing matched 'toString'" );
  1428. });
  1429. test( "delegated event with intermediate DOM manipulation (#13208)", function() {
  1430. expect(1);
  1431. jQuery("#foo").on( "click", "#sap", function() {});
  1432. jQuery("#sap").on( "click", "#anchor2", function() {
  1433. jQuery( this.parentNode ).remove();
  1434. ok( true, "Element removed" );
  1435. });
  1436. jQuery("#anchor2").trigger("click");
  1437. });
  1438. test("stopPropagation() stops directly-bound events on delegated target", function() {
  1439. expect(1);
  1440. var markup = jQuery("<div><p><a href=\"#\">target</a></p></div>");
  1441. markup
  1442. .on( "click", function() {
  1443. ok( false, "directly-bound event on delegate target was called" );
  1444. })
  1445. .on( "click", "a", function( e ) {
  1446. e.stopPropagation();
  1447. ok( true, "delegated handler was called" );
  1448. })
  1449. .find("a").trigger("click").end()
  1450. .remove();
  1451. });
  1452. test("undelegate all bound events", function(){
  1453. expect(2);
  1454. var count = 0,
  1455. clicks = 0,
  1456. div = jQuery("#body");
  1457. div.delegate( "div#nothiddendivchild", "click submit", function(){ count++; } );
  1458. div.bind( "click", function(){ clicks++; } );
  1459. div.undelegate();
  1460. jQuery("div#nothiddendivchild").trigger("click");
  1461. jQuery("div#nothiddendivchild").trigger("submit");
  1462. equal( count, 0, "Make sure no events were triggered." );
  1463. div.trigger("click");
  1464. equal( clicks, 2, "Make sure delegated and directly bound event occurred." );
  1465. div.unbind("click");
  1466. });
  1467. test("delegate with multiple events", function(){
  1468. expect(1);
  1469. var count = 0;
  1470. var div = jQuery("#body");
  1471. div.delegate("div#nothiddendivchild", "click submit", function(){ count++; });
  1472. jQuery("div#nothiddendivchild").trigger("click");
  1473. jQuery("div#nothiddendivchild").trigger("submit");
  1474. equal( count, 2, "Make sure both the click and submit were triggered." );
  1475. jQuery("#body").undelegate();
  1476. });
  1477. test("delegate with change", function(){
  1478. expect(8);
  1479. var selectChange = 0, checkboxChange = 0;
  1480. var select = jQuery("select[name='S1']");
  1481. jQuery("#body").delegate("select[name='S1']", "change", function() {
  1482. selectChange++;
  1483. });
  1484. var checkbox = jQuery("#check2"),
  1485. checkboxFunction = function(){
  1486. checkboxChange++;
  1487. };
  1488. jQuery("#body").delegate("#check2", "change", checkboxFunction);
  1489. // test click on select
  1490. // second click that changed it
  1491. selectChange = 0;
  1492. select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
  1493. select.trigger("change");
  1494. equal( selectChange, 1, "Change on click." );
  1495. // test keys on select
  1496. selectChange = 0;
  1497. select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
  1498. select.trigger("change");
  1499. equal( selectChange, 1, "Change on keyup." );
  1500. // test click on checkbox
  1501. checkbox.trigger("change");
  1502. equal( checkboxChange, 1, "Change on checkbox." );
  1503. // test blur/focus on text
  1504. var text = jQuery("#name"), textChange = 0, oldTextVal = text.val();
  1505. jQuery("#body").delegate("#name", "change", function() {
  1506. textChange++;
  1507. });
  1508. text.val(oldTextVal+"foo");
  1509. text.trigger("change");
  1510. equal( textChange, 1, "Change on text input." );
  1511. text.val(oldTextVal);
  1512. jQuery("#body").undelegate("#name", "change");
  1513. // test blur/focus on password
  1514. var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val();
  1515. jQuery("#body").delegate("#name", "change", function() {
  1516. passwordChange++;
  1517. });
  1518. password.val(oldPasswordVal + "foo");
  1519. password.trigger("change");
  1520. equal( passwordChange, 1, "Change on password input." );
  1521. password.val(oldPasswordVal);
  1522. jQuery("#body").undelegate("#name", "change");
  1523. // make sure die works
  1524. // die all changes
  1525. selectChange = 0;
  1526. jQuery("#body").undelegate("select[name='S1']", "change");
  1527. select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
  1528. select.trigger("change");
  1529. equal( selectChange, 0, "Die on click works." );
  1530. selectChange = 0;
  1531. select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
  1532. select.trigger("change");
  1533. equal( selectChange, 0, "Die on keyup works." );
  1534. // die specific checkbox
  1535. jQuery("#body").undelegate("#check2", "change", checkboxFunction);
  1536. checkbox.trigger("change");
  1537. equal( checkboxChange, 1, "Die on checkbox." );
  1538. });
  1539. test("delegate with submit", function() {
  1540. expect( 2 );
  1541. var count1 = 0, count2 = 0;
  1542. jQuery("#body").delegate("#testForm", "submit", function(ev) {
  1543. count1++;
  1544. ev.preventDefault();
  1545. });
  1546. jQuery(document).delegate("body", "submit", function(ev) {
  1547. count2++;
  1548. ev.preventDefault();
  1549. });
  1550. jQuery("#testForm input[name=sub1]").trigger("submit");
  1551. equal( count1, 1, "Verify form submit." );
  1552. equal( count2, 1, "Verify body submit." );
  1553. jQuery("#body").undelegate();
  1554. jQuery(document).undelegate();
  1555. });
  1556. test("undelegate() with only namespaces", function() {
  1557. expect(2);
  1558. var $delegate = jQuery("#liveHandlerOrder"),
  1559. count = 0;
  1560. $delegate.delegate("a", "click.ns", function(e) {
  1561. count++;
  1562. });
  1563. jQuery("a", $delegate).eq(0).trigger("click.ns");
  1564. equal( count, 1, "delegated click.ns");
  1565. $delegate.undelegate(".ns");
  1566. jQuery("a", $delegate).eq(1).trigger("click.ns");
  1567. equal( count, 1, "no more .ns after undelegate");
  1568. });
  1569. test("Non DOM element events", function() {
  1570. expect(1);
  1571. var o = {};
  1572. jQuery(o).bind("nonelementobj", function(e) {
  1573. ok( true, "Event on non-DOM object triggered" );
  1574. });
  1575. jQuery(o).trigger("nonelementobj");
  1576. });
  1577. test("inline handler returning false stops default", function() {
  1578. expect(1);
  1579. var markup = jQuery("<div><a href=\"#\" onclick=\"return false\">x</a></div>");
  1580. markup.on( "click", function(e) {
  1581. ok( e.isDefaultPrevented(), "inline handler prevented default");
  1582. return false;
  1583. });
  1584. markup.find("a").trigger("click");
  1585. markup.off("click");
  1586. });
  1587. test("window resize", function() {
  1588. expect(2);
  1589. jQuery(window).off();
  1590. jQuery(window).on( "resize", function(){
  1591. ok( true, "Resize event fired." );
  1592. }).trigger("resize").off("resize");
  1593. ok( !jQuery._data(window, "events"), "Make sure all the events are gone." );
  1594. });
  1595. test("focusin bubbles", function() {
  1596. expect(2);
  1597. var input = jQuery( "<input type='text' />" ).prependTo( "body" ),
  1598. order = 0;
  1599. // focus the element so DOM focus won't fire
  1600. input[0].focus();
  1601. jQuery( "body" ).bind( "focusin.focusinBubblesTest", function(){
  1602. equal( 1, order++, "focusin on the body second" );
  1603. });
  1604. input.bind( "focusin.focusinBubblesTest", function(){
  1605. equal( 0, order++, "focusin on the element first" );
  1606. });
  1607. // Removed since DOM focus is unreliable on test swarm
  1608. // DOM focus method
  1609. // input[0].focus();
  1610. // To make the next focus test work, we need to take focus off the input.
  1611. // This will fire another focusin event, so set order to reflect that.
  1612. // order = 1;
  1613. // jQuery("#text1")[0].focus();
  1614. // jQuery trigger, which calls DOM focus
  1615. order = 0;
  1616. input.trigger( "focus" );
  1617. input.remove();
  1618. jQuery( "body" ).unbind( "focusin.focusinBubblesTest" );
  1619. });
  1620. test("custom events with colons (#3533, #8272)", function() {
  1621. expect(1);
  1622. var tab = jQuery("<table><tr><td>trigger</td></tr></table>").appendTo("body");
  1623. try {
  1624. tab.trigger("back:forth");
  1625. ok( true, "colon events don't throw" );
  1626. } catch ( e ) {
  1627. ok( false, "colon events die" );
  1628. }
  1629. tab.remove();
  1630. });
  1631. test(".on and .off", function() {
  1632. expect(9);
  1633. var counter, mixfn;
  1634. var $onandoff = jQuery("<div id=\"onandoff\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>").appendTo("body");
  1635. // Simple case
  1636. jQuery( "#onandoff" )
  1637. .on( "whip", function() {
  1638. ok( true, "whipped it good" );
  1639. })
  1640. .trigger( "whip" )
  1641. .off();
  1642. // Direct events only
  1643. counter = 0;
  1644. jQuery( "#onandoff b" )
  1645. .on( "click", 5, function( e, trig ) {
  1646. counter += e.data + (trig || 9); // twice, 5+9+5+17=36
  1647. })
  1648. .one( "click", 7, function( e, trig ) {
  1649. counter += e.data + (trig || 11); // once, 7+11=18
  1650. })
  1651. .trigger("click")
  1652. .trigger( "click", 17 )
  1653. .off( "click" );
  1654. equal( counter, 54, "direct event bindings with data" );
  1655. // Delegated events only
  1656. counter = 0;
  1657. jQuery( "#onandoff" )
  1658. .on( "click", "em", 5, function( e, trig ) {
  1659. counter += e.data + (trig || 9); // twice, 5+9+5+17=36
  1660. })
  1661. .one( "click", "em", 7, function( e, trig ) {
  1662. counter += e.data + (trig || 11); // once, 7+11=18
  1663. })
  1664. .find("em")
  1665. .trigger("click")
  1666. .trigger( "click", 17 )
  1667. .end()
  1668. .off( "click", "em" );
  1669. equal( counter, 54, "delegated event bindings with data" );
  1670. // Mixed event bindings and types
  1671. counter = 0;
  1672. mixfn = function(e, trig) {
  1673. counter += (e.data || 0) + (trig || 1);
  1674. };
  1675. jQuery( "#onandoff" )
  1676. .on( " click clack cluck ", "em", 2, mixfn )
  1677. .on( "cluck", "b", 7, mixfn )
  1678. .on( "cluck", mixfn )
  1679. .trigger( "what!" )
  1680. .each( function() {
  1681. equal( counter, 0, "nothing triggered yet" );
  1682. })
  1683. .find( "em" )
  1684. .one( "cluck", 3, mixfn )
  1685. .trigger( "cluck", 8 ) // 3+8 2+8 + 0+8 = 29
  1686. .off()
  1687. .trigger( "cluck", 9 ) // 2+9 + 0+9 = 20
  1688. .end()
  1689. .each( function() {
  1690. equal( counter, 49, "after triggering em element" );
  1691. })
  1692. .off( "cluck", function(){} ) // shouldn't remove anything
  1693. .trigger( "cluck", 2 ) // 0+2 = 2
  1694. .each( function() {
  1695. equal( counter, 51, "after triggering #onandoff cluck" );
  1696. })
  1697. .find( "b" )
  1698. .on( "click", 95, mixfn )
  1699. .on( "clack", "p", 97, mixfn )
  1700. .one( "cluck", 3, mixfn )
  1701. .trigger( "quack", 19 ) // 0
  1702. .off( "click clack cluck" )
  1703. .end()
  1704. .each( function() {
  1705. equal( counter, 51, "after triggering b" );
  1706. })
  1707. .trigger( "cluck", 3 ) // 0+3 = 3
  1708. .off( "clack", "em", mixfn )
  1709. .find( "em" )
  1710. .trigger( "clack" ) // 0
  1711. .end()
  1712. .each( function() {
  1713. equal( counter, 54, "final triggers" );
  1714. })
  1715. .off( "click cluck" );
  1716. // We should have removed all the event handlers ... kinda hacky way to check this
  1717. var data = jQuery.data[ jQuery( "#onandoff" )[0].expando ] || {};
  1718. equal( data["events"], undefined, "no events left" );
  1719. $onandoff.remove();
  1720. });
  1721. test("special bind/delegate name mapping", function() {
  1722. expect( 7 );
  1723. jQuery.event.special["slap"] = {
  1724. bindType: "click",
  1725. delegateType: "swing",
  1726. handle: function( event ) {
  1727. equal( event.handleObj.origType, "slap", "slapped your mammy, " + event.type );
  1728. }
  1729. };
  1730. var comeback = function( event ) {
  1731. ok( true, "event " + event.type + " triggered" );
  1732. };
  1733. jQuery("<div><button id=\"mammy\">Are We Not Men?</button></div>")
  1734. .on( "slap", "button", jQuery.noop )
  1735. .on( "swing", "button", comeback )
  1736. .find( "button" )
  1737. .on( "slap", jQuery.noop )
  1738. .on( "click", comeback )
  1739. .trigger( "click" ) // bindType-slap and click
  1740. .off( "slap" )
  1741. .trigger( "click" ) // click
  1742. .off( "click" )
  1743. .trigger( "swing" ) // delegateType-slap and swing
  1744. .end()
  1745. .off( "slap swing", "button" )
  1746. .find( "button" ) // everything should be gone
  1747. .trigger( "slap" )
  1748. .trigger( "click" )
  1749. .trigger( "swing" )
  1750. .end()
  1751. .remove();
  1752. delete jQuery.event.special["slap"];
  1753. jQuery.event.special["gutfeeling"] = {
  1754. bindType: "click",
  1755. delegateType: "click",
  1756. handle: function( event ) {
  1757. equal( event.handleObj.origType, "gutfeeling", "got a gutfeeling" );
  1758. // Need to call the handler since .one() uses it to unbind
  1759. return event.handleObj.handler.call( this , event );
  1760. }
  1761. };
  1762. // Ensure a special event isn't removed by its mapped type
  1763. jQuery( "<p>Gut Feeling</p>" )
  1764. .on( "click", jQuery.noop )
  1765. .on( "gutfeeling", jQuery.noop )
  1766. .off( "click" )
  1767. .trigger( "gutfeeling" )
  1768. .remove();
  1769. // Ensure special events are removed when only a namespace is provided
  1770. jQuery( "<p>Gut Feeling</p>" )
  1771. .on( "gutfeeling.Devo", jQuery.noop )
  1772. .off( ".Devo" )
  1773. .trigger( "gutfeeling" )
  1774. .remove();
  1775. // Ensure .one() events are removed after their maiden voyage
  1776. jQuery( "<p>Gut Feeling</p>" )
  1777. .one( "gutfeeling", jQuery.noop )
  1778. .trigger( "gutfeeling" ) // This one should
  1779. .trigger( "gutfeeling" ) // This one should not
  1780. .remove();
  1781. delete jQuery.event.special["gutfeeling"];
  1782. });
  1783. test(".on and .off, selective mixed removal (#10705)", function() {
  1784. expect(7);
  1785. var clockout = 0,
  1786. timingx = function( e ) {
  1787. ok( true, "triggered " + e.type );
  1788. };
  1789. jQuery( "<p>Strange Pursuit</p>" )
  1790. .on( "click", timingx )
  1791. .on( "click.duty", timingx )
  1792. .on( "click.now", timingx )
  1793. .on( "devo", timingx )
  1794. .on( "future", timingx )
  1795. .trigger( "click" ) // 3
  1796. .trigger( "devo" ) // 1
  1797. .off( ".duty devo " ) // trailing space
  1798. .trigger( "future" ) // 1
  1799. .trigger( "click" ) // 2
  1800. .off( "future click" )
  1801. .trigger( "click" ); // 0
  1802. });
  1803. test(".on( event-map, null-selector, data ) #11130", function() {
  1804. expect( 1 );
  1805. var $p = jQuery("<p>Strange Pursuit</p>"),
  1806. data = "bar",
  1807. map = {
  1808. "foo": function( event ) {
  1809. equal( event.data, "bar", "event.data correctly relayed with null selector" );
  1810. $p.remove();
  1811. }
  1812. };
  1813. $p.on( map, null, data ).trigger("foo");
  1814. });
  1815. test("clone() delegated events (#11076)", function() {
  1816. expect(3);
  1817. var counter = { "center": 0, "fold": 0, "centerfold": 0 },
  1818. clicked = function( event ) {
  1819. counter[ jQuery(this).text().replace(/\s+/, "") ]++;
  1820. },
  1821. table =
  1822. jQuery( "<table><tr><td>center</td><td>fold</td></tr></table>" )
  1823. .on( "click", "tr", clicked )
  1824. .on( "click", "td:first-child", clicked )
  1825. .on( "click", "td:last-child", clicked ),
  1826. clone = table.clone( true );
  1827. clone.find("td").trigger("click");
  1828. equal( counter["center"], 1, "first child" );
  1829. equal( counter["fold"], 1, "last child" );
  1830. equal( counter["centerfold"], 2, "all children" );
  1831. table.remove();
  1832. clone.remove();
  1833. });
  1834. test("checkbox state (#3827)", function() {
  1835. expect( 9 );
  1836. var markup = jQuery("<div><input type=checkbox><div>").appendTo("#qunit-fixture"),
  1837. cb = markup.find("input")[0];
  1838. jQuery(cb).on( "click", function(){
  1839. equal( this.checked, false, "just-clicked checkbox is not checked" );
  1840. });
  1841. markup.on( "click", function(){
  1842. equal( cb.checked, false, "checkbox is not checked in bubbled event" );
  1843. });
  1844. // Native click
  1845. cb.checked = true;
  1846. equal( cb.checked, true, "native - checkbox is initially checked" );
  1847. cb.click();
  1848. equal( cb.checked, false, "native - checkbox is no longer checked" );
  1849. // jQuery click
  1850. cb.checked = true;
  1851. equal( cb.checked, true, "jQuery - checkbox is initially checked" );
  1852. jQuery( cb ).trigger("click");
  1853. equal( cb.checked, false, "jQuery - checkbox is no longer checked" );
  1854. // Handlers only; checkbox state remains false
  1855. jQuery( cb ).triggerHandler( "click" );
  1856. });
  1857. test("focus-blur order (#12868)", function() {
  1858. expect( 5 );
  1859. var $text = jQuery("#text1"),
  1860. $radio = jQuery("#radio1").trigger("focus"),
  1861. order;
  1862. // IE6-10 fire focus/blur events asynchronously; this is the resulting mess.
  1863. // IE's browser window must be topmost for this to work properly!!
  1864. stop();
  1865. $radio[0].focus();
  1866. setTimeout( function() {
  1867. $text
  1868. .on( "focus", function(){
  1869. equal( order++, 1, "text focus" );
  1870. })
  1871. .on( "blur", function(){
  1872. equal( order++, 0, "text blur" );
  1873. });
  1874. $radio
  1875. .on( "focus", function(){
  1876. equal( order++, 1, "radio focus" );
  1877. })
  1878. .on( "blur", function(){
  1879. equal( order++, 0, "radio blur" );
  1880. });
  1881. // Enabled input getting focus
  1882. order = 0;
  1883. equal( document.activeElement, $radio[0], "radio has focus" );
  1884. $text.trigger("focus");
  1885. setTimeout( function() {
  1886. equal( document.activeElement, $text[0], "text has focus" );
  1887. // Run handlers without native method on an input
  1888. order = 1;
  1889. $radio.triggerHandler( "focus" );
  1890. start();
  1891. }, 50 );
  1892. }, 50 );
  1893. });
  1894. test("hover event no longer special since 1.9", function() {
  1895. expect( 1 );
  1896. jQuery("<div>craft</div>")
  1897. .on( "hover", function( e ) {
  1898. equal( e.type, "hover", "I am hovering!" );
  1899. })
  1900. .trigger("hover")
  1901. .off("hover");
  1902. });
  1903. test("fixHooks extensions", function() {
  1904. expect( 2 );
  1905. // IE requires focusable elements to be visible, so append to body
  1906. var $fixture = jQuery( "<input type='text' id='hook-fixture' />" ).appendTo( "body" ),
  1907. saved = jQuery.event.fixHooks.click;
  1908. // Ensure the property doesn't exist
  1909. $fixture.bind( "click", function( event ) {
  1910. ok( !("blurrinessLevel" in event), "event.blurrinessLevel does not exist" );
  1911. });
  1912. fireNative( $fixture[0], "click" );
  1913. $fixture.unbind( "click" );
  1914. jQuery.event.fixHooks.click = {
  1915. filter: function( event, originalEvent ) {
  1916. event.blurrinessLevel = 42;
  1917. return event;
  1918. }
  1919. };
  1920. // Trigger a native click and ensure the property is set
  1921. $fixture.bind( "click", function( event ) {
  1922. equal( event.blurrinessLevel, 42, "event.blurrinessLevel was set" );
  1923. });
  1924. fireNative( $fixture[0], "click" );
  1925. delete jQuery.event.fixHooks.click;
  1926. $fixture.unbind( "click" ).remove();
  1927. jQuery.event.fixHooks.click = saved;
  1928. });
  1929. testIframeWithCallback( "jQuery.ready promise", "event/promiseReady.html", function( isOk ) {
  1930. expect(1);
  1931. ok( isOk, "$.when( $.ready ) works" );
  1932. });
  1933. // need PHP here to make the incepted IFRAME hang
  1934. if ( hasPHP ) {
  1935. testIframeWithCallback( "jQuery.ready synchronous load with long loading subresources", "event/syncReady.html", function( isOk ) {
  1936. expect(1);
  1937. ok( isOk, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
  1938. });
  1939. }
  1940. (function(){
  1941. // This code must be run before DOM ready!
  1942. var notYetReady, noEarlyExecution,
  1943. order = [],
  1944. args = {};
  1945. notYetReady = !jQuery.isReady;
  1946. test("jQuery.isReady", function() {
  1947. expect(2);
  1948. equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready");
  1949. equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready");
  1950. });
  1951. // Create an event handler.
  1952. function makeHandler( testId ) {
  1953. // When returned function is executed, push testId onto `order` array
  1954. // to ensure execution order. Also, store event handler arg to ensure
  1955. // the correct arg is being passed into the event handler.
  1956. return function( arg ) {
  1957. order.push(testId);
  1958. args[testId] = arg;
  1959. };
  1960. }
  1961. // Bind to the ready event in every possible way.
  1962. jQuery(makeHandler("a"));
  1963. jQuery(document).ready(makeHandler("b"));
  1964. jQuery(document).bind("ready.readytest", makeHandler("c"));
  1965. // Do it twice, just to be sure.
  1966. jQuery(makeHandler("d"));
  1967. jQuery(document).ready(makeHandler("e"));
  1968. jQuery(document).bind("ready.readytest", makeHandler("f"));
  1969. noEarlyExecution = order.length === 0;
  1970. // This assumes that QUnit tests are run on DOM ready!
  1971. test("jQuery ready", function() {
  1972. expect(10);
  1973. ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready");
  1974. // Ensure execution order.
  1975. 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");
  1976. // Ensure handler argument is correct.
  1977. equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
  1978. equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
  1979. ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).bind( 'ready', fn ) should be an event object");
  1980. order = [];
  1981. // Now that the ready event has fired, again bind to the ready event
  1982. // in every possible way. These event handlers should execute immediately.
  1983. jQuery(makeHandler("g"));
  1984. equal(order.pop(), "g", "Event handler should execute immediately");
  1985. equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
  1986. jQuery(document).ready(makeHandler("h"));
  1987. equal(order.pop(), "h", "Event handler should execute immediately");
  1988. equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
  1989. jQuery(document).bind("ready.readytest", makeHandler("never"));
  1990. equal(order.length, 0, "Event handler should never execute since DOM ready has already passed");
  1991. // Cleanup.
  1992. jQuery(document).unbind("ready.readytest");
  1993. });
  1994. })();
  1995. test("change handler should be detached from element", function() {
  1996. expect( 2 );
  1997. var $fixture = jQuery( "<input type='text' id='change-ie-leak' />" ).appendTo( "body" );
  1998. var originRemoveEvent = jQuery.removeEvent;
  1999. var wrapperRemoveEvent = function(elem, type, handle){
  2000. equal("change", type, "Event handler for 'change' event should be removed");
  2001. equal("change-ie-leak", jQuery(elem).attr("id"), "Event handler for 'change' event should be removed from appropriate element");
  2002. originRemoveEvent(elem, type, handle);
  2003. };
  2004. jQuery.removeEvent = wrapperRemoveEvent ;
  2005. $fixture.bind( "change", function( event ) {});
  2006. $fixture.unbind( "change" );
  2007. $fixture.remove();
  2008. jQuery.removeEvent = originRemoveEvent;
  2009. });
  2010. asyncTest("trigger click on checkbox, fires change event", function() {
  2011. expect(1);
  2012. var check = jQuery("#check2");
  2013. check.on( "change", function() {
  2014. // get it?
  2015. check.off("change");
  2016. ok( true, "Change event fired as a result of triggered click" );
  2017. start();
  2018. }).trigger("click");
  2019. });
  2020. test( "Namespace preserved when passed an Event (#12739)", function() {
  2021. expect( 4 );
  2022. var markup = jQuery(
  2023. "<div id='parent'><div id='child'></div></div>"
  2024. ),
  2025. triggered = 0,
  2026. fooEvent;
  2027. markup.find("div")
  2028. .addBack()
  2029. .on( "foo.bar", function( e ) {
  2030. if ( !e.handled ) {
  2031. triggered++;
  2032. e.handled = true;
  2033. equal( e.namespace, "bar", "namespace is bar" );
  2034. jQuery( e.target ).find("div").each(function() {
  2035. jQuery( this ).triggerHandler( e );
  2036. });
  2037. }
  2038. })
  2039. .on( "foo.bar2", function( e ) {
  2040. ok( false, "foo.bar2 called on trigger " + triggered + " id " + this.id );
  2041. });
  2042. markup.trigger("foo.bar");
  2043. markup.trigger( jQuery.Event("foo.bar") );
  2044. fooEvent = jQuery.Event("foo");
  2045. fooEvent.namespace = "bar";
  2046. markup.trigger( fooEvent );
  2047. markup.remove();
  2048. equal( triggered, 3, "foo.bar triggered" );
  2049. });
  2050. test( "make sure events cloned correctly", 18, function() {
  2051. var clone,
  2052. fixture = jQuery("#qunit-fixture"),
  2053. checkbox = jQuery("#check1"),
  2054. p = jQuery("#firstp");
  2055. fixture.on( "click change", function( event, result ) {
  2056. ok( result, event.type + " on original element is fired" );
  2057. }).on( "click", "#firstp", function( event, result ) {
  2058. ok( result, "Click on original child element though delegation is fired" );
  2059. }).on( "change", "#check1", function( event, result ) {
  2060. ok( result, "Change on original child element though delegation is fired" );
  2061. });
  2062. p.on("click", function( event, result ) {
  2063. ok( true, "Click on original child element is fired" );
  2064. });
  2065. checkbox.on("change", function( event, result ) {
  2066. ok( true, "Change on original child element is fired" );
  2067. });
  2068. fixture.clone().trigger("click").trigger("change"); // 0 events should be fired
  2069. clone = fixture.clone( true );
  2070. clone.find("p:first").trigger( "click", true ); // 3 events should fire
  2071. clone.find("#check1").trigger( "change", true ); // 3 events should fire
  2072. clone.remove();
  2073. clone = fixture.clone( true, true );
  2074. clone.find("p:first").trigger( "click", true ); // 3 events should fire
  2075. clone.find("#check1").trigger( "change", true ); // 3 events should fire
  2076. fixture.off();
  2077. p.off();
  2078. checkbox.off();
  2079. p.trigger("click"); // 0 should be fired
  2080. checkbox.trigger("change"); // 0 should be fired
  2081. clone.find("p:first").trigger( "click", true ); // 3 events should fire
  2082. clone.find("#check1").trigger( "change", true ); // 3 events should fire
  2083. clone.remove();
  2084. clone.find("p:first").trigger("click"); // 0 should be fired
  2085. clone.find("#check1").trigger("change"); // 0 events should fire
  2086. });
  2087. test( "Check order of focusin/focusout events", 2, function() {
  2088. var focus, blur,
  2089. input = jQuery("#name");
  2090. input.on("focus", function() {
  2091. focus = true;
  2092. }).on("focusin", function() {
  2093. ok( !focus, "Focusin event should fire before focus does" );
  2094. }).on("blur", function() {
  2095. blur = true;
  2096. }).on("focusout", function() {
  2097. ok( !blur, "Focusout event should fire before blur does" );
  2098. });
  2099. // gain focus
  2100. input.trigger("focus");
  2101. // then lose it
  2102. jQuery("#search").trigger("focus");
  2103. // cleanup
  2104. input.off();
  2105. });
  2106. test( "String.prototype.namespace does not cause trigger() to throw (#13360)", function() {
  2107. expect( 1 );
  2108. var errored = false;
  2109. String.prototype.namespace = function() {};
  2110. try {
  2111. jQuery("<p>").trigger("foo.bar");
  2112. } catch( e ) {
  2113. errored = true;
  2114. }
  2115. equal( errored, false, "trigger() did not throw exception" );
  2116. delete String.prototype.namespace;
  2117. });