Нет описания

event.js 98KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339
  1. QUnit.module( "event", {
  2. beforeEach: function() {
  3. document.body.focus();
  4. },
  5. afterEach: moduleTeardown
  6. } );
  7. QUnit.test( "null or undefined handler", function( assert ) {
  8. assert.expect( 4 );
  9. // Supports Fixes bug #7229
  10. try {
  11. jQuery( "#firstp" ).on( "click", null );
  12. assert.ok( true, "Passing a null handler will not throw an exception" );
  13. } catch ( e ) {}
  14. try {
  15. jQuery( "#firstp" ).on( "click", undefined );
  16. assert.ok( true, "Passing an undefined handler will not throw an exception" );
  17. } catch ( e ) {}
  18. var expectedElem = jQuery( "#firstp" );
  19. var actualElem = expectedElem.on( "click", null );
  20. assert.equal( actualElem, expectedElem, "Passing a null handler should return the original element" );
  21. actualElem = expectedElem.on( "click", undefined );
  22. assert.equal( actualElem, expectedElem, "Passing a null handler should return the original element" );
  23. } );
  24. QUnit.test( "on() with non-null,defined data", function( assert ) {
  25. assert.expect( 2 );
  26. var handler = function( event, data ) {
  27. assert.equal( data, 0, "non-null, defined data (zero) is correctly passed" );
  28. };
  29. jQuery( "#foo" ).on( "foo.on", handler );
  30. jQuery( "div" ).on( "foo.delegate", "#foo", handler );
  31. jQuery( "#foo" ).trigger( "foo", 0 );
  32. jQuery( "#foo" ).off( "foo.on", handler );
  33. jQuery( "div" ).off( "foo.delegate", "#foo" );
  34. } );
  35. QUnit.test( "Handler changes and .trigger() order", function( assert ) {
  36. assert.expect( 1 );
  37. var markup = jQuery(
  38. "<div><div><p><span><b class=\"a\">b</b></span></p></div></div>"
  39. ),
  40. path = "";
  41. markup
  42. .find( "*" ).addBack().on( "click", function() {
  43. path += this.nodeName.toLowerCase() + " ";
  44. } )
  45. .filter( "b" ).on( "click", function( e ) {
  46. // Removing span should not stop propagation to original parents
  47. if ( e.target === this ) {
  48. jQuery( this ).parent().remove();
  49. }
  50. } );
  51. markup.find( "b" ).trigger( "click" );
  52. assert.equal( path, "b p div div ", "Delivered all events" );
  53. markup.remove();
  54. } );
  55. QUnit.test( "on(), with data", function( assert ) {
  56. assert.expect( 4 );
  57. var test, handler, handler2;
  58. handler = function( event ) {
  59. assert.ok( event.data, "on() with data, check passed data exists" );
  60. assert.equal( event.data.foo, "bar", "on() with data, Check value of passed data" );
  61. };
  62. jQuery( "#firstp" ).on( "click", { "foo": "bar" }, handler ).trigger( "click" ).off( "click", handler );
  63. assert.ok( !jQuery._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using data." );
  64. test = function() {};
  65. handler2 = function( event ) {
  66. assert.equal( event.data, test, "on() with function data, Check value of passed data" );
  67. };
  68. jQuery( "#firstp" ).on( "click", test, handler2 ).trigger( "click" ).off( "click", handler2 );
  69. } );
  70. QUnit.test( "click(), with data", function( assert ) {
  71. assert.expect( 3 );
  72. var handler = function( event ) {
  73. assert.ok( event.data, "on() with data, check passed data exists" );
  74. assert.equal( event.data.foo, "bar", "on() with data, Check value of passed data" );
  75. };
  76. jQuery( "#firstp" ).on( "click", { "foo": "bar" }, handler ).trigger( "click" ).off( "click", handler );
  77. assert.ok( !jQuery._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using data." );
  78. } );
  79. QUnit.test( "on(), with data, trigger with data", function( assert ) {
  80. assert.expect( 4 );
  81. var handler = function( event, data ) {
  82. assert.ok( event.data, "check passed data exists" );
  83. assert.equal( event.data.foo, "bar", "Check value of passed data" );
  84. assert.ok( data, "Check trigger data" );
  85. assert.equal( data.bar, "foo", "Check value of trigger data" );
  86. };
  87. jQuery( "#firstp" ).on( "click", { foo: "bar" }, handler ).trigger( "click", [ { bar: "foo" } ] ).off( "click", handler );
  88. } );
  89. QUnit.test( "on(), multiple events at once", function( assert ) {
  90. assert.expect( 2 );
  91. var handler,
  92. clickCounter = 0,
  93. mouseoverCounter = 0;
  94. handler = function( event ) {
  95. if ( event.type === "click" ) {
  96. clickCounter += 1;
  97. } else if ( event.type === "mouseover" ) {
  98. mouseoverCounter += 1;
  99. }
  100. };
  101. jQuery( "#firstp" ).on( "click mouseover", handler ).trigger( "click" ).trigger( "mouseover" );
  102. assert.equal( clickCounter, 1, "on() with multiple events at once" );
  103. assert.equal( mouseoverCounter, 1, "on() with multiple events at once" );
  104. } );
  105. QUnit.test( "on(), five events at once", function( assert ) {
  106. assert.expect( 1 );
  107. var count = 0,
  108. handler = function() {
  109. count++;
  110. };
  111. jQuery( "#firstp" ).on( "click mouseover foo bar baz", handler )
  112. .trigger( "click" ).trigger( "mouseover" )
  113. .trigger( "foo" ).trigger( "bar" )
  114. .trigger( "baz" );
  115. assert.equal( count, 5, "on() five events at once" );
  116. } );
  117. QUnit.test( "on(), multiple events at once and namespaces", function( assert ) {
  118. assert.expect( 7 );
  119. var cur, div,
  120. obj = {};
  121. div = jQuery( "<div></div>" ).on( "focusin.a", function( e ) {
  122. assert.equal( e.type, cur, "Verify right single event was fired." );
  123. } );
  124. cur = "focusin";
  125. div.trigger( "focusin.a" );
  126. // manually clean up detached elements
  127. div.remove();
  128. div = jQuery( "<div></div>" ).on( "click mouseover", obj, function( e ) {
  129. assert.equal( e.type, cur, "Verify right multi event was fired." );
  130. assert.equal( e.data, obj, "Make sure the data came in correctly." );
  131. } );
  132. cur = "click";
  133. div.trigger( "click" );
  134. cur = "mouseover";
  135. div.trigger( "mouseover" );
  136. // manually clean up detached elements
  137. div.remove();
  138. div = jQuery( "<div></div>" ).on( "focusin.a focusout.b", function( e ) {
  139. assert.equal( e.type, cur, "Verify right multi event was fired." );
  140. } );
  141. cur = "focusin";
  142. div.trigger( "focusin.a" );
  143. cur = "focusout";
  144. div.trigger( "focusout.b" );
  145. // manually clean up detached elements
  146. div.remove();
  147. } );
  148. QUnit.test( "on(), namespace with special add", function( assert ) {
  149. assert.expect( 27 );
  150. var i = 0,
  151. div = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" ).on( "test", function() {
  152. assert.ok( true, "Test event fired." );
  153. } );
  154. jQuery.event.special.test = {
  155. _default: function( e, data ) {
  156. assert.equal( e.type, "test", "Make sure we're dealing with a test event." );
  157. assert.ok( data, "And that trigger data was passed." );
  158. assert.strictEqual( e.target, div[ 0 ], "And that the target is correct." );
  159. assert.equal( this, window, "And that the context is correct." );
  160. },
  161. setup: function() {},
  162. teardown: function() {
  163. assert.ok( true, "Teardown called." );
  164. },
  165. add: function( handleObj ) {
  166. var handler = handleObj.handler;
  167. handleObj.handler = function( e ) {
  168. e.xyz = ++i;
  169. handler.apply( this, arguments );
  170. };
  171. },
  172. remove: function() {
  173. assert.ok( true, "Remove called." );
  174. }
  175. };
  176. div.on( "test.a", { x: 1 }, function( e ) {
  177. assert.ok( !!e.xyz, "Make sure that the data is getting passed through." );
  178. assert.equal( e.data[ "x" ], 1, "Make sure data is attached properly." );
  179. } );
  180. div.on( "test.b", { x: 2 }, function( e ) {
  181. assert.ok( !!e.xyz, "Make sure that the data is getting passed through." );
  182. assert.equal( e.data[ "x" ], 2, "Make sure data is attached properly." );
  183. } );
  184. // Should trigger 5
  185. div.trigger( "test", 33.33 );
  186. // Should trigger 2
  187. div.trigger( "test.a", "George Harrison" );
  188. // Should trigger 2
  189. div.trigger( "test.b", { year: 1982 } );
  190. // Should trigger 4
  191. div.off( "test" );
  192. div = jQuery( "<div></div>" ).on( "test", function() {
  193. assert.ok( true, "Test event fired." );
  194. } );
  195. // Should trigger 2
  196. div.appendTo( "#qunit-fixture" ).remove();
  197. delete jQuery.event.special.test;
  198. } );
  199. QUnit.test( "on(), no data", function( assert ) {
  200. assert.expect( 1 );
  201. var handler = function( event ) {
  202. assert.ok( !event.data, "Check that no data is added to the event object" );
  203. };
  204. jQuery( "#firstp" ).on( "click", handler ).trigger( "click" );
  205. } );
  206. QUnit.test( "on/one/off(Object)", function( assert ) {
  207. assert.expect( 6 );
  208. var $elem,
  209. clickCounter = 0,
  210. mouseoverCounter = 0;
  211. function handler( event ) {
  212. if ( event.type === "click" ) {
  213. clickCounter++;
  214. } else if ( event.type === "mouseover" ) {
  215. mouseoverCounter++;
  216. }
  217. }
  218. function handlerWithData( event ) {
  219. if ( event.type === "click" ) {
  220. clickCounter += event.data;
  221. } else if ( event.type === "mouseover" ) {
  222. mouseoverCounter += event.data;
  223. }
  224. }
  225. function trigger() {
  226. $elem.trigger( "click" ).trigger( "mouseover" );
  227. }
  228. $elem = jQuery( "#firstp" )
  229. // Regular bind
  230. .on( {
  231. "click":handler,
  232. "mouseover":handler
  233. } )
  234. // Bind with data
  235. .one( {
  236. "click":handlerWithData,
  237. "mouseover":handlerWithData
  238. }, 2 );
  239. trigger();
  240. assert.equal( clickCounter, 3, "on(Object)" );
  241. assert.equal( mouseoverCounter, 3, "on(Object)" );
  242. trigger();
  243. assert.equal( clickCounter, 4, "on(Object)" );
  244. assert.equal( mouseoverCounter, 4, "on(Object)" );
  245. jQuery( "#firstp" ).off( {
  246. "click":handler,
  247. "mouseover":handler
  248. } );
  249. trigger();
  250. assert.equal( clickCounter, 4, "on(Object)" );
  251. assert.equal( mouseoverCounter, 4, "on(Object)" );
  252. } );
  253. QUnit.test( "on/off(Object), on/off(Object, String)", function( assert ) {
  254. assert.expect( 6 );
  255. var events,
  256. clickCounter = 0,
  257. mouseoverCounter = 0,
  258. $p = jQuery( "#firstp" ),
  259. $a = $p.find( "a" ).eq( 0 );
  260. events = {
  261. "click": function( event ) {
  262. clickCounter += ( event.data || 1 );
  263. },
  264. "mouseover": function( event ) {
  265. mouseoverCounter += ( event.data || 1 );
  266. }
  267. };
  268. function trigger() {
  269. $a.trigger( "click" ).trigger( "mouseover" );
  270. }
  271. jQuery( document ).on( events, "#firstp a" );
  272. $p.on( events, "a", 2 );
  273. trigger();
  274. assert.equal( clickCounter, 3, "on" );
  275. assert.equal( mouseoverCounter, 3, "on" );
  276. $p.off( events, "a" );
  277. trigger();
  278. assert.equal( clickCounter, 4, "off" );
  279. assert.equal( mouseoverCounter, 4, "off" );
  280. jQuery( document ).off( events, "#firstp a" );
  281. trigger();
  282. assert.equal( clickCounter, 4, "off" );
  283. assert.equal( mouseoverCounter, 4, "off" );
  284. } );
  285. QUnit.test( "on immediate propagation", function( assert ) {
  286. assert.expect( 2 );
  287. var lastClick,
  288. $p = jQuery( "#firstp" ),
  289. $a = $p.find( "a" ).eq( 0 );
  290. lastClick = "";
  291. jQuery( document ).on( "click", "#firstp a", function( e ) {
  292. lastClick = "click1";
  293. e.stopImmediatePropagation();
  294. } );
  295. jQuery( document ).on( "click", "#firstp a", function() {
  296. lastClick = "click2";
  297. } );
  298. $a.trigger( "click" );
  299. assert.equal( lastClick, "click1", "on stopImmediatePropagation" );
  300. jQuery( document ).off( "click", "#firstp a" );
  301. lastClick = "";
  302. $p.on( "click", "a", function( e ) {
  303. lastClick = "click1";
  304. e.stopImmediatePropagation();
  305. } );
  306. $p.on( "click", "a", function() {
  307. lastClick = "click2";
  308. } );
  309. $a.trigger( "click" );
  310. assert.equal( lastClick, "click1", "on stopImmediatePropagation" );
  311. $p.off( "click", "**" );
  312. } );
  313. QUnit.test( "on bubbling, isDefaultPrevented, stopImmediatePropagation", function( assert ) {
  314. assert.expect( 3 );
  315. var $anchor2 = jQuery( "#anchor2" ),
  316. $main = jQuery( "#qunit-fixture" ),
  317. neverCallMe = function() {
  318. assert.ok( false, "immediate propagation should have been stopped" );
  319. },
  320. fakeClick = function( $jq ) {
  321. // Use a native click so we don't get jQuery simulated bubbling
  322. var e = document.createEvent( "MouseEvents" );
  323. e.initEvent( "click", true, true );
  324. $jq[ 0 ].dispatchEvent( e );
  325. };
  326. $anchor2.on( "click", function( e ) {
  327. e.preventDefault();
  328. } );
  329. $main.on( "click", "#foo", function( e ) {
  330. assert.equal( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
  331. } );
  332. fakeClick( $anchor2 );
  333. $anchor2.off( "click" );
  334. $main.off( "click", "**" );
  335. $anchor2.on( "click", function() {
  336. // Let the default action occur
  337. } );
  338. $main.on( "click", "#foo", function( e ) {
  339. assert.equal( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
  340. } );
  341. fakeClick( $anchor2 );
  342. $anchor2.off( "click" );
  343. $main.off( "click", "**" );
  344. $anchor2.on( "click", function( e ) {
  345. e.stopImmediatePropagation();
  346. assert.ok( true, "anchor was clicked and prop stopped" );
  347. } );
  348. $anchor2[ 0 ].addEventListener( "click", neverCallMe, false );
  349. fakeClick( $anchor2 );
  350. $anchor2[ 0 ].removeEventListener( "click", neverCallMe );
  351. } );
  352. QUnit.test( "triggered events stopPropagation() for natively-bound events", function( assert ) {
  353. assert.expect( 1 );
  354. var $button = jQuery( "#button" ),
  355. $parent = $button.parent(),
  356. neverCallMe = function() {
  357. assert.ok( false, "propagation should have been stopped" );
  358. },
  359. stopPropagationCallback = function( e ) {
  360. assert.ok( true, "propagation is stopped" );
  361. e.stopPropagation();
  362. };
  363. $parent[ 0 ].addEventListener( "click", neverCallMe );
  364. $button.on( "click", stopPropagationCallback );
  365. $button.trigger( "click" );
  366. $parent[ 0 ].removeEventListener( "click", neverCallMe );
  367. $button.off( "click", stopPropagationCallback );
  368. } );
  369. QUnit.test( "trigger() works with events that were previously stopped", function( assert ) {
  370. assert.expect( 0 );
  371. var $button = jQuery( "#button" ),
  372. $parent = $button.parent(),
  373. neverCallMe = function() {
  374. assert.ok( false, "propagation should have been stopped" );
  375. };
  376. $parent[ 0 ].addEventListener( "click", neverCallMe );
  377. $button.on( "click", neverCallMe );
  378. var clickEvent = jQuery.Event( "click" );
  379. clickEvent.stopPropagation();
  380. $button.trigger( clickEvent );
  381. $parent[ 0 ].removeEventListener( "click", neverCallMe );
  382. $button.off( "click", neverCallMe );
  383. } );
  384. QUnit.test( "on(), iframes", function( assert ) {
  385. assert.expect( 1 );
  386. // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
  387. var doc = jQuery( "#loadediframe" ).contents();
  388. jQuery( "div", doc ).on( "click", function() {
  389. assert.ok( true, "Binding to element inside iframe" );
  390. } ).trigger( "click" ).off( "click" );
  391. } );
  392. QUnit.test( "on(), trigger change on select", function( assert ) {
  393. assert.expect( 5 );
  394. var counter = 0;
  395. function selectOnChange( event ) {
  396. assert.equal( event.data, counter++, "Event.data is not a global event object" );
  397. }
  398. jQuery( "#form select" ).each( function( i ) {
  399. jQuery( this ).on( "change", i, selectOnChange );
  400. } ).trigger( "change" );
  401. } );
  402. QUnit.test( "on(), namespaced events, cloned events", function( assert ) {
  403. assert.expect( 18 );
  404. var firstp = jQuery( "#firstp" );
  405. firstp.on( "custom.test", function() {
  406. assert.ok( false, "Custom event triggered" );
  407. } );
  408. firstp.on( "click", function( e ) {
  409. assert.ok( true, "Normal click triggered" );
  410. assert.equal( e.type + e.namespace, "click", "Check that only click events trigger this fn" );
  411. } );
  412. firstp.on( "click.test", function( e ) {
  413. var check = "click";
  414. assert.ok( true, "Namespaced click triggered" );
  415. if ( e.namespace ) {
  416. check += "test";
  417. }
  418. assert.equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
  419. } );
  420. //clone(true) element to verify events are cloned correctly
  421. firstp = firstp.add( firstp.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp ) );
  422. // Trigger both bound fn (8)
  423. firstp.trigger( "click" );
  424. // Trigger one bound fn (4)
  425. firstp.trigger( "click.test" );
  426. // Remove only the one fn
  427. firstp.off( "click.test" );
  428. // Trigger the remaining fn (4)
  429. firstp.trigger( "click" );
  430. // Remove the remaining namespaced fn
  431. firstp.off( ".test" );
  432. // Try triggering the custom event (0)
  433. firstp.trigger( "custom" );
  434. // using contents will get comments regular, text, and comment nodes
  435. jQuery( "#nonnodes" ).contents().on( "tester", function() {
  436. assert.equal( this.nodeType, 1, "Check node,textnode,comment on just does real nodes" );
  437. } ).trigger( "tester" );
  438. // Make sure events stick with appendTo'd elements (which are cloned) #2027
  439. jQuery( "<a href='#fail' class='test'>test</a>" ).on( "click", function() { return false; } ).appendTo( "#qunit-fixture" );
  440. assert.ok( jQuery( "a.test" ).eq( 0 ).triggerHandler( "click" ) === false, "Handler is bound to appendTo'd elements" );
  441. } );
  442. QUnit.test( "on(), multi-namespaced events", function( assert ) {
  443. assert.expect( 6 );
  444. var order = [
  445. "click.test.abc",
  446. "click.test.abc",
  447. "click.test",
  448. "click.test.abc",
  449. "click.test",
  450. "custom.test2"
  451. ];
  452. function check( name, msg ) {
  453. assert.deepEqual( name, order.shift(), msg );
  454. }
  455. jQuery( "#firstp" ).on( "custom.test", function() {
  456. check( "custom.test", "Custom event triggered" );
  457. } );
  458. jQuery( "#firstp" ).on( "custom.test2", function() {
  459. check( "custom.test2", "Custom event triggered" );
  460. } );
  461. jQuery( "#firstp" ).on( "click.test", function() {
  462. check( "click.test", "Normal click triggered" );
  463. } );
  464. jQuery( "#firstp" ).on( "click.test.abc", function() {
  465. check( "click.test.abc", "Namespaced click triggered" );
  466. } );
  467. // Those would not trigger/off (#5303)
  468. jQuery( "#firstp" ).trigger( "click.a.test" );
  469. jQuery( "#firstp" ).off( "click.a.test" );
  470. // Trigger both bound fn (1)
  471. jQuery( "#firstp" ).trigger( "click.test.abc" );
  472. // Trigger one bound fn (1)
  473. jQuery( "#firstp" ).trigger( "click.abc" );
  474. // Trigger two bound fn (2)
  475. jQuery( "#firstp" ).trigger( "click.test" );
  476. // Remove only the one fn
  477. jQuery( "#firstp" ).off( "click.abc" );
  478. // Trigger the remaining fn (1)
  479. jQuery( "#firstp" ).trigger( "click" );
  480. // Remove the remaining fn
  481. jQuery( "#firstp" ).off( ".test" );
  482. // Trigger the remaining fn (1)
  483. jQuery( "#firstp" ).trigger( "custom" );
  484. } );
  485. QUnit.test( "namespace-only event binding is a no-op", function( assert ) {
  486. assert.expect( 2 );
  487. jQuery( "#firstp" )
  488. .on( ".whoops", function() {
  489. assert.ok( false, "called a namespace-only event" );
  490. } )
  491. .on( "whoops", function() {
  492. assert.ok( true, "called whoops" );
  493. } )
  494. .trigger( "whoops" ) // 1
  495. .off( ".whoops" )
  496. .trigger( "whoops" ) // 2
  497. .off( "whoops" );
  498. } );
  499. QUnit.test( "Empty namespace is ignored", function( assert ) {
  500. assert.expect( 1 );
  501. jQuery( "#firstp" )
  502. .on( "meow.", function( e ) {
  503. assert.equal( e.namespace, "", "triggered a namespace-less meow event" );
  504. } )
  505. .trigger( "meow." )
  506. .off( "meow." );
  507. } );
  508. QUnit.test( "on(), with same function", function( assert ) {
  509. assert.expect( 2 );
  510. var count = 0, func = function() {
  511. count++;
  512. };
  513. jQuery( "#liveHandlerOrder" ).on( "foo.bar", func ).on( "foo.zar", func );
  514. jQuery( "#liveHandlerOrder" ).trigger( "foo.bar" );
  515. assert.equal( count, 1, "Verify binding function with multiple namespaces." );
  516. jQuery( "#liveHandlerOrder" ).off( "foo.bar", func ).off( "foo.zar", func );
  517. jQuery( "#liveHandlerOrder" ).trigger( "foo.bar" );
  518. assert.equal( count, 1, "Verify that removing events still work." );
  519. } );
  520. QUnit.test( "on(), make sure order is maintained", function( assert ) {
  521. assert.expect( 1 );
  522. var elem = jQuery( "#firstp" ), log = [], check = [];
  523. jQuery.each( new Array( 100 ), function( i ) {
  524. elem.on( "click", function() {
  525. log.push( i );
  526. } );
  527. check.push( i );
  528. } );
  529. elem.trigger( "click" );
  530. assert.equal( log.join( "," ), check.join( "," ), "Make sure order was maintained." );
  531. elem.off( "click" );
  532. } );
  533. QUnit.test( "on(), with different this object", function( assert ) {
  534. assert.expect( 4 );
  535. var thisObject = { myThis: true },
  536. data = { myData: true },
  537. handler1 = function() {
  538. assert.equal( this, thisObject, "on() with different this object" );
  539. }.bind( thisObject ),
  540. handler2 = function( event ) {
  541. assert.equal( this, thisObject, "on() with different this object and data" );
  542. assert.equal( event.data, data, "on() with different this object and data" );
  543. }.bind( thisObject );
  544. jQuery( "#firstp" )
  545. .on( "click", handler1 ).trigger( "click" ).off( "click", handler1 )
  546. .on( "click", data, handler2 ).trigger( "click" ).off( "click", handler2 );
  547. assert.ok( !jQuery._data( jQuery( "#firstp" )[ 0 ], "events" ), "Event handler unbound when using different this object and data." );
  548. } );
  549. QUnit.test( "on(name, false), off(name, false)", function( assert ) {
  550. assert.expect( 3 );
  551. var main = 0;
  552. jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
  553. jQuery( "#ap" ).trigger( "click" );
  554. assert.equal( main, 1, "Verify that the trigger happened correctly." );
  555. main = 0;
  556. jQuery( "#ap" ).on( "click", false );
  557. jQuery( "#ap" ).trigger( "click" );
  558. assert.equal( main, 0, "Verify that no bubble happened." );
  559. main = 0;
  560. jQuery( "#ap" ).off( "click", false );
  561. jQuery( "#ap" ).trigger( "click" );
  562. assert.equal( main, 1, "Verify that the trigger happened correctly." );
  563. // manually clean up events from elements outside the fixture
  564. jQuery( "#qunit-fixture" ).off( "click" );
  565. } );
  566. QUnit.test( "on(name, selector, false), off(name, selector, false)", function( assert ) {
  567. assert.expect( 3 );
  568. var main = 0;
  569. jQuery( "#qunit-fixture" ).on( "click", "#ap", function() { main++; } );
  570. jQuery( "#ap" ).trigger( "click" );
  571. assert.equal( main, 1, "Verify that the trigger happened correctly." );
  572. main = 0;
  573. jQuery( "#ap" ).on( "click", "#groups", false );
  574. jQuery( "#groups" ).trigger( "click" );
  575. assert.equal( main, 0, "Verify that no bubble happened." );
  576. main = 0;
  577. jQuery( "#ap" ).off( "click", "#groups", false );
  578. jQuery( "#groups" ).trigger( "click" );
  579. assert.equal( main, 1, "Verify that the trigger happened correctly." );
  580. jQuery( "#qunit-fixture" ).off( "click", "#ap" );
  581. } );
  582. QUnit.test( "on()/trigger()/off() on plain object", function( assert ) {
  583. assert.expect( 7 );
  584. var events,
  585. obj = {};
  586. // Make sure it doesn't complain when no events are found
  587. jQuery( obj ).trigger( "test" );
  588. // Make sure it doesn't complain when no events are found
  589. jQuery( obj ).off( "test" );
  590. jQuery( obj ).on( {
  591. "test": function() {
  592. assert.ok( true, "Custom event run." );
  593. },
  594. "submit": function() {
  595. assert.ok( true, "Custom submit event run." );
  596. }
  597. } );
  598. events = jQuery._data( obj, "events" );
  599. assert.ok( events, "Object has events bound." );
  600. assert.equal( obj[ "events" ], undefined, "Events object on plain objects is not events" );
  601. assert.equal( obj.test, undefined, "Make sure that test event is not on the plain object." );
  602. assert.equal( obj.handle, undefined, "Make sure that the event handler is not on the plain object." );
  603. // Should trigger 1
  604. jQuery( obj ).trigger( "test" );
  605. jQuery( obj ).trigger( "submit" );
  606. jQuery( obj ).off( "test" );
  607. jQuery( obj ).off( "submit" );
  608. // Should trigger 0
  609. jQuery( obj ).trigger( "test" );
  610. // Make sure it doesn't complain when no events are found
  611. jQuery( obj ).off( "test" );
  612. assert.equal( obj && obj[ jQuery.expando ] &&
  613. obj[ jQuery.expando ][ jQuery.expando ] &&
  614. obj[ jQuery.expando ][ jQuery.expando ][ "events" ], undefined, "Make sure events object is removed" );
  615. } );
  616. QUnit.test( "off(type)", function( assert ) {
  617. assert.expect( 1 );
  618. var message, func,
  619. $elem = jQuery( "#firstp" );
  620. function error() {
  621. assert.ok( false, message );
  622. }
  623. message = "unbind passing function";
  624. $elem.on( "error1", error ).off( "error1", error ).triggerHandler( "error1" );
  625. message = "unbind all from event";
  626. $elem.on( "error1", error ).off( "error1" ).triggerHandler( "error1" );
  627. message = "unbind all";
  628. $elem.on( "error1", error ).off().triggerHandler( "error1" );
  629. message = "unbind many with function";
  630. $elem.on( "error1 error2", error )
  631. .off( "error1 error2", error )
  632. .trigger( "error1" ).triggerHandler( "error2" );
  633. message = "unbind many"; // #3538
  634. $elem.on( "error1 error2", error )
  635. .off( "error1 error2" )
  636. .trigger( "error1" ).triggerHandler( "error2" );
  637. message = "unbind without a type or handler";
  638. $elem.on( "error1 error2.test", error )
  639. .off()
  640. .trigger( "error1" ).triggerHandler( "error2" );
  641. // Should only unbind the specified function
  642. jQuery( document ).on( "click", function() {
  643. assert.ok( true, "called handler after selective removal" );
  644. } );
  645. func = function() {};
  646. jQuery( document )
  647. .on( "click", func )
  648. .off( "click", func )
  649. .trigger( "click" )
  650. .off( "click" );
  651. } );
  652. QUnit.test( "off(eventObject)", function( assert ) {
  653. assert.expect( 4 );
  654. var $elem = jQuery( "#firstp" ),
  655. num;
  656. function check( expected ) {
  657. num = 0;
  658. $elem.trigger( "foo" ).triggerHandler( "bar" );
  659. assert.equal( num, expected, "Check the right handlers are triggered" );
  660. }
  661. $elem
  662. // This handler shouldn't be unbound
  663. .on( "foo", function() {
  664. num += 1;
  665. } )
  666. .on( "foo", function( e ) {
  667. $elem.off( e );
  668. num += 2;
  669. } )
  670. // Neither this one
  671. .on( "bar", function() {
  672. num += 4;
  673. } );
  674. check( 7 );
  675. check( 5 );
  676. $elem.off( "bar" );
  677. check( 1 );
  678. $elem.off();
  679. check( 0 );
  680. } );
  681. QUnit.test( "mouseover triggers mouseenter", function( assert ) {
  682. assert.expect( 1 );
  683. var count = 0,
  684. elem = jQuery( "<a></a>" );
  685. elem.on( "mouseenter", function() {
  686. count++;
  687. } );
  688. elem.trigger( "mouseover" );
  689. assert.equal( count, 1, "make sure mouseover triggers a mouseenter" );
  690. elem.remove();
  691. } );
  692. QUnit.test( "pointerover triggers pointerenter", function( assert ) {
  693. assert.expect( 1 );
  694. var count = 0,
  695. elem = jQuery( "<a></a>" );
  696. elem.on( "pointerenter", function() {
  697. count++;
  698. } );
  699. elem.trigger( "pointerover" );
  700. assert.equal( count, 1, "make sure pointerover triggers a pointerenter" );
  701. elem.remove();
  702. } );
  703. QUnit.test( "withinElement implemented with jQuery.contains()", function( assert ) {
  704. assert.expect( 1 );
  705. jQuery( "#qunit-fixture" ).append( "<div id='jc-outer'><div id='jc-inner'></div></div>" );
  706. jQuery( "#jc-outer" ).on( "mouseenter mouseleave", function( event ) {
  707. assert.equal( this.id, "jc-outer", this.id + " " + event.type );
  708. } );
  709. jQuery( "#jc-inner" ).trigger( "mouseenter" );
  710. } );
  711. QUnit.test( "mouseenter, mouseleave don't catch exceptions", function( assert ) {
  712. assert.expect( 2 );
  713. var elem = jQuery( "#firstp" ).on( "mouseenter mouseleave", function() {
  714. throw "an Exception";
  715. } );
  716. try {
  717. elem.trigger( "mouseenter" );
  718. } catch ( e ) {
  719. assert.equal( e, "an Exception", "mouseenter doesn't catch exceptions" );
  720. }
  721. try {
  722. elem.trigger( "mouseleave" );
  723. } catch ( e ) {
  724. assert.equal( e, "an Exception", "mouseleave doesn't catch exceptions" );
  725. }
  726. } );
  727. QUnit.test( "trigger() bubbling", function( assert ) {
  728. assert.expect( 18 );
  729. var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
  730. jQuery( window ).on( "click", function() { win++; } );
  731. jQuery( document ).on( "click", function( e ) { if ( e.target !== document ) { doc++; } } );
  732. jQuery( "html" ).on( "click", function() { html++; } );
  733. jQuery( "body" ).on( "click", function() { body++; } );
  734. jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
  735. jQuery( "#ap" ).on( "click", function() { ap++; return false; } );
  736. jQuery( "html" ).trigger( "click" );
  737. assert.equal( win, 1, "HTML bubble" );
  738. assert.equal( doc, 1, "HTML bubble" );
  739. assert.equal( html, 1, "HTML bubble" );
  740. jQuery( "body" ).trigger( "click" );
  741. assert.equal( win, 2, "Body bubble" );
  742. assert.equal( doc, 2, "Body bubble" );
  743. assert.equal( html, 2, "Body bubble" );
  744. assert.equal( body, 1, "Body bubble" );
  745. jQuery( "#qunit-fixture" ).trigger( "click" );
  746. assert.equal( win, 3, "Main bubble" );
  747. assert.equal( doc, 3, "Main bubble" );
  748. assert.equal( html, 3, "Main bubble" );
  749. assert.equal( body, 2, "Main bubble" );
  750. assert.equal( main, 1, "Main bubble" );
  751. jQuery( "#ap" ).trigger( "click" );
  752. assert.equal( doc, 3, "ap bubble" );
  753. assert.equal( html, 3, "ap bubble" );
  754. assert.equal( body, 2, "ap bubble" );
  755. assert.equal( main, 1, "ap bubble" );
  756. assert.equal( ap, 1, "ap bubble" );
  757. jQuery( document ).trigger( "click" );
  758. assert.equal( win, 4, "doc bubble" );
  759. // manually clean up events from elements outside the fixture
  760. jQuery( window ).off( "click" );
  761. jQuery( document ).off( "click" );
  762. jQuery( "html, body, #qunit-fixture" ).off( "click" );
  763. } );
  764. QUnit.test( "trigger(type, [data], [fn])", function( assert ) {
  765. assert.expect( 16 );
  766. var $elem, pass, form, elem2,
  767. handler = function( event, a, b, c ) {
  768. assert.equal( event.type, "click", "check passed data" );
  769. assert.equal( a, 1, "check passed data" );
  770. assert.equal( b, "2", "check passed data" );
  771. assert.equal( c, "abc", "check passed data" );
  772. return "test";
  773. };
  774. $elem = jQuery( "#firstp" );
  775. // Simulate a "native" click
  776. $elem[ 0 ].click = function() {
  777. assert.ok( true, "Native call was triggered" );
  778. };
  779. jQuery( document ).on( "mouseenter", "#firstp", function() {
  780. assert.ok( true, "Trigger mouseenter bound by on" );
  781. } );
  782. jQuery( document ).on( "mouseleave", "#firstp", function() {
  783. assert.ok( true, "Trigger mouseleave bound by on" );
  784. } );
  785. $elem.trigger( "mouseenter" );
  786. $elem.trigger( "mouseleave" );
  787. jQuery( document ).off( "mouseenter mouseleave", "#firstp" );
  788. // Triggers handlers and native
  789. // Trigger 5
  790. $elem.on( "click", handler ).trigger( "click", [ 1, "2", "abc" ] );
  791. // Simulate a "native" click
  792. $elem[ 0 ].click = function() {
  793. assert.ok( false, "Native call was triggered" );
  794. };
  795. // Trigger only the handlers (no native)
  796. // Triggers 5
  797. assert.equal( $elem.triggerHandler( "click", [ 1, "2", "abc" ] ), "test", "Verify handler response" );
  798. pass = true;
  799. try {
  800. elem2 = jQuery( "#form input" ).eq( 0 );
  801. elem2.get( 0 ).style.display = "none";
  802. elem2.trigger( "focus" );
  803. } catch ( e ) {
  804. pass = false;
  805. }
  806. assert.ok( pass, "Trigger focus on hidden element" );
  807. pass = true;
  808. try {
  809. jQuery( "#qunit-fixture table" ).eq( 0 ).on( "test:test", function() {} ).trigger( "test:test" );
  810. } catch ( e ) {
  811. pass = false;
  812. }
  813. assert.ok( pass, "Trigger on a table with a colon in the even type, see #3533" );
  814. form = jQuery( "<form action=''></form>" ).appendTo( "body" );
  815. // Make sure it can be prevented locally
  816. form.on( "submit", function() {
  817. assert.ok( true, "Local `on` still works." );
  818. return false;
  819. } );
  820. // Trigger 1
  821. form.trigger( "submit" );
  822. form.off( "submit" );
  823. jQuery( document ).on( "submit", function() {
  824. assert.ok( true, "Make sure bubble works up to document." );
  825. return false;
  826. } );
  827. // Trigger 1
  828. form.trigger( "submit" );
  829. jQuery( document ).off( "submit" );
  830. form.remove();
  831. } );
  832. QUnit.test( "submit event bubbles on copied forms (#11649)", function( assert ) {
  833. assert.expect( 3 );
  834. var $formByClone, $formByHTML,
  835. $testForm = jQuery( "#testForm" ),
  836. $fixture = jQuery( "#qunit-fixture" ),
  837. $wrapperDiv = jQuery( "<div></div>" ).appendTo( $fixture );
  838. function noSubmit( e ) {
  839. e.preventDefault();
  840. }
  841. function delegatedSubmit() {
  842. assert.ok( true, "Make sure submit event bubbles up." );
  843. return false;
  844. }
  845. // Attach a delegated submit handler to the parent element
  846. $fixture.on( "submit", "form", delegatedSubmit );
  847. // Trigger form submission to introduce the _submit_attached property
  848. $testForm.on( "submit", noSubmit ).find( "input[name=sub1]" ).trigger( "click" );
  849. // Copy the form via .clone() and .html()
  850. $formByClone = $testForm.clone( true, true ).removeAttr( "id" );
  851. $formByHTML = jQuery( jQuery.parseHTML( $fixture.html() ) ).filter( "#testForm" ).removeAttr( "id" );
  852. $wrapperDiv.append( $formByClone, $formByHTML );
  853. // Check submit bubbling on the copied forms
  854. $wrapperDiv.find( "form" ).on( "submit", noSubmit ).find( "input[name=sub1]" ).trigger( "click" );
  855. // Clean up
  856. $wrapperDiv.remove();
  857. $fixture.off( "submit", "form", delegatedSubmit );
  858. $testForm.off( "submit", noSubmit );
  859. } );
  860. QUnit.test( "change event bubbles on copied forms (#11796)", function( assert ) {
  861. assert.expect( 3 );
  862. var $formByClone, $formByHTML,
  863. $form = jQuery( "#form" ),
  864. $fixture = jQuery( "#qunit-fixture" ),
  865. $wrapperDiv = jQuery( "<div></div>" ).appendTo( $fixture );
  866. function delegatedChange() {
  867. assert.ok( true, "Make sure change event bubbles up." );
  868. return false;
  869. }
  870. // Attach a delegated change handler to the form
  871. $fixture.on( "change", "form", delegatedChange );
  872. // Trigger change event to introduce the _change_attached property
  873. $form.find( "select[name=select1]" ).val( "1" ).trigger( "change" );
  874. // Copy the form via .clone() and .html()
  875. $formByClone = $form.clone( true, true ).removeAttr( "id" );
  876. $formByHTML = jQuery( jQuery.parseHTML( $fixture.html() ) ).filter( "#form" ).removeAttr( "id" );
  877. $wrapperDiv.append( $formByClone, $formByHTML );
  878. // Check change bubbling on the copied forms
  879. $wrapperDiv.find( "form select[name=select1]" ).val( "2" ).trigger( "change" );
  880. // Clean up
  881. $wrapperDiv.remove();
  882. $fixture.off( "change", "form", delegatedChange );
  883. } );
  884. QUnit.test( "trigger(eventObject, [data], [fn])", function( assert ) {
  885. assert.expect( 28 );
  886. var event,
  887. $parent = jQuery( "<div id='par'></div>" ).appendTo( "body" ),
  888. $child = jQuery( "<p id='child'>foo</p>" ).appendTo( $parent );
  889. $parent.get( 0 ).style.display = "none";
  890. event = jQuery.Event( "noNew" );
  891. assert.ok( event !== window, "Instantiate jQuery.Event without the 'new' keyword" );
  892. assert.equal( event.type, "noNew", "Verify its type" );
  893. assert.equal( event.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
  894. assert.equal( event.isPropagationStopped(), false, "Verify isPropagationStopped" );
  895. assert.equal( event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
  896. event.preventDefault();
  897. assert.equal( event.isDefaultPrevented(), true, "Verify isDefaultPrevented" );
  898. event.stopPropagation();
  899. assert.equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
  900. event.isPropagationStopped = function() { return false; };
  901. event.stopImmediatePropagation();
  902. assert.equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
  903. assert.equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
  904. $parent.on( "foo", function( e ) {
  905. // Tries bubbling
  906. assert.equal( e.type, "foo", "Verify event type when passed passing an event object" );
  907. assert.equal( e.target.id, "child", "Verify event.target when passed passing an event object" );
  908. assert.equal( e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object" );
  909. assert.equal( e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object" );
  910. } );
  911. // test with an event object
  912. event = new jQuery.Event( "foo" );
  913. event.secret = "boo!";
  914. $child.trigger( event );
  915. // test with a literal object
  916. $child.trigger( { "type": "foo", "secret": "boo!" } );
  917. $parent.off();
  918. function error() {
  919. assert.ok( false, "This assertion shouldn't be reached" );
  920. }
  921. $parent.on( "foo", error );
  922. $child.on( "foo", function( e, a, b, c ) {
  923. assert.equal( arguments.length, 4, "Check arguments length" );
  924. assert.equal( a, 1, "Check first custom argument" );
  925. assert.equal( b, 2, "Check second custom argument" );
  926. assert.equal( c, 3, "Check third custom argument" );
  927. assert.equal( e.isDefaultPrevented(), false, "Verify isDefaultPrevented" );
  928. assert.equal( e.isPropagationStopped(), false, "Verify isPropagationStopped" );
  929. assert.equal( e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped" );
  930. // Skips both errors
  931. e.stopImmediatePropagation();
  932. return "result";
  933. } );
  934. // We should add this back in when we want to test the order
  935. // in which event handlers are iterated.
  936. //$child.on("foo", error );
  937. event = new jQuery.Event( "foo" );
  938. $child.trigger( event, [ 1, 2, 3 ] ).off();
  939. assert.equal( event.result, "result", "Check event.result attribute" );
  940. // Will error if it bubbles
  941. $child.triggerHandler( "foo" );
  942. $child.off();
  943. $parent.off().remove();
  944. // Ensure triggerHandler doesn't molest its event object (#xxx)
  945. event = jQuery.Event( "zowie" );
  946. jQuery( document ).triggerHandler( event );
  947. assert.equal( event.type, "zowie", "Verify its type" );
  948. assert.equal( event.isPropagationStopped(), false, "propagation not stopped" );
  949. assert.equal( event.isDefaultPrevented(), false, "default not prevented" );
  950. } );
  951. QUnit.test( ".trigger() bubbling on disconnected elements (#10489)", function( assert ) {
  952. assert.expect( 2 );
  953. jQuery( window ).on( "click", function() {
  954. assert.ok( false, "click fired on window" );
  955. } );
  956. jQuery( "<div><p>hi</p></div>" )
  957. .on( "click", function() {
  958. assert.ok( true, "click fired on div" );
  959. } )
  960. .find( "p" )
  961. .on( "click", function() {
  962. assert.ok( true, "click fired on p" );
  963. } )
  964. .trigger( "click" )
  965. .off( "click" )
  966. .end()
  967. .off( "click" )
  968. .remove();
  969. jQuery( window ).off( "click" );
  970. } );
  971. QUnit.test( ".trigger() doesn't bubble load event (#10717)", function( assert ) {
  972. assert.expect( 1 );
  973. jQuery( window ).on( "load", function() {
  974. assert.ok( false, "load fired on window" );
  975. } );
  976. jQuery( "<img src='" + baseURL + "1x1.jpg' />" )
  977. .appendTo( "body" )
  978. .on( "load", function() {
  979. assert.ok( true, "load fired on img" );
  980. } )
  981. .trigger( "load" )
  982. .remove();
  983. jQuery( window ).off( "load" );
  984. } );
  985. QUnit.test( "Delegated events in SVG (#10791; #13180)", function( assert ) {
  986. assert.expect( 2 );
  987. var useElem, e,
  988. svg = jQuery(
  989. "<svg height='1' version='1.1' width='1' xmlns='http://www.w3.org/2000/svg'>" +
  990. "<defs><rect id='ref' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect></defs>" +
  991. "<rect class='svg-by-class' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
  992. "<rect id='svg-by-id' x='10' y='20' width='100' height='60' r='10' rx='10' ry='10'></rect>" +
  993. "<use id='use' xlink:href='#ref'></use>" +
  994. "</svg>"
  995. );
  996. jQuery( "#qunit-fixture" )
  997. .append( svg )
  998. .on( "click", "#svg-by-id", function() {
  999. assert.ok( true, "delegated id selector" );
  1000. } )
  1001. .on( "click", "[class~='svg-by-class']", function() {
  1002. assert.ok( true, "delegated class selector" );
  1003. } )
  1004. .find( "#svg-by-id, [class~='svg-by-class']" )
  1005. .trigger( "click" )
  1006. .end();
  1007. // Fire a native click on an SVGElementInstance (the instance tree of an SVG <use>)
  1008. // to confirm that it doesn't break our event delegation handling (#13180)
  1009. useElem = svg.find( "#use" )[ 0 ];
  1010. if ( document.createEvent && useElem && useElem.instanceRoot ) {
  1011. e = document.createEvent( "MouseEvents" );
  1012. e.initEvent( "click", true, true );
  1013. useElem.instanceRoot.dispatchEvent( e );
  1014. }
  1015. jQuery( "#qunit-fixture" ).off( "click" );
  1016. } );
  1017. QUnit.test( "Delegated events with malformed selectors (gh-3071)", function( assert ) {
  1018. assert.expect( 3 );
  1019. assert.throws( function() {
  1020. jQuery( "#foo" ).on( "click", ":not", function() {} );
  1021. }, "malformed selector throws on attach" );
  1022. assert.throws( function() {
  1023. jQuery( "#foo" ).on( "click", "nonexistent:not", function() {} );
  1024. }, "short-circuitable malformed selector throws on attach" );
  1025. jQuery( "#foo > :first-child" ).trigger( "click" );
  1026. assert.ok( true, "malformed selector does not throw on event" );
  1027. } );
  1028. QUnit.test( "Delegated events in forms (#10844; #11145; #8165; #11382, #11764)", function( assert ) {
  1029. assert.expect( 5 );
  1030. // Alias names like "id" cause havoc
  1031. var form = jQuery(
  1032. "<form id='myform'>" +
  1033. "<input type='text' name='id' value='secret agent man' />" +
  1034. "</form>"
  1035. )
  1036. .on( "submit", function( event ) {
  1037. event.preventDefault();
  1038. } )
  1039. .appendTo( "body" );
  1040. jQuery( "body" )
  1041. .on( "submit", "#myform", function() {
  1042. assert.ok( true, "delegated id selector with aliased id" );
  1043. } )
  1044. .find( "#myform" )
  1045. .trigger( "submit" )
  1046. .end()
  1047. .off( "submit" );
  1048. form.append( "<input type='text' name='disabled' value='differently abled' />" );
  1049. jQuery( "body" )
  1050. .on( "submit", "#myform", function() {
  1051. assert.ok( true, "delegated id selector with aliased disabled" );
  1052. } )
  1053. .find( "#myform" )
  1054. .trigger( "submit" )
  1055. .end()
  1056. .off( "submit" );
  1057. form
  1058. .append( "<button id='nestyDisabledBtn'><span>Zing</span></button>" )
  1059. .on( "click", "#nestyDisabledBtn", function() {
  1060. assert.ok( true, "click on enabled/disabled button with nesty elements" );
  1061. } )
  1062. .on( "mouseover", "#nestyDisabledBtn", function() {
  1063. assert.ok( true, "mouse on enabled/disabled button with nesty elements" );
  1064. } )
  1065. .find( "span" )
  1066. .trigger( "click" ) // yep
  1067. .trigger( "mouseover" ) // yep
  1068. .end()
  1069. .find( "#nestyDisabledBtn" ).prop( "disabled", true ).end()
  1070. .find( "span" )
  1071. .trigger( "click" ) // nope
  1072. .trigger( "mouseover" ) // yep
  1073. .end()
  1074. .off( "click" );
  1075. form.remove();
  1076. } );
  1077. QUnit.test( "Submit event can be stopped (#11049)", function( assert ) {
  1078. assert.expect( 1 );
  1079. // Since we manually bubble in IE, make sure inner handlers get a chance to cancel
  1080. var form = jQuery(
  1081. "<form id='myform'>" +
  1082. "<input type='text' name='sue' value='bawls' />" +
  1083. "<input type='submit' />" +
  1084. "</form>"
  1085. )
  1086. .appendTo( "body" );
  1087. jQuery( "body" )
  1088. .on( "submit", function() {
  1089. assert.ok( true, "submit bubbled on first handler" );
  1090. return false;
  1091. } )
  1092. .find( "#myform input[type=submit]" )
  1093. .each( function() { this.click(); } )
  1094. .end()
  1095. .on( "submit", function() {
  1096. assert.ok( false, "submit bubbled on second handler" );
  1097. return false;
  1098. } )
  1099. .find( "#myform input[type=submit]" )
  1100. .each( function() {
  1101. jQuery( this.form ).on( "submit", function( e ) {
  1102. e.preventDefault();
  1103. e.stopPropagation();
  1104. } );
  1105. this.click();
  1106. } )
  1107. .end()
  1108. .off( "submit" );
  1109. form.remove();
  1110. } );
  1111. // Support: iOS 7 - 9
  1112. // iOS has the window.onbeforeunload field but doesn't support the beforeunload
  1113. // handler making it impossible to feature-detect the support.
  1114. QUnit[ /(ipad|iphone|ipod)/i.test( navigator.userAgent ) ? "skip" : "test" ](
  1115. "on(beforeunload)", function( assert ) {
  1116. assert.expect( 1 );
  1117. var iframe = jQuery( jQuery.parseHTML( "<iframe src='" + baseURL + "event/onbeforeunload.html'><iframe>" ) );
  1118. var done = assert.async();
  1119. window.onmessage = function( event ) {
  1120. var payload = JSON.parse( event.data );
  1121. assert.ok( payload.event, "beforeunload", "beforeunload event" );
  1122. iframe.remove();
  1123. window.onmessage = null;
  1124. done();
  1125. };
  1126. iframe.appendTo( "#qunit-fixture" );
  1127. } );
  1128. QUnit.test( "jQuery.Event( type, props )", function( assert ) {
  1129. assert.expect( 6 );
  1130. var event = jQuery.Event( "keydown", { keyCode: 64 } ),
  1131. handler = function( event ) {
  1132. assert.ok( "keyCode" in event, "Special property 'keyCode' exists" );
  1133. assert.equal( event.keyCode, 64, "event.keyCode has explicit value '64'" );
  1134. };
  1135. // Supports jQuery.Event implementation
  1136. assert.equal( event.type, "keydown", "Verify type" );
  1137. // ensure "type" in props won't clobber the one set by constructor
  1138. assert.equal( jQuery.inArray( "type", jQuery.event.props ), -1, "'type' property not in props (#10375)" );
  1139. assert.ok( "keyCode" in event, "Special 'keyCode' property exists" );
  1140. assert.strictEqual( jQuery.isPlainObject( event ), false, "Instances of $.Event should not be identified as a plain object." );
  1141. jQuery( "body" ).on( "keydown", handler ).trigger( event );
  1142. jQuery( "body" ).off( "keydown" );
  1143. } );
  1144. QUnit.test( "jQuery.Event properties", function( assert ) {
  1145. assert.expect( 12 );
  1146. var handler,
  1147. $structure = jQuery( "<div id='ancestor'><p id='delegate'><span id='target'>shiny</span></p></div>" ),
  1148. $target = $structure.find( "#target" );
  1149. handler = function( e ) {
  1150. assert.strictEqual( e.currentTarget, this, "currentTarget at " + this.id );
  1151. assert.equal( e.isTrigger, 3, "trigger at " + this.id );
  1152. };
  1153. $structure.one( "click", handler );
  1154. $structure.one( "click", "p", handler );
  1155. $target.one( "click", handler );
  1156. $target[ 0 ].onclick = function( e ) {
  1157. assert.strictEqual( e.currentTarget, this, "currentTarget at target (native handler)" );
  1158. assert.equal( e.isTrigger, 3, "trigger at target (native handler)" );
  1159. };
  1160. $target.trigger( "click" );
  1161. $target.one( "click", function( e ) {
  1162. assert.equal( e.isTrigger, 2, "triggerHandler at target" );
  1163. } );
  1164. $target[ 0 ].onclick = function( e ) {
  1165. assert.equal( e.isTrigger, 2, "triggerHandler at target (native handler)" );
  1166. };
  1167. $target.triggerHandler( "click" );
  1168. handler = function( e ) {
  1169. assert.strictEqual( e.isTrigger, undefined, "native event at " + this.id );
  1170. };
  1171. $target.one( "click", handler );
  1172. $target[ 0 ].onclick = function( e ) {
  1173. assert.strictEqual( e.isTrigger, undefined, "native event at target (native handler)" );
  1174. };
  1175. fireNative( $target[ 0 ], "click" );
  1176. } );
  1177. QUnit.test( ".on()/.off()", function( assert ) {
  1178. assert.expect( 65 );
  1179. var event, clicked, hash, called, livec, lived, livee,
  1180. submit = 0, div = 0, livea = 0, liveb = 0;
  1181. jQuery( "#body" ).on( "submit", "#qunit-fixture div", function() { submit++; return false; } );
  1182. jQuery( "#body" ).on( "click", "#qunit-fixture div", function() { div++; } );
  1183. jQuery( "#body" ).on( "click", "div#nothiddendiv", function() { livea++; } );
  1184. jQuery( "#body" ).on( "click", "div#nothiddendivchild", function() { liveb++; } );
  1185. // Nothing should trigger on the body
  1186. jQuery( "body" ).trigger( "click" );
  1187. assert.equal( submit, 0, "Click on body" );
  1188. assert.equal( div, 0, "Click on body" );
  1189. assert.equal( livea, 0, "Click on body" );
  1190. assert.equal( liveb, 0, "Click on body" );
  1191. // This should trigger two events
  1192. submit = 0; div = 0; livea = 0; liveb = 0;
  1193. jQuery( "div#nothiddendiv" ).trigger( "click" );
  1194. assert.equal( submit, 0, "Click on div" );
  1195. assert.equal( div, 1, "Click on div" );
  1196. assert.equal( livea, 1, "Click on div" );
  1197. assert.equal( liveb, 0, "Click on div" );
  1198. // This should trigger three events (w/ bubbling)
  1199. submit = 0; div = 0; livea = 0; liveb = 0;
  1200. jQuery( "div#nothiddendivchild" ).trigger( "click" );
  1201. assert.equal( submit, 0, "Click on inner div" );
  1202. assert.equal( div, 2, "Click on inner div" );
  1203. assert.equal( livea, 1, "Click on inner div" );
  1204. assert.equal( liveb, 1, "Click on inner div" );
  1205. // This should trigger one submit
  1206. submit = 0; div = 0; livea = 0; liveb = 0;
  1207. jQuery( "div#nothiddendivchild" ).trigger( "submit" );
  1208. assert.equal( submit, 1, "Submit on div" );
  1209. assert.equal( div, 0, "Submit on div" );
  1210. assert.equal( livea, 0, "Submit on div" );
  1211. assert.equal( liveb, 0, "Submit on div" );
  1212. // Make sure no other events were removed in the process
  1213. submit = 0; div = 0; livea = 0; liveb = 0;
  1214. jQuery( "div#nothiddendivchild" ).trigger( "click" );
  1215. assert.equal( submit, 0, "off Click on inner div" );
  1216. assert.equal( div, 2, "off Click on inner div" );
  1217. assert.equal( livea, 1, "off Click on inner div" );
  1218. assert.equal( liveb, 1, "off Click on inner div" );
  1219. // Now make sure that the removal works
  1220. submit = 0; div = 0; livea = 0; liveb = 0;
  1221. jQuery( "#body" ).off( "click", "div#nothiddendivchild" );
  1222. jQuery( "div#nothiddendivchild" ).trigger( "click" );
  1223. assert.equal( submit, 0, "off Click on inner div" );
  1224. assert.equal( div, 2, "off Click on inner div" );
  1225. assert.equal( livea, 1, "off Click on inner div" );
  1226. assert.equal( liveb, 0, "off Click on inner div" );
  1227. // Make sure that the click wasn't removed too early
  1228. submit = 0; div = 0; livea = 0; liveb = 0;
  1229. jQuery( "div#nothiddendiv" ).trigger( "click" );
  1230. assert.equal( submit, 0, "off Click on inner div" );
  1231. assert.equal( div, 1, "off Click on inner div" );
  1232. assert.equal( livea, 1, "off Click on inner div" );
  1233. assert.equal( liveb, 0, "off Click on inner div" );
  1234. // Make sure that stopPropagation doesn't stop live events
  1235. submit = 0; div = 0; livea = 0; liveb = 0;
  1236. jQuery( "#body" ).on( "click", "div#nothiddendivchild", function( e ) { liveb++; e.stopPropagation(); } );
  1237. jQuery( "div#nothiddendivchild" ).trigger( "click" );
  1238. assert.equal( submit, 0, "stopPropagation Click on inner div" );
  1239. assert.equal( div, 1, "stopPropagation Click on inner div" );
  1240. assert.equal( livea, 0, "stopPropagation Click on inner div" );
  1241. assert.equal( liveb, 1, "stopPropagation Click on inner div" );
  1242. // Make sure click events only fire with primary click
  1243. submit = 0; div = 0; livea = 0; liveb = 0;
  1244. event = jQuery.Event( "click" );
  1245. event.button = 1;
  1246. jQuery( "div#nothiddendiv" ).trigger( event );
  1247. assert.equal( livea, 0, "on secondary click" );
  1248. jQuery( "#body" ).off( "click", "div#nothiddendivchild" );
  1249. jQuery( "#body" ).off( "click", "div#nothiddendiv" );
  1250. jQuery( "#body" ).off( "click", "#qunit-fixture div" );
  1251. jQuery( "#body" ).off( "submit", "#qunit-fixture div" );
  1252. // Test binding with a different context
  1253. clicked = 0;
  1254. jQuery( "#qunit-fixture" ).on( "click", "#foo", function() { clicked++; } );
  1255. jQuery( "#qunit-fixture div" ).trigger( "click" );
  1256. jQuery( "#foo" ).trigger( "click" );
  1257. jQuery( "#qunit-fixture" ).trigger( "click" );
  1258. jQuery( "body" ).trigger( "click" );
  1259. assert.equal( clicked, 2, "on with a context" );
  1260. // Test unbinding with a different context
  1261. jQuery( "#qunit-fixture" ).off( "click", "#foo" );
  1262. jQuery( "#foo" ).trigger( "click" );
  1263. assert.equal( clicked, 2, "off with a context" );
  1264. // Test binding with event data
  1265. jQuery( "#body" ).on( "click", "#foo", true, function( e ) {
  1266. assert.equal( e.data, true, "on with event data" );
  1267. } );
  1268. jQuery( "#foo" ).trigger( "click" );
  1269. jQuery( "#body" ).off( "click", "#foo" );
  1270. // Test binding with trigger data
  1271. jQuery( "#body" ).on( "click", "#foo", function( e, data ) {
  1272. assert.equal( data, true, "on with trigger data" );
  1273. } );
  1274. jQuery( "#foo" ).trigger( "click", true );
  1275. jQuery( "#body" ).off( "click", "#foo" );
  1276. // Test binding with different this object
  1277. jQuery( "#body" ).on( "click", "#foo", function() {
  1278. assert.equal( this.foo, "bar", "on with event scope" );
  1279. }.bind( { "foo": "bar" } ) );
  1280. jQuery( "#foo" ).trigger( "click" );
  1281. jQuery( "#body" ).off( "click", "#foo" );
  1282. // Test binding with different this object, event data, and trigger data
  1283. jQuery( "#body" ).on( "click", "#foo", true, function( e, data ) {
  1284. assert.equal( e.data, true, "on with with different this object, event data, and trigger data" );
  1285. assert.equal( this.foo, "bar", "on with with different this object, event data, and trigger data" );
  1286. assert.equal( data, true, "on with with different this object, event data, and trigger data" );
  1287. }.bind( { "foo": "bar" } ) );
  1288. jQuery( "#foo" ).trigger( "click", true );
  1289. jQuery( "#body" ).off( "click", "#foo" );
  1290. // Verify that return false prevents default action
  1291. jQuery( "#body" ).on( "click", "#anchor2", function() { return false; } );
  1292. hash = window.location.hash;
  1293. jQuery( "#anchor2" ).trigger( "click" );
  1294. assert.equal( window.location.hash, hash, "return false worked" );
  1295. jQuery( "#body" ).off( "click", "#anchor2" );
  1296. // Verify that .preventDefault() prevents default action
  1297. jQuery( "#body" ).on( "click", "#anchor2", function( e ) { e.preventDefault(); } );
  1298. hash = window.location.hash;
  1299. jQuery( "#anchor2" ).trigger( "click" );
  1300. assert.equal( window.location.hash, hash, "e.preventDefault() worked" );
  1301. jQuery( "#body" ).off( "click", "#anchor2" );
  1302. // Test binding the same handler to multiple points
  1303. called = 0;
  1304. function callback() { called++; return false; }
  1305. jQuery( "#body" ).on( "click", "#nothiddendiv", callback );
  1306. jQuery( "#body" ).on( "click", "#anchor2", callback );
  1307. jQuery( "#nothiddendiv" ).trigger( "click" );
  1308. assert.equal( called, 1, "Verify that only one click occurred." );
  1309. called = 0;
  1310. jQuery( "#anchor2" ).trigger( "click" );
  1311. assert.equal( called, 1, "Verify that only one click occurred." );
  1312. // Make sure that only one callback is removed
  1313. jQuery( "#body" ).off( "click", "#anchor2", callback );
  1314. called = 0;
  1315. jQuery( "#nothiddendiv" ).trigger( "click" );
  1316. assert.equal( called, 1, "Verify that only one click occurred." );
  1317. called = 0;
  1318. jQuery( "#anchor2" ).trigger( "click" );
  1319. assert.equal( called, 0, "Verify that no click occurred." );
  1320. // Make sure that it still works if the selector is the same,
  1321. // but the event type is different
  1322. jQuery( "#body" ).on( "foo", "#nothiddendiv", callback );
  1323. // Cleanup
  1324. jQuery( "#body" ).off( "click", "#nothiddendiv", callback );
  1325. called = 0;
  1326. jQuery( "#nothiddendiv" ).trigger( "click" );
  1327. assert.equal( called, 0, "Verify that no click occurred." );
  1328. called = 0;
  1329. jQuery( "#nothiddendiv" ).trigger( "foo" );
  1330. assert.equal( called, 1, "Verify that one foo occurred." );
  1331. // Cleanup
  1332. jQuery( "#body" ).off( "foo", "#nothiddendiv", callback );
  1333. // Make sure we don't loose the target by DOM modifications
  1334. // after the bubble already reached the liveHandler
  1335. livec = 0;
  1336. jQuery( "#nothiddendivchild" ).html( "<span></span>" );
  1337. jQuery( "#body" ).on( "click", "#nothiddendivchild", function() { jQuery( "#nothiddendivchild" ).html( "" ); } );
  1338. jQuery( "#body" ).on( "click", "#nothiddendivchild", function( e ) { if ( e.target ) {livec++;} } );
  1339. jQuery( "#nothiddendiv span" ).trigger( "click" );
  1340. assert.equal( jQuery( "#nothiddendiv span" ).length, 0, "Verify that first handler occurred and modified the DOM." );
  1341. assert.equal( livec, 1, "Verify that second handler occurred even with nuked target." );
  1342. // Cleanup
  1343. jQuery( "#body" ).off( "click", "#nothiddendivchild" );
  1344. // Verify that .live() occurs and cancel bubble in the same order as
  1345. // we would expect .on() and .click() without delegation
  1346. lived = 0;
  1347. livee = 0;
  1348. // bind one pair in one order
  1349. jQuery( "#body" ).on( "click", "span#liveSpan1 a", function() { lived++; return false; } );
  1350. jQuery( "#body" ).on( "click", "span#liveSpan1", function() { livee++; } );
  1351. jQuery( "span#liveSpan1 a" ).trigger( "click" );
  1352. assert.equal( lived, 1, "Verify that only one first handler occurred." );
  1353. assert.equal( livee, 0, "Verify that second handler doesn't." );
  1354. // and one pair in inverse
  1355. jQuery( "#body" ).on( "click", "span#liveSpan2", function() { livee++; } );
  1356. jQuery( "#body" ).on( "click", "span#liveSpan2 a", function() { lived++; return false; } );
  1357. lived = 0;
  1358. livee = 0;
  1359. jQuery( "span#liveSpan2 a" ).trigger( "click" );
  1360. assert.equal( lived, 1, "Verify that only one first handler occurred." );
  1361. assert.equal( livee, 0, "Verify that second handler doesn't." );
  1362. // Cleanup
  1363. jQuery( "#body" ).off( "click", "**" );
  1364. // Test this, target and currentTarget are correct
  1365. jQuery( "#body" ).on( "click", "span#liveSpan1", function( e ) {
  1366. assert.equal( this.id, "liveSpan1", "Check the this within a on handler" );
  1367. assert.equal( e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a on handler" );
  1368. assert.equal( e.delegateTarget, document.body, "Check the event.delegateTarget within a on handler" );
  1369. assert.equal( e.target.nodeName.toUpperCase(), "A", "Check the event.target within a on handler" );
  1370. } );
  1371. jQuery( "span#liveSpan1 a" ).trigger( "click" );
  1372. jQuery( "#body" ).off( "click", "span#liveSpan1" );
  1373. // Work with deep selectors
  1374. livee = 0;
  1375. function clickB() { livee++; }
  1376. jQuery( "#body" ).on( "click", "#nothiddendiv div", function() { livee++; } );
  1377. jQuery( "#body" ).on( "click", "#nothiddendiv div", clickB );
  1378. jQuery( "#body" ).on( "mouseover", "#nothiddendiv div", function() { livee++; } );
  1379. assert.equal( livee, 0, "No clicks, deep selector." );
  1380. livee = 0;
  1381. jQuery( "#nothiddendivchild" ).trigger( "click" );
  1382. assert.equal( livee, 2, "Click, deep selector." );
  1383. livee = 0;
  1384. jQuery( "#nothiddendivchild" ).trigger( "mouseover" );
  1385. assert.equal( livee, 1, "Mouseover, deep selector." );
  1386. jQuery( "#body" ).off( "mouseover", "#nothiddendiv div" );
  1387. livee = 0;
  1388. jQuery( "#nothiddendivchild" ).trigger( "click" );
  1389. assert.equal( livee, 2, "Click, deep selector." );
  1390. livee = 0;
  1391. jQuery( "#nothiddendivchild" ).trigger( "mouseover" );
  1392. assert.equal( livee, 0, "Mouseover, deep selector." );
  1393. jQuery( "#body" ).off( "click", "#nothiddendiv div", clickB );
  1394. livee = 0;
  1395. jQuery( "#nothiddendivchild" ).trigger( "click" );
  1396. assert.equal( livee, 1, "Click, deep selector." );
  1397. jQuery( "#body" ).off( "click", "#nothiddendiv div" );
  1398. } );
  1399. QUnit.test( "jQuery.off using dispatched jQuery.Event", function( assert ) {
  1400. assert.expect( 1 );
  1401. var markup = jQuery( "<p><a href='#'>target</a></p>" ),
  1402. count = 0;
  1403. markup
  1404. .on( "click.name", "a", function( event ) {
  1405. assert.equal( ++count, 1, "event called once before removal" );
  1406. jQuery().off( event );
  1407. } )
  1408. .find( "a" ).trigger( "click" ).trigger( "click" ).end()
  1409. .remove();
  1410. } );
  1411. QUnit.test( "events with type matching an Object.prototype property (gh-3256)", function( assert ) {
  1412. assert.expect( 1 );
  1413. var elem = jQuery( "<div></div>" ),
  1414. eventFired = false;
  1415. elem.appendTo( "#qunit-fixture" );
  1416. try {
  1417. elem
  1418. .one( "hasOwnProperty", function() {
  1419. eventFired = true;
  1420. } )
  1421. .trigger( "hasOwnProperty" );
  1422. } finally {
  1423. assert.strictEqual( eventFired, true, "trigger fired without crashing" );
  1424. }
  1425. } );
  1426. QUnit.test( "events with type matching an Object.prototype property, cloned element (gh-3256)",
  1427. function( assert ) {
  1428. assert.expect( 1 );
  1429. var elem = jQuery( "<div></div>" ),
  1430. eventFired = false;
  1431. elem.appendTo( "#qunit-fixture" );
  1432. try {
  1433. // Make sure the original element has some event data.
  1434. elem.on( "click", function() {} );
  1435. elem
  1436. .clone( true )
  1437. .one( "hasOwnProperty", function() {
  1438. eventFired = true;
  1439. } )
  1440. .trigger( "hasOwnProperty" );
  1441. } finally {
  1442. assert.strictEqual( eventFired, true, "trigger fired without crashing" );
  1443. }
  1444. } );
  1445. // selector-native does not support scope-fixing in delegation
  1446. QUnit[ jQuery.find.compile ? "test" : "skip" ]( "delegated event with delegateTarget-relative selector", function( assert ) {
  1447. assert.expect( 3 );
  1448. var markup = jQuery( "<div><ul><li><a id=\"a0\"></a><ul id=\"ul0\"><li class=test><a id=\"a0_0\"></a></li><li><a id=\"a0_1\"></a></li></ul></li></ul></div>" ).appendTo( "#qunit-fixture" );
  1449. // Non-positional selector (#12383)
  1450. markup.find( "#ul0" )
  1451. .on( "click", "div li a", function() {
  1452. assert.ok( false, "div is ABOVE the delegation point!" );
  1453. } )
  1454. .on( "click", "ul a", function() {
  1455. assert.ok( false, "ul IS the delegation point!" );
  1456. } )
  1457. .on( "click", "li.test a", function() {
  1458. assert.ok( true, "li.test is below the delegation point." );
  1459. } )
  1460. .find( "#a0_0" ).trigger( "click" ).end()
  1461. .off( "click" );
  1462. // Positional selector (#11315)
  1463. markup.find( "ul" ).eq( 0 )
  1464. .on( "click", ">li>a", function() {
  1465. assert.ok( this.id === "a0", "child li was clicked" );
  1466. } )
  1467. .find( "#ul0" )
  1468. .on( "click", "li:first>a", function() {
  1469. assert.ok( this.id === "a0_0", "first li under #u10 was clicked" );
  1470. } )
  1471. .end()
  1472. .find( "a" ).trigger( "click" ).end()
  1473. .find( "#ul0" ).off();
  1474. markup.remove();
  1475. } );
  1476. QUnit.test( "delegated event with selector matching Object.prototype property (#13203)", function( assert ) {
  1477. assert.expect( 1 );
  1478. var matched = 0;
  1479. jQuery( "#foo" ).on( "click", "toString", function() {
  1480. matched++;
  1481. } );
  1482. jQuery( "#anchor2" ).trigger( "click" );
  1483. assert.equal( matched, 0, "Nothing matched 'toString'" );
  1484. } );
  1485. QUnit.test( "delegated event with intermediate DOM manipulation (#13208)", function( assert ) {
  1486. assert.expect( 1 );
  1487. jQuery( "#foo" ).on( "click", "[id=sap]", function() {} );
  1488. jQuery( "#sap" ).on( "click", "[id=anchor2]", function() {
  1489. document.createDocumentFragment().appendChild( this.parentNode );
  1490. assert.ok( true, "Element removed" );
  1491. } );
  1492. jQuery( "#anchor2" ).trigger( "click" );
  1493. } );
  1494. QUnit.test( "ignore comment nodes in event delegation (gh-2055)", function( assert ) {
  1495. assert.expect( 1 );
  1496. // Test if DOMNodeInserted is supported
  1497. // This is a back-up for when DOMNodeInserted support
  1498. // is eventually removed from browsers
  1499. function test() {
  1500. var ret = false;
  1501. var $fixture = jQuery( "#qunit-fixture" );
  1502. $fixture.on( "DOMNodeInserted", function() {
  1503. ret = true;
  1504. $fixture.off( "DOMNodeInserted" );
  1505. } ).append( "<div></div>" );
  1506. return ret;
  1507. }
  1508. var $foo = jQuery( "#foo" ).on( "DOMNodeInserted", "[id]", function() {
  1509. assert.ok( true, "No error thrown on comment node" );
  1510. } ),
  1511. $comment = jQuery( document.createComment( "comment" ) )
  1512. .appendTo( $foo.find( "#sap" ) );
  1513. if ( !test() ) {
  1514. fireNative( $comment[ 0 ], "DOMNodeInserted" );
  1515. }
  1516. } );
  1517. QUnit.test( "stopPropagation() stops directly-bound events on delegated target", function( assert ) {
  1518. assert.expect( 1 );
  1519. var markup = jQuery( "<div><p><a href=\"#\">target</a></p></div>" );
  1520. markup
  1521. .on( "click", function() {
  1522. assert.ok( false, "directly-bound event on delegate target was called" );
  1523. } )
  1524. .on( "click", "a", function( e ) {
  1525. e.stopPropagation();
  1526. assert.ok( true, "delegated handler was called" );
  1527. } )
  1528. .find( "a" ).trigger( "click" ).end()
  1529. .remove();
  1530. } );
  1531. QUnit.test( "off all bound delegated events", function( assert ) {
  1532. assert.expect( 2 );
  1533. var count = 0,
  1534. clicks = 0,
  1535. div = jQuery( "#body" );
  1536. div.on( "click submit", "div#nothiddendivchild", function() { count++; } );
  1537. div.on( "click", function() { clicks++; } );
  1538. div.off( undefined, "**" );
  1539. jQuery( "div#nothiddendivchild" ).trigger( "click" );
  1540. jQuery( "div#nothiddendivchild" ).trigger( "submit" );
  1541. assert.equal( count, 0, "Make sure no events were triggered." );
  1542. div.trigger( "click" );
  1543. assert.equal( clicks, 2, "Make sure delegated and directly bound event occurred." );
  1544. div.off( "click" );
  1545. } );
  1546. QUnit.test( "on with multiple delegated events", function( assert ) {
  1547. assert.expect( 1 );
  1548. var count = 0,
  1549. div = jQuery( "#body" );
  1550. div.on( "click submit", "div#nothiddendivchild", function() { count++; } );
  1551. jQuery( "div#nothiddendivchild" ).trigger( "click" );
  1552. jQuery( "div#nothiddendivchild" ).trigger( "submit" );
  1553. assert.equal( count, 2, "Make sure both the click and submit were triggered." );
  1554. jQuery( "#body" ).off( undefined, "**" );
  1555. } );
  1556. QUnit.test( "delegated on with change", function( assert ) {
  1557. assert.expect( 8 );
  1558. var select, checkbox, checkboxFunction,
  1559. text, textChange, oldTextVal,
  1560. password, passwordChange, oldPasswordVal,
  1561. selectChange = 0,
  1562. checkboxChange = 0;
  1563. select = jQuery( "select[name='S1']" );
  1564. jQuery( "#body" ).on( "change", "select[name='S1']", function() {
  1565. selectChange++;
  1566. } );
  1567. checkbox = jQuery( "#check2" );
  1568. checkboxFunction = function() {
  1569. checkboxChange++;
  1570. };
  1571. jQuery( "#body" ).on( "change", "#check2", checkboxFunction );
  1572. // test click on select
  1573. // second click that changed it
  1574. selectChange = 0;
  1575. select[ 0 ].selectedIndex = select[ 0 ].selectedIndex ? 0 : 1;
  1576. select.trigger( "change" );
  1577. assert.equal( selectChange, 1, "Change on click." );
  1578. // test keys on select
  1579. selectChange = 0;
  1580. select[ 0 ].selectedIndex = select[ 0 ].selectedIndex ? 0 : 1;
  1581. select.trigger( "change" );
  1582. assert.equal( selectChange, 1, "Change on keyup." );
  1583. // test click on checkbox
  1584. checkbox.trigger( "change" );
  1585. assert.equal( checkboxChange, 1, "Change on checkbox." );
  1586. // test blur/focus on text
  1587. text = jQuery( "#name" );
  1588. textChange = 0;
  1589. oldTextVal = text.val();
  1590. jQuery( "#body" ).on( "change", "#name", function() {
  1591. textChange++;
  1592. } );
  1593. text.val( oldTextVal + "foo" );
  1594. text.trigger( "change" );
  1595. assert.equal( textChange, 1, "Change on text input." );
  1596. text.val( oldTextVal );
  1597. jQuery( "#body" ).off( "change", "#name" );
  1598. // test blur/focus on password
  1599. password = jQuery( "#name" );
  1600. passwordChange = 0;
  1601. oldPasswordVal = password.val();
  1602. jQuery( "#body" ).on( "change", "#name", function() {
  1603. passwordChange++;
  1604. } );
  1605. password.val( oldPasswordVal + "foo" );
  1606. password.trigger( "change" );
  1607. assert.equal( passwordChange, 1, "Change on password input." );
  1608. password.val( oldPasswordVal );
  1609. jQuery( "#body" ).off( "change", "#name" );
  1610. // make sure die works
  1611. // die all changes
  1612. selectChange = 0;
  1613. jQuery( "#body" ).off( "change", "select[name='S1']" );
  1614. select[ 0 ].selectedIndex = select[ 0 ].selectedIndex ? 0 : 1;
  1615. select.trigger( "change" );
  1616. assert.equal( selectChange, 0, "Die on click works." );
  1617. selectChange = 0;
  1618. select[ 0 ].selectedIndex = select[ 0 ].selectedIndex ? 0 : 1;
  1619. select.trigger( "change" );
  1620. assert.equal( selectChange, 0, "Die on keyup works." );
  1621. // die specific checkbox
  1622. jQuery( "#body" ).off( "change", "#check2", checkboxFunction );
  1623. checkbox.trigger( "change" );
  1624. assert.equal( checkboxChange, 1, "Die on checkbox." );
  1625. } );
  1626. QUnit.test( "delegated on with submit", function( assert ) {
  1627. assert.expect( 2 );
  1628. var count1 = 0, count2 = 0;
  1629. jQuery( "#body" ).on( "submit", "#testForm", function( ev ) {
  1630. count1++;
  1631. ev.preventDefault();
  1632. } );
  1633. jQuery( document ).on( "submit", "body", function( ev ) {
  1634. count2++;
  1635. ev.preventDefault();
  1636. } );
  1637. jQuery( "#testForm input[name=sub1]" ).trigger( "submit" );
  1638. assert.equal( count1, 1, "Verify form submit." );
  1639. assert.equal( count2, 1, "Verify body submit." );
  1640. jQuery( "#body" ).off( undefined, "**" );
  1641. jQuery( document ).off( undefined, "**" );
  1642. } );
  1643. QUnit.test( "delegated off() with only namespaces", function( assert ) {
  1644. assert.expect( 2 );
  1645. var $delegate = jQuery( "#liveHandlerOrder" ),
  1646. count = 0;
  1647. $delegate.on( "click.ns", "a", function() {
  1648. count++;
  1649. } );
  1650. jQuery( "a", $delegate ).eq( 0 ).trigger( "click.ns" );
  1651. assert.equal( count, 1, "delegated click.ns" );
  1652. $delegate.off( ".ns", "**" );
  1653. jQuery( "a", $delegate ).eq( 1 ).trigger( "click.ns" );
  1654. assert.equal( count, 1, "no more .ns after off" );
  1655. } );
  1656. QUnit.test( "Non DOM element events", function( assert ) {
  1657. assert.expect( 1 );
  1658. var o = {};
  1659. jQuery( o ).on( "nonelementobj", function() {
  1660. assert.ok( true, "Event on non-DOM object triggered" );
  1661. } );
  1662. jQuery( o ).trigger( "nonelementobj" ).off( "nonelementobj" );
  1663. } );
  1664. QUnit.test( "inline handler returning false stops default", function( assert ) {
  1665. assert.expect( 1 );
  1666. var markup = jQuery( "<div><a href=\"#\" onclick=\"return false\">x</a></div>" );
  1667. markup.on( "click", function( e ) {
  1668. assert.ok( e.isDefaultPrevented(), "inline handler prevented default" );
  1669. return false;
  1670. } );
  1671. markup.find( "a" ).trigger( "click" );
  1672. markup.off( "click" );
  1673. } );
  1674. QUnit.test( "window resize", function( assert ) {
  1675. assert.expect( 2 );
  1676. jQuery( window ).off();
  1677. jQuery( window ).on( "resize", function() {
  1678. assert.ok( true, "Resize event fired." );
  1679. } ).trigger( "resize" ).off( "resize" );
  1680. assert.ok( !jQuery._data( window, "events" ), "Make sure all the events are gone." );
  1681. } );
  1682. QUnit.test( "focusin bubbles", function( assert ) {
  1683. assert.expect( 2 );
  1684. var input = jQuery( "<input type='text' />" ).prependTo( "body" ),
  1685. order = 0;
  1686. // focus the element so DOM focus won't fire
  1687. input[ 0 ].focus();
  1688. jQuery( "body" ).on( "focusin.focusinBubblesTest", function() {
  1689. assert.equal( 1, order++, "focusin on the body second" );
  1690. } );
  1691. input.on( "focusin.focusinBubblesTest", function() {
  1692. assert.equal( 0, order++, "focusin on the element first" );
  1693. } );
  1694. // Removed since DOM focus is unreliable on test swarm
  1695. // DOM focus method
  1696. // input[0].focus();
  1697. // To make the next focus test work, we need to take focus off the input.
  1698. // This will fire another focusin event, so set order to reflect that.
  1699. // order = 1;
  1700. // jQuery("#text1")[0].focus();
  1701. // jQuery trigger, which calls DOM focus
  1702. order = 0;
  1703. input.trigger( "focus" );
  1704. input.remove();
  1705. jQuery( "body" ).off( "focusin.focusinBubblesTest" );
  1706. } );
  1707. QUnit.test( "custom events with colons (#3533, #8272)", function( assert ) {
  1708. assert.expect( 1 );
  1709. var tab = jQuery( "<table><tr><td>trigger</td></tr></table>" ).appendTo( "body" );
  1710. try {
  1711. tab.trigger( "back:forth" );
  1712. assert.ok( true, "colon events don't throw" );
  1713. } catch ( e ) {
  1714. assert.ok( false, "colon events die" );
  1715. }
  1716. tab.remove();
  1717. } );
  1718. QUnit.test( ".on and .off", function( assert ) {
  1719. assert.expect( 9 );
  1720. var counter, mixfn, data,
  1721. $onandoff = jQuery( "<div id=\"onandoff\"><p>on<b>and</b>off</p><div>worked<em>or</em>borked?</div></div>" ).appendTo( "body" );
  1722. // Simple case
  1723. jQuery( "#onandoff" )
  1724. .on( "whip", function() {
  1725. assert.ok( true, "whipped it good" );
  1726. } )
  1727. .trigger( "whip" )
  1728. .off();
  1729. // Direct events only
  1730. counter = 0;
  1731. jQuery( "#onandoff b" )
  1732. .on( "click", 5, function( e, trig ) {
  1733. counter += e.data + ( trig || 9 ); // twice, 5+9+5+17=36
  1734. } )
  1735. .one( "click", 7, function( e, trig ) {
  1736. counter += e.data + ( trig || 11 ); // once, 7+11=18
  1737. } )
  1738. .trigger( "click" )
  1739. .trigger( "click", 17 )
  1740. .off( "click" );
  1741. assert.equal( counter, 54, "direct event bindings with data" );
  1742. // Delegated events only
  1743. counter = 0;
  1744. jQuery( "#onandoff" )
  1745. .on( "click", "em", 5, function( e, trig ) {
  1746. counter += e.data + ( trig || 9 ); // twice, 5+9+5+17=36
  1747. } )
  1748. .one( "click", "em", 7, function( e, trig ) {
  1749. counter += e.data + ( trig || 11 ); // once, 7+11=18
  1750. } )
  1751. .find( "em" )
  1752. .trigger( "click" )
  1753. .trigger( "click", 17 )
  1754. .end()
  1755. .off( "click", "em" );
  1756. assert.equal( counter, 54, "delegated event bindings with data" );
  1757. // Mixed event bindings and types
  1758. counter = 0;
  1759. mixfn = function( e, trig ) {
  1760. counter += ( e.data || 0 ) + ( trig || 1 );
  1761. };
  1762. jQuery( "#onandoff" )
  1763. .on( " click clack cluck ", "em", 2, mixfn )
  1764. .on( "cluck", "b", 7, mixfn )
  1765. .on( "cluck", mixfn )
  1766. .trigger( "what!" )
  1767. .each( function() {
  1768. assert.equal( counter, 0, "nothing triggered yet" );
  1769. } )
  1770. .find( "em" )
  1771. .one( "cluck", 3, mixfn )
  1772. .trigger( "cluck", 8 ) // 3+8 2+8 + 0+8 = 29
  1773. .off()
  1774. .trigger( "cluck", 9 ) // 2+9 + 0+9 = 20
  1775. .end()
  1776. .each( function() {
  1777. assert.equal( counter, 49, "after triggering em element" );
  1778. } )
  1779. .off( "cluck", function() {} ) // shouldn't remove anything
  1780. .trigger( "cluck", 2 ) // 0+2 = 2
  1781. .each( function() {
  1782. assert.equal( counter, 51, "after triggering #onandoff cluck" );
  1783. } )
  1784. .find( "b" )
  1785. .on( "click", 95, mixfn )
  1786. .on( "clack", "p", 97, mixfn )
  1787. .one( "cluck", 3, mixfn )
  1788. .trigger( "quack", 19 ) // 0
  1789. .off( "click clack cluck" )
  1790. .end()
  1791. .each( function() {
  1792. assert.equal( counter, 51, "after triggering b" );
  1793. } )
  1794. .trigger( "cluck", 3 ) // 0+3 = 3
  1795. .off( "clack", "em", mixfn )
  1796. .find( "em" )
  1797. .trigger( "clack" ) // 0
  1798. .end()
  1799. .each( function() {
  1800. assert.equal( counter, 54, "final triggers" );
  1801. } )
  1802. .off( "click cluck" );
  1803. // We should have removed all the event handlers ... kinda hacky way to check this
  1804. data = jQuery.data[ jQuery( "#onandoff" )[ 0 ].expando ] || {};
  1805. assert.equal( data[ "events" ], undefined, "no events left" );
  1806. $onandoff.remove();
  1807. } );
  1808. QUnit.test( "special on name mapping", function( assert ) {
  1809. assert.expect( 7 );
  1810. jQuery.event.special.slap = {
  1811. bindType: "click",
  1812. delegateType: "swing",
  1813. handle: function( event ) {
  1814. assert.equal( event.handleObj.origType, "slap", "slapped your mammy, " + event.type );
  1815. }
  1816. };
  1817. var comeback = function( event ) {
  1818. assert.ok( true, "event " + event.type + " triggered" );
  1819. };
  1820. jQuery( "<div><button id=\"mammy\">Are We Not Men?</button></div>" )
  1821. .on( "slap", "button", jQuery.noop )
  1822. .on( "swing", "button", comeback )
  1823. .find( "button" )
  1824. .on( "slap", jQuery.noop )
  1825. .on( "click", comeback )
  1826. .trigger( "click" ) // bindType-slap and click
  1827. .off( "slap" )
  1828. .trigger( "click" ) // click
  1829. .off( "click" )
  1830. .trigger( "swing" ) // delegateType-slap and swing
  1831. .end()
  1832. .off( "slap swing", "button" )
  1833. .find( "button" ) // everything should be gone
  1834. .trigger( "slap" )
  1835. .trigger( "click" )
  1836. .trigger( "swing" )
  1837. .end()
  1838. .remove();
  1839. delete jQuery.event.special.slap;
  1840. jQuery.event.special.gutfeeling = {
  1841. bindType: "click",
  1842. delegateType: "click",
  1843. handle: function( event ) {
  1844. assert.equal( event.handleObj.origType, "gutfeeling", "got a gutfeeling" );
  1845. // Need to call the handler since .one() uses it to unbind
  1846. return event.handleObj.handler.call( this, event );
  1847. }
  1848. };
  1849. // Ensure a special event isn't removed by its mapped type
  1850. jQuery( "<p>Gut Feeling</p>" )
  1851. .on( "click", jQuery.noop )
  1852. .on( "gutfeeling", jQuery.noop )
  1853. .off( "click" )
  1854. .trigger( "gutfeeling" )
  1855. .remove();
  1856. // Ensure special events are removed when only a namespace is provided
  1857. jQuery( "<p>Gut Feeling</p>" )
  1858. .on( "gutfeeling.Devo", jQuery.noop )
  1859. .off( ".Devo" )
  1860. .trigger( "gutfeeling" )
  1861. .remove();
  1862. // Ensure .one() events are removed after their maiden voyage
  1863. jQuery( "<p>Gut Feeling</p>" )
  1864. .one( "gutfeeling", jQuery.noop )
  1865. .trigger( "gutfeeling" ) // This one should
  1866. .trigger( "gutfeeling" ) // This one should not
  1867. .remove();
  1868. delete jQuery.event.special[ "gutfeeling" ];
  1869. } );
  1870. QUnit.test( ".on and .off, selective mixed removal (#10705)", function( assert ) {
  1871. assert.expect( 7 );
  1872. var timingx = function( e ) {
  1873. assert.ok( true, "triggered " + e.type );
  1874. };
  1875. jQuery( "<p>Strange Pursuit</p>" )
  1876. .on( "click", timingx )
  1877. .on( "click.duty", timingx )
  1878. .on( "click.now", timingx )
  1879. .on( "devo", timingx )
  1880. .on( "future", timingx )
  1881. .trigger( "click" ) // 3
  1882. .trigger( "devo" ) // 1
  1883. .off( ".duty devo " ) // trailing space
  1884. .trigger( "future" ) // 1
  1885. .trigger( "click" ) // 2
  1886. .off( "future click" )
  1887. .trigger( "click" ); // 0
  1888. } );
  1889. QUnit.test( ".on( event-map, null-selector, data ) #11130", function( assert ) {
  1890. assert.expect( 1 );
  1891. var $p = jQuery( "<p>Strange Pursuit</p>" ),
  1892. data = "bar",
  1893. map = {
  1894. "foo": function( event ) {
  1895. assert.equal( event.data, "bar", "event.data correctly relayed with null selector" );
  1896. $p.remove();
  1897. }
  1898. };
  1899. $p.on( map, null, data ).trigger( "foo" );
  1900. } );
  1901. QUnit.test( "clone() delegated events (#11076)", function( assert ) {
  1902. assert.expect( 3 );
  1903. var counter = { "center": 0, "fold": 0, "centerfold": 0 },
  1904. clicked = function() {
  1905. counter[ jQuery( this ).text().replace( /\s+/, "" ) ]++;
  1906. },
  1907. table =
  1908. jQuery( "<table><tr><td>center</td><td>fold</td></tr></table>" )
  1909. .on( "click", "tr", clicked )
  1910. .on( "click", "td:first-child", clicked )
  1911. .on( "click", "td:last-child", clicked ),
  1912. clone = table.clone( true );
  1913. clone.find( "td" ).trigger( "click" );
  1914. assert.equal( counter.center, 1, "first child" );
  1915. assert.equal( counter.fold, 1, "last child" );
  1916. assert.equal( counter.centerfold, 2, "all children" );
  1917. table.remove();
  1918. clone.remove();
  1919. } );
  1920. QUnit.test( "checkbox state (trac-3827)", function( assert ) {
  1921. assert.expect( 16 );
  1922. var markup = jQuery( "<div class='parent'><input type=checkbox><div>" ),
  1923. cb = markup.find( "input" )[ 0 ];
  1924. markup.appendTo( "#qunit-fixture" );
  1925. jQuery( cb ).on( "click", function() {
  1926. assert.equal( this.checked, false, "just-clicked checkbox is not checked" );
  1927. } );
  1928. markup.on( "click", function() {
  1929. assert.equal( cb.checked, false, "checkbox is not checked in bubbled event" );
  1930. } );
  1931. // Native click
  1932. cb.checked = true;
  1933. assert.equal( cb.checked, true, "native event - checkbox is initially checked" );
  1934. cb.click();
  1935. assert.equal( cb.checked, false, "native event - checkbox is no longer checked" );
  1936. // jQuery click
  1937. cb.checked = true;
  1938. assert.equal( cb.checked, true, "jQuery event - checkbox is initially checked" );
  1939. jQuery( cb ).trigger( "click" );
  1940. assert.equal( cb.checked, false, "jQuery event - checkbox is no longer checked" );
  1941. // Handlers only; checkbox state remains false
  1942. jQuery( cb ).triggerHandler( "click" );
  1943. assert.equal( cb.checked, false, "handlers only - checkbox is still unchecked" );
  1944. // Trigger parameters are preserved (trac-13353, gh-4139)
  1945. cb.checked = true;
  1946. assert.equal( cb.checked, true, "jQuery event with data - checkbox is initially checked" );
  1947. jQuery( cb ).on( "click", function( e, data ) {
  1948. assert.equal( data, "clicked", "trigger data passed to handler" );
  1949. } );
  1950. markup.on( "click", function( e, data ) {
  1951. assert.equal( data, "clicked", "trigger data passed to bubbled handler" );
  1952. } );
  1953. jQuery( cb ).trigger( "click", [ "clicked" ] );
  1954. assert.equal( cb.checked, false, "jQuery event with data - checkbox is no longer checked" );
  1955. } );
  1956. QUnit.test( "event object properties on natively-triggered event", function( assert ) {
  1957. assert.expect( 3 );
  1958. var link = document.createElement( "a" ),
  1959. $link = jQuery( link ),
  1960. evt = document.createEvent( "MouseEvents" );
  1961. // Support: IE <=9 - 11 only
  1962. // IE requires element to be in the body before it will dispatch
  1963. $link.appendTo( "body" ).on( "click", function( e ) {
  1964. // Not trying to assert specific values here, just ensure the property exists
  1965. assert.equal( "detail" in e, true, "has .detail" );
  1966. assert.equal( "cancelable" in e, true, "has .cancelable" );
  1967. assert.equal( "bubbles" in e, true, "has .bubbles" );
  1968. } );
  1969. evt.initEvent( "click", true, true );
  1970. link.dispatchEvent( evt );
  1971. $link.off( "click" ).remove();
  1972. } );
  1973. QUnit.test( "addProp extensions", function( assert ) {
  1974. assert.expect( 2 );
  1975. var $fixture = jQuery( "<div>" ).appendTo( "#qunit-fixture" );
  1976. // Ensure the property doesn't exist
  1977. $fixture.on( "click", function( event ) {
  1978. assert.ok( !( "testProperty" in event ), "event.testProperty does not exist" );
  1979. } );
  1980. fireNative( $fixture[ 0 ], "click" );
  1981. $fixture.off( "click" );
  1982. jQuery.event.addProp( "testProperty", function() { return 42; } );
  1983. // Trigger a native click and ensure the property is set
  1984. $fixture.on( "click", function( event ) {
  1985. assert.equal( event.testProperty, 42, "event.testProperty getter was invoked" );
  1986. } );
  1987. fireNative( $fixture[ 0 ], "click" );
  1988. $fixture.off( "click" );
  1989. $fixture.remove();
  1990. } );
  1991. QUnit.test( "drag/drop events copy mouse-related event properties (gh-1925, gh-2009)", function( assert ) {
  1992. assert.expect( 4 );
  1993. var $fixture = jQuery( "<div id='drag-fixture'></div>" ).appendTo( "body" );
  1994. $fixture.on( "dragmove", function( evt ) {
  1995. assert.ok( "pageX" in evt, "checking for pageX property on dragmove" );
  1996. assert.ok( "pageY" in evt, "checking for pageY property on dragmove" );
  1997. } );
  1998. fireNative( $fixture[ 0 ], "dragmove" );
  1999. $fixture.on( "drop", function( evt ) {
  2000. assert.ok( "pageX" in evt, "checking for pageX property on drop" );
  2001. assert.ok( "pageY" in evt, "checking for pageY property on drop" );
  2002. } );
  2003. fireNative( $fixture[ 0 ], "drop" );
  2004. $fixture.off( "dragmove drop" ).remove();
  2005. } );
  2006. QUnit.test( "focusin using non-element targets", function( assert ) {
  2007. assert.expect( 2 );
  2008. jQuery( document ).on( "focusin", function( e ) {
  2009. assert.ok( e.type === "focusin", "got a focusin event on a document" );
  2010. } ).trigger( "focusin" ).off( "focusin" );
  2011. jQuery( window ).on( "focusin", function( e ) {
  2012. assert.ok( e.type === "focusin", "got a focusin event on a window" );
  2013. } ).trigger( "focusin" ).off( "focusin" );
  2014. } );
  2015. testIframe(
  2016. "focusin from an iframe",
  2017. "event/focusinCrossFrame.html",
  2018. function( assert, framejQuery, frameWin, frameDoc ) {
  2019. assert.expect( 1 );
  2020. var done = assert.async(),
  2021. focus = false,
  2022. input = jQuery( frameDoc ).find( "#frame-input" );
  2023. // Create a focusin handler on the parent; shouldn't affect the iframe's fate
  2024. jQuery( "body" ).on( "focusin.iframeTest", function() {
  2025. // Support: IE 9 - 11+
  2026. // IE does propagate the event to the parent document. In this test
  2027. // we mainly care about the inner element so we'll just skip this one
  2028. // assertion in IE.
  2029. if ( !document.documentMode ) {
  2030. assert.ok( false, "fired a focusin event in the parent document" );
  2031. }
  2032. } );
  2033. input.on( "focusin", function() {
  2034. focus = true;
  2035. assert.ok( true, "fired a focusin event in the iframe" );
  2036. } );
  2037. // Avoid a native event; Chrome can't force focus to another frame
  2038. input[ 0 ].focus();
  2039. // Remove body handler manually since it's outside the fixture
  2040. jQuery( "body" ).off( "focusin.iframeTest" );
  2041. setTimeout( function() {
  2042. // DOM focus is unreliable in TestSwarm
  2043. if ( QUnit.isSwarm && !focus ) {
  2044. assert.ok( true, "GAP: Could not observe focus change" );
  2045. }
  2046. done();
  2047. }, 50 );
  2048. }
  2049. );
  2050. QUnit.test( "focusin on document & window", function( assert ) {
  2051. assert.expect( 1 );
  2052. var counter = 0,
  2053. input = jQuery( "<input />" );
  2054. function increment() {
  2055. counter++;
  2056. }
  2057. input.appendTo( "#qunit-fixture" );
  2058. input[ 0 ].focus();
  2059. jQuery( window ).on( "focusout", increment );
  2060. jQuery( document ).on( "focusout", increment );
  2061. input[ 0 ].blur();
  2062. // DOM focus is unreliable in TestSwarm
  2063. if ( QUnit.isSwarm && counter === 0 ) {
  2064. assert.ok( true, "GAP: Could not observe focus change" );
  2065. }
  2066. assert.strictEqual( counter, 2,
  2067. "focusout handlers on document/window fired once only" );
  2068. jQuery( window ).off( "focusout", increment );
  2069. jQuery( document ).off( "focusout", increment );
  2070. } );
  2071. QUnit.test( "element removed during focusout (gh-4417)", function( assert ) {
  2072. assert.expect( 1 );
  2073. var button = jQuery( "<button>Click me</button>" );
  2074. button.appendTo( "#qunit-fixture" );
  2075. button.on( "click", function() {
  2076. button.trigger( "blur" );
  2077. assert.ok( true, "Removing the element didn't crash" );
  2078. } );
  2079. // Support: Chrome 86+
  2080. // In Chrome, if an element having a focusout handler is blurred by
  2081. // clicking outside of it, it invokes the handler synchronously. However,
  2082. // if the click happens programmatically, the invocation is asynchronous.
  2083. // As we have no way to simulate real user input in unit tests, simulate
  2084. // this behavior by calling `jQuery.cleanData` & removing the element using
  2085. // native APIs.
  2086. button[ 0 ].blur = function() {
  2087. jQuery.cleanData( [ this ] );
  2088. this.parentNode.removeChild( this );
  2089. };
  2090. button[ 0 ].click();
  2091. } );
  2092. testIframe(
  2093. "jQuery.ready promise",
  2094. "event/promiseReady.html",
  2095. function( assert, jQuery, window, document, isOk ) {
  2096. assert.expect( 1 );
  2097. assert.ok( isOk, "$.when( $.ready ) works" );
  2098. },
  2099. jQuery.when ? QUnit.test : QUnit.skip
  2100. );
  2101. // need PHP here to make the incepted IFRAME hang
  2102. if ( hasPHP ) {
  2103. testIframe(
  2104. "jQuery.ready uses interactive",
  2105. "event/interactiveReady.html",
  2106. function( assert, jQuery, window, document, isOk ) {
  2107. assert.expect( 1 );
  2108. assert.ok( isOk, "jQuery fires ready when the DOM can truly be interacted with" );
  2109. }
  2110. );
  2111. }
  2112. testIframe(
  2113. "Focusing iframe element",
  2114. "event/focusElem.html",
  2115. function( assert, jQuery, window, document, isOk ) {
  2116. assert.expect( 1 );
  2117. assert.ok( isOk, "Focused an element in an iframe" );
  2118. }
  2119. );
  2120. testIframe(
  2121. "triggerHandler(onbeforeunload)",
  2122. "event/triggerunload.html",
  2123. function( assert, jQuery, window, document, isOk ) {
  2124. assert.expect( 1 );
  2125. assert.ok( isOk, "Triggered onbeforeunload without an error" );
  2126. }
  2127. );
  2128. // need PHP here to make the incepted IFRAME hang
  2129. if ( hasPHP ) {
  2130. testIframe(
  2131. "jQuery.ready synchronous load with long loading subresources",
  2132. "event/syncReady.html",
  2133. function( assert, jQuery, window, document, isOk ) {
  2134. assert.expect( 1 );
  2135. assert.ok( isOk, "jQuery loaded synchronously fires ready when the DOM can truly be interacted with" );
  2136. }
  2137. );
  2138. }
  2139. QUnit.test( "change handler should be detached from element", function( assert ) {
  2140. assert.expect( 2 );
  2141. var $fixture = jQuery( "<input type='text' id='change-ie-leak' />" ).appendTo( "body" ),
  2142. originRemoveEvent = jQuery.removeEvent,
  2143. wrapperRemoveEvent = function( elem, type, handle ) {
  2144. assert.equal( "change", type, "Event handler for 'change' event should be removed" );
  2145. assert.equal( "change-ie-leak", jQuery( elem ).attr( "id" ), "Event handler for 'change' event should be removed from appropriate element" );
  2146. originRemoveEvent( elem, type, handle );
  2147. };
  2148. jQuery.removeEvent = wrapperRemoveEvent;
  2149. $fixture.on( "change", function() {} );
  2150. $fixture.off( "change" );
  2151. $fixture.remove();
  2152. jQuery.removeEvent = originRemoveEvent;
  2153. } );
  2154. QUnit.test( "trigger click on checkbox, fires change event", function( assert ) {
  2155. assert.expect( 1 );
  2156. var check = jQuery( "#check2" );
  2157. var done = assert.async();
  2158. check.on( "change", function() {
  2159. // get it?
  2160. check.off( "change" );
  2161. assert.ok( true, "Change event fired as a result of triggered click" );
  2162. done();
  2163. } ).trigger( "click" );
  2164. } );
  2165. QUnit.test( "Namespace preserved when passed an Event (#12739)", function( assert ) {
  2166. assert.expect( 4 );
  2167. var markup = jQuery(
  2168. "<div id='parent'><div id='child'></div></div>"
  2169. ),
  2170. triggered = 0,
  2171. fooEvent;
  2172. markup.find( "div" )
  2173. .addBack()
  2174. .on( "foo.bar", function( e ) {
  2175. if ( !e.handled ) {
  2176. triggered++;
  2177. e.handled = true;
  2178. assert.equal( e.namespace, "bar", "namespace is bar" );
  2179. jQuery( e.target ).find( "div" ).each( function() {
  2180. jQuery( this ).triggerHandler( e );
  2181. } );
  2182. }
  2183. } )
  2184. .on( "foo.bar2", function() {
  2185. assert.ok( false, "foo.bar2 called on trigger " + triggered + " id " + this.id );
  2186. } );
  2187. markup.trigger( "foo.bar" );
  2188. markup.trigger( jQuery.Event( "foo.bar" ) );
  2189. fooEvent = jQuery.Event( "foo" );
  2190. fooEvent.namespace = "bar";
  2191. markup.trigger( fooEvent );
  2192. markup.remove();
  2193. assert.equal( triggered, 3, "foo.bar triggered" );
  2194. } );
  2195. QUnit.test( "make sure events cloned correctly", function( assert ) {
  2196. assert.expect( 18 );
  2197. var clone,
  2198. fixture = jQuery( "#qunit-fixture" ),
  2199. checkbox = jQuery( "#check1" ),
  2200. p = jQuery( "#firstp" );
  2201. fixture.on( "click change", function( event, result ) {
  2202. assert.ok( result, event.type + " on original element is fired" );
  2203. } ).on( "click", "#firstp", function( event, result ) {
  2204. assert.ok( result, "Click on original child element though delegation is fired" );
  2205. } ).on( "change", "#check1", function( event, result ) {
  2206. assert.ok( result, "Change on original child element though delegation is fired" );
  2207. } );
  2208. p.on( "click", function() {
  2209. assert.ok( true, "Click on original child element is fired" );
  2210. } );
  2211. checkbox.on( "change", function() {
  2212. assert.ok( true, "Change on original child element is fired" );
  2213. } );
  2214. fixture.clone().trigger( "click" ).trigger( "change" ); // 0 events should be fired
  2215. clone = fixture.clone( true );
  2216. clone.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
  2217. clone.find( "#check1" ).trigger( "change", true ); // 3 events should fire
  2218. clone.remove();
  2219. clone = fixture.clone( true, true );
  2220. clone.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
  2221. clone.find( "#check1" ).trigger( "change", true ); // 3 events should fire
  2222. fixture.off();
  2223. p.off();
  2224. checkbox.off();
  2225. p.trigger( "click" ); // 0 should be fired
  2226. checkbox.trigger( "change" ); // 0 should be fired
  2227. clone.find( "p" ).eq( 0 ).trigger( "click", true ); // 3 events should fire
  2228. clone.find( "#check1" ).trigger( "change", true ); // 3 events should fire
  2229. clone.remove();
  2230. clone.find( "p" ).eq( 0 ).trigger( "click" ); // 0 should be fired
  2231. clone.find( "#check1" ).trigger( "change" ); // 0 events should fire
  2232. } );
  2233. QUnit.test( "String.prototype.namespace does not cause trigger() to throw (#13360)", function( assert ) {
  2234. assert.expect( 1 );
  2235. var errored = false;
  2236. String.prototype.namespace = function() {};
  2237. try {
  2238. jQuery( "<p>" ).trigger( "foo.bar" );
  2239. } catch ( e ) {
  2240. errored = true;
  2241. }
  2242. assert.equal( errored, false, "trigger() did not throw exception" );
  2243. delete String.prototype.namespace;
  2244. } );
  2245. QUnit.test( "Inline event result is returned (#13993)", function( assert ) {
  2246. assert.expect( 1 );
  2247. var result = jQuery( "<p onclick='return 42'>hello</p>" ).triggerHandler( "click" );
  2248. assert.equal( result, 42, "inline handler returned value" );
  2249. } );
  2250. QUnit.test( ".off() removes the expando when there's no more data", function( assert ) {
  2251. assert.expect( 2 );
  2252. var key,
  2253. div = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" );
  2254. div.on( "click", false );
  2255. div.on( "custom", function() {
  2256. assert.ok( true, "Custom event triggered" );
  2257. } );
  2258. div.trigger( "custom" );
  2259. div.off( "click custom" );
  2260. // Make sure the expando is gone
  2261. for ( key in div[ 0 ] ) {
  2262. if ( /^jQuery/.test( key ) ) {
  2263. assert.strictEqual(
  2264. div[ 0 ][ key ], undefined,
  2265. "Expando was not removed when there was no more data"
  2266. );
  2267. }
  2268. }
  2269. } );
  2270. QUnit.test( "jQuery.Event( src ) does not require a target property", function( assert ) {
  2271. assert.expect( 2 );
  2272. var event = jQuery.Event( { type: "offtarget" } );
  2273. assert.equal( event.type, "offtarget", "correct type" );
  2274. assert.equal( event.target, undefined, "no target" );
  2275. } );
  2276. QUnit.test( "preventDefault() on focusin does not throw exception", function( assert ) {
  2277. assert.expect( 1 );
  2278. var done = assert.async(),
  2279. input = jQuery( "<input/>" ).appendTo( "#form" );
  2280. input.on( "focusin", function( event ) {
  2281. if ( !done ) {
  2282. return;
  2283. }
  2284. var exceptionCaught;
  2285. try {
  2286. event.preventDefault();
  2287. } catch ( theException ) {
  2288. exceptionCaught = theException;
  2289. }
  2290. assert.strictEqual( exceptionCaught, undefined,
  2291. "Preventing default on focusin throws no exception" );
  2292. done();
  2293. done = null;
  2294. } );
  2295. input.trigger( "focus" );
  2296. // DOM focus is unreliable in TestSwarm; set a simulated event workaround timeout
  2297. setTimeout( function() {
  2298. if ( !done ) {
  2299. return;
  2300. }
  2301. input[ 0 ].addEventListener( "click", function( nativeEvent ) {
  2302. jQuery.event.simulate( "focusin", this, jQuery.event.fix( nativeEvent ) );
  2303. } );
  2304. input[ 0 ].click();
  2305. }, QUnit.config.testTimeout / 4 || 1000 );
  2306. } );
  2307. QUnit.test( ".on('focus', fn) on a text node doesn't throw", function( assert ) {
  2308. assert.expect( 1 );
  2309. jQuery( document.createTextNode( "text" ) )
  2310. .on( "focus", function() {} );
  2311. assert.ok( true, "No crash" );
  2312. } );
  2313. QUnit.test( "Donor event interference", function( assert ) {
  2314. assert.expect( 8 );
  2315. var outer = jQuery(
  2316. "<div id='donor-outer'>" +
  2317. "<form id='donor-form'>" +
  2318. "<input id='donor-input' type='checkbox' />" +
  2319. "</form>" +
  2320. "</div>"
  2321. ).appendTo( "#qunit-fixture" ),
  2322. input = jQuery( "#donor-input" );
  2323. input.on( "click", function( event ) {
  2324. assert.equal( event.type, "click", "click event at input" );
  2325. assert.ok( !event.isPropagationStopped(), "click event at input is still propagating" );
  2326. assert.equal( typeof event.originalEvent, "object",
  2327. "click event at input has originalEvent property" );
  2328. } );
  2329. outer.on( "click", function( event ) {
  2330. assert.equal( event.type, "click", "click event at ancestor" );
  2331. assert.ok( !event.isPropagationStopped(), "click event at ancestor is still propagating" );
  2332. assert.equal( typeof event.originalEvent, "object",
  2333. "click event at ancestor has originalEvent property" );
  2334. } );
  2335. input.on( "change", function( event ) {
  2336. assert.equal( event.type, "change", "change event at input" );
  2337. assert.equal( typeof event.originalEvent, "object",
  2338. "change event at input has originalEvent property" );
  2339. event.stopPropagation();
  2340. } );
  2341. input[ 0 ].click();
  2342. } );
  2343. QUnit.test(
  2344. "simulated events shouldn't forward stopPropagation/preventDefault methods",
  2345. function( assert ) {
  2346. assert.expect( 3 );
  2347. var outer = jQuery(
  2348. "<div id='donor-outer'>" +
  2349. "<form id='donor-form'>" +
  2350. "<input id='donor-input' type='checkbox' />" +
  2351. "</form>" +
  2352. "</div>"
  2353. ).appendTo( "#qunit-fixture" ),
  2354. input = jQuery( "#donor-input" ),
  2355. spy = {};
  2356. jQuery( "#donor-form" )
  2357. .on( "simulated", function( event ) {
  2358. spy.prevent = sinon.stub( event.originalEvent, "preventDefault" );
  2359. event.preventDefault();
  2360. } )
  2361. .on( "simulated", function( event ) {
  2362. spy.stop = sinon.stub( event.originalEvent, "stopPropagation" );
  2363. event.stopPropagation();
  2364. } )
  2365. .on( "simulated", function( event ) {
  2366. spy.immediate = sinon.stub( event.originalEvent, "stopImmediatePropagation" );
  2367. event.stopImmediatePropagation();
  2368. } )
  2369. .on( "simulated", function( event ) {
  2370. assert.ok( false, "simulated event immediate propagation stopped" );
  2371. } );
  2372. outer
  2373. .on( "simulated", function( event ) {
  2374. assert.ok( false, "simulated event propagation stopped" );
  2375. } );
  2376. // Force a simulated event
  2377. input[ 0 ].addEventListener( "click", function( nativeEvent ) {
  2378. jQuery.event.simulate( "simulated", this, jQuery.event.fix( nativeEvent ) );
  2379. } );
  2380. input[ 0 ].click();
  2381. assert.strictEqual( spy.prevent.called, false, "Native preventDefault not called" );
  2382. assert.strictEqual( spy.stop.called, false, "Native stopPropagation not called" );
  2383. assert.strictEqual( spy.immediate.called, false,
  2384. "Native stopImmediatePropagation not called" );
  2385. }
  2386. );
  2387. QUnit.test( "originalEvent type of simulated event", function( assert ) {
  2388. assert.expect( 2 );
  2389. var outer = jQuery(
  2390. "<div id='donor-outer'>" +
  2391. "<form id='donor-form'>" +
  2392. "<input id='donor-input' type='text' />" +
  2393. "</form>" +
  2394. "</div>"
  2395. ).appendTo( "#qunit-fixture" ),
  2396. input = jQuery( "#donor-input" ),
  2397. done = assert.async(),
  2398. finish = function() {
  2399. // Remove jQuery handlers to ensure removal of capturing handlers on the document
  2400. outer.off( "focusin" );
  2401. done();
  2402. };
  2403. outer.on( "focusin", function( event ) {
  2404. assert.equal( event.type, "focusin", "focusin event at ancestor" );
  2405. assert.equal( event.originalEvent.type, "click",
  2406. "focus event at ancestor has correct originalEvent type" );
  2407. setTimeout( finish );
  2408. } );
  2409. input[ 0 ].addEventListener( "click", function( nativeEvent ) {
  2410. jQuery.event.simulate( "focusin", this, jQuery.event.fix( nativeEvent ) );
  2411. } );
  2412. input[ 0 ].click();
  2413. } );
  2414. QUnit.test( "trigger('click') on radio passes extra params", function( assert ) {
  2415. assert.expect( 1 );
  2416. var $radio = jQuery( "<input type='radio' />" ).appendTo( "#qunit-fixture" )
  2417. .on( "click", function( e, data ) {
  2418. assert.ok( data, "Trigger data is passed to radio click handler" );
  2419. } );
  2420. $radio.trigger( "click", [ true ] );
  2421. } );
  2422. // Support: IE <=9 only
  2423. // https://msdn.microsoft.com/en-us/library/hh801223(v=vs.85).aspx
  2424. QUnit.test( "VML with special event handlers (trac-7071)", function( assert ) {
  2425. assert.expect( 1 );
  2426. var ns = jQuery( "<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />" ).appendTo( "head" );
  2427. jQuery( "<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>" ).appendTo( "#form" );
  2428. jQuery( "#form" ).on( "keydown", function() {
  2429. assert.ok( true, "no error was thrown" );
  2430. } );
  2431. jQuery( "#oval" ).trigger( "click" ).trigger( "keydown" );
  2432. ns.remove();
  2433. } );
  2434. QUnit.test( "Check order of focusin/focusout events", function( assert ) {
  2435. assert.expect( 2 );
  2436. var focus, blur,
  2437. input = jQuery( "#name" );
  2438. input
  2439. .on( "focus", function() {
  2440. focus = true;
  2441. } )
  2442. .on( "focusin", function() {
  2443. assert.ok( !focus, "Focusin event should fire before focus does" );
  2444. focus = true;
  2445. } )
  2446. .on( "blur", function() {
  2447. blur = true;
  2448. } )
  2449. .on( "focusout", function() {
  2450. assert.ok( !blur, "Focusout event should fire before blur does" );
  2451. blur = true;
  2452. } );
  2453. // gain focus
  2454. input.trigger( "focus" );
  2455. // then lose it
  2456. jQuery( "#search" ).trigger( "focus" );
  2457. // cleanup
  2458. input.off();
  2459. // DOM focus is unreliable in TestSwarm
  2460. if ( !focus ) {
  2461. assert.ok( true, "GAP: Could not observe focus change" );
  2462. assert.ok( true, "GAP: Could not observe focus change" );
  2463. }
  2464. } );
  2465. QUnit.test( "focus-blur order (#12868)", function( assert ) {
  2466. assert.expect( 5 );
  2467. var order,
  2468. $text = jQuery( "#text1" ),
  2469. $radio = jQuery( "#radio1" ),
  2470. // Support: IE <=9 - 11+
  2471. // focus and blur events are asynchronous; this is the resulting mess.
  2472. // The browser window must be topmost for this to work properly!!
  2473. done = assert.async();
  2474. $radio[ 0 ].focus();
  2475. setTimeout( function() {
  2476. $text
  2477. .on( "focus", function() {
  2478. assert.equal( order++, 1, "text focus" );
  2479. } )
  2480. .on( "blur", function() {
  2481. assert.equal( order++, 0, "text blur" );
  2482. } );
  2483. $radio
  2484. .on( "focus", function() {
  2485. assert.equal( order++, 1, "radio focus" );
  2486. } )
  2487. .on( "blur", function() {
  2488. assert.equal( order++, 0, "radio blur" );
  2489. } );
  2490. // Enabled input getting focus
  2491. order = 0;
  2492. assert.equal( document.activeElement, $radio[ 0 ], "radio has focus" );
  2493. $text.trigger( "focus" );
  2494. setTimeout( function() {
  2495. // DOM focus is unreliable in TestSwarm
  2496. if ( order === 0 ) {
  2497. assert.ok( true, "GAP: Could not observe focus change" );
  2498. assert.ok( true, "GAP: Could not observe focus change" );
  2499. }
  2500. assert.equal( document.activeElement, $text[ 0 ], "text has focus" );
  2501. // Run handlers without native method on an input
  2502. order = 1;
  2503. $radio.triggerHandler( "focus" );
  2504. // Clean up
  2505. $text.off();
  2506. $radio.off();
  2507. done();
  2508. }, 50 );
  2509. }, 50 );
  2510. } );
  2511. QUnit.test( "Event handling works with multiple async focus events (gh-4350)", function( assert ) {
  2512. assert.expect( 3 );
  2513. var remaining = 3,
  2514. input = jQuery( "#name" ),
  2515. // Support: IE <=9 - 11+
  2516. // focus and blur events are asynchronous; this is the resulting mess.
  2517. // The browser window must be topmost for this to work properly!!
  2518. done = assert.async();
  2519. input
  2520. .on( "focus", function() {
  2521. remaining--;
  2522. assert.ok( true, "received focus event, expecting " + remaining + " more" );
  2523. if ( remaining > 0 ) {
  2524. input.trigger( "blur" );
  2525. } else {
  2526. done();
  2527. }
  2528. } )
  2529. .on( "blur", function() {
  2530. setTimeout( function() {
  2531. input.trigger( "focus" );
  2532. } );
  2533. } );
  2534. // gain focus
  2535. input.trigger( "focus" );
  2536. // DOM focus is unreliable in TestSwarm
  2537. setTimeout( function() {
  2538. if ( QUnit.isSwarm && remaining === 3 ) {
  2539. assert.ok( true, "GAP: Could not observe focus change" );
  2540. assert.ok( true, "GAP: Could not observe focus change" );
  2541. assert.ok( true, "GAP: Could not observe focus change" );
  2542. setTimeout( function() {
  2543. done();
  2544. } );
  2545. }
  2546. } );
  2547. } );
  2548. QUnit.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", function( assert ) {
  2549. assert.expect( 17 );
  2550. var parent = supportjQuery(
  2551. "<div class='parent'><input type='checkbox'><input type='radio'></div>"
  2552. ).appendTo( "#qunit-fixture" ),
  2553. targets = jQuery( parent[ 0 ].childNodes ),
  2554. checkbox = jQuery( targets[ 0 ] ),
  2555. data = [ "arg1", "arg2" ],
  2556. slice = data.slice,
  2557. // Support: IE <=9 - 11+
  2558. // focus and blur events are asynchronous; this is the resulting mess.
  2559. // The browser window must be topmost for this to work properly!!
  2560. done = assert.async();
  2561. // click (gh-4139)
  2562. assert.strictEqual( targets[ 0 ].checked, false, "checkbox unchecked before click" );
  2563. assert.strictEqual( targets[ 1 ].checked, false, "radio unchecked before click" );
  2564. targets.add( parent ).on( "click", function( event ) {
  2565. var type = event.target.type,
  2566. level = event.currentTarget === parent[ 0 ] ? "parent" : "";
  2567. assert.strictEqual( event.target.checked, true,
  2568. type + " toggled before invoking " + level + " handler" );
  2569. assert.deepEqual( slice.call( arguments, 1 ), data,
  2570. type + " " + level + " handler received correct data" );
  2571. } );
  2572. targets.trigger( "click", data );
  2573. assert.strictEqual( targets[ 0 ].checked, true,
  2574. "checkbox toggled after click (default action)" );
  2575. assert.strictEqual( targets[ 1 ].checked, true,
  2576. "radio toggled after event (default action)" );
  2577. // focus (gh-1741)
  2578. assert.notEqual( document.activeElement, checkbox[ 0 ],
  2579. "element not focused before focus event" );
  2580. checkbox.on( "focus blur", function( event ) {
  2581. var type = event.type;
  2582. assert.deepEqual( slice.call( arguments, 1 ), data,
  2583. type + " handler received correct data" );
  2584. } );
  2585. checkbox.trigger( "focus", data );
  2586. setTimeout( function() {
  2587. assert.strictEqual( document.activeElement, checkbox[ 0 ],
  2588. "element focused after focus event (default action)" );
  2589. checkbox.trigger( "blur", data );
  2590. setTimeout( function() {
  2591. assert.notEqual( document.activeElement, checkbox[ 0 ],
  2592. "element not focused after blur event (default action)" );
  2593. done();
  2594. }, 50 );
  2595. }, 50 );
  2596. } );
  2597. QUnit.test( "focus change during a focus handler (gh-4382)", function( assert ) {
  2598. assert.expect( 2 );
  2599. var done = assert.async(),
  2600. select = jQuery( "<select><option selected='selected'>A</option></select>" ),
  2601. button = jQuery( "<button>Focus target</button>" );
  2602. jQuery( "#qunit-fixture" )
  2603. .append( select )
  2604. .append( button );
  2605. select.on( "focus", function() {
  2606. button.trigger( "focus" );
  2607. } );
  2608. jQuery( document ).on( "focusin.focusTests", function( ev ) {
  2609. // Support: IE 11+
  2610. // In IE focus is async so focusin on document is fired multiple times,
  2611. // for each of the elements. In other browsers it's fired just once, for
  2612. // the last one.
  2613. if ( ev.target === button[ 0 ] ) {
  2614. assert.ok( true, "focusin propagated to document from the button" );
  2615. }
  2616. } );
  2617. select.trigger( "focus" );
  2618. setTimeout( function() {
  2619. assert.strictEqual( document.activeElement, button[ 0 ], "Focus redirect worked" );
  2620. jQuery( document ).off( ".focusTests" );
  2621. done();
  2622. } );
  2623. } );
  2624. // TODO replace with an adaptation of
  2625. // https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464
  2626. ( function() {
  2627. supportjQuery.each(
  2628. {
  2629. checkbox: "<input type='checkbox'>",
  2630. radio: "<input type='radio'>"
  2631. },
  2632. makeTestFor3751
  2633. );
  2634. function makeTestFor3751( type, html ) {
  2635. var testName = "native-backed namespaced clicks are handled correctly (gh-3751) - " + type;
  2636. QUnit.test( testName, function( assert ) {
  2637. assert.expect( 2 );
  2638. var parent = supportjQuery( "<div class='parent'>" + html + "</div>" ),
  2639. target = jQuery( parent[ 0 ].firstChild );
  2640. parent.appendTo( "#qunit-fixture" );
  2641. target.add( parent )
  2642. .on( "click.notFired", function( event ) {
  2643. assert.ok( false, "namespaced event should not be received" +
  2644. " by wrong-namespace listener at " + event.currentTarget.nodeName );
  2645. } )
  2646. .on( "click.fired", function( event ) {
  2647. assert.equal( event.target.checked, true,
  2648. "toggled before invoking handler at " + event.currentTarget.nodeName );
  2649. } )
  2650. .on( "click", function( event ) {
  2651. assert.ok( false, "namespaced event should not be received" +
  2652. " by non-namespaced listener at " + event.currentTarget.nodeName );
  2653. } );
  2654. target.trigger( "click.fired" );
  2655. } );
  2656. }
  2657. } )();