dropdown.js 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. $(function () {
  2. 'use strict'
  3. QUnit.module('dropdowns plugin')
  4. QUnit.test('should be defined on jquery object', function (assert) {
  5. assert.expect(1)
  6. assert.ok($(document.body).dropdown, 'dropdown method is defined')
  7. })
  8. QUnit.module('dropdowns', {
  9. beforeEach: function () {
  10. // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
  11. $.fn.bootstrapDropdown = $.fn.dropdown.noConflict()
  12. },
  13. afterEach: function () {
  14. $.fn.dropdown = $.fn.bootstrapDropdown
  15. delete $.fn.bootstrapDropdown
  16. $('#qunit-fixture').html('')
  17. }
  18. })
  19. QUnit.test('should provide no conflict', function (assert) {
  20. assert.expect(1)
  21. assert.strictEqual(typeof $.fn.dropdown, 'undefined', 'dropdown was set back to undefined (org value)')
  22. })
  23. QUnit.test('should throw explicit error on undefined method', function (assert) {
  24. assert.expect(1)
  25. var $el = $('<div/>')
  26. $el.bootstrapDropdown()
  27. try {
  28. $el.bootstrapDropdown('noMethod')
  29. } catch (err) {
  30. assert.strictEqual(err.message, 'No method named "noMethod"')
  31. }
  32. })
  33. QUnit.test('should return jquery collection containing the element', function (assert) {
  34. assert.expect(2)
  35. var $el = $('<div/>')
  36. var $dropdown = $el.bootstrapDropdown()
  37. assert.ok($dropdown instanceof $, 'returns jquery collection')
  38. assert.strictEqual($dropdown[0], $el[0], 'collection contains element')
  39. })
  40. QUnit.test('should not open dropdown if target is disabled via attribute', function (assert) {
  41. assert.expect(1)
  42. var done = assert.async()
  43. var dropdownHTML = '<div class="tabs">' +
  44. '<div class="dropdown">' +
  45. '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' +
  46. '<div class="dropdown-menu">' +
  47. '<a class="dropdown-item" href="#">Secondary link</a>' +
  48. '<a class="dropdown-item" href="#">Something else here</a>' +
  49. '<div class="divider"/>' +
  50. '<a class="dropdown-item" href="#">Another link</a>' +
  51. '</div>' +
  52. '</div>' +
  53. '</div>'
  54. $(dropdownHTML).appendTo('#qunit-fixture')
  55. var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
  56. $dropdown.on('click', function () {
  57. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
  58. done()
  59. })
  60. $dropdown.trigger($.Event('click'))
  61. })
  62. QUnit.test('should not add class position-static to dropdown if boundary not set', function (assert) {
  63. assert.expect(1)
  64. var done = assert.async()
  65. var dropdownHTML = '<div class="tabs">' +
  66. '<div class="dropdown">' +
  67. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  68. '<div class="dropdown-menu">' +
  69. '<a class="dropdown-item" href="#">Secondary link</a>' +
  70. '<a class="dropdown-item" href="#">Something else here</a>' +
  71. '</div>' +
  72. '</div>' +
  73. '</div>'
  74. var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
  75. $dropdown
  76. .parent('.dropdown')
  77. .on('shown.bs.dropdown', function () {
  78. assert.ok(!$dropdown.parent('.dropdown').hasClass('position-static'), '"position-static" class not added')
  79. done()
  80. })
  81. $dropdown.trigger('click')
  82. })
  83. QUnit.test('should add class position-static to dropdown if boundary not scrollParent', function (assert) {
  84. assert.expect(1)
  85. var done = assert.async()
  86. var dropdownHTML = '<div class="tabs">' +
  87. '<div class="dropdown">' +
  88. '<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-boundary="viewport">Dropdown</a>' +
  89. '<div class="dropdown-menu">' +
  90. '<a class="dropdown-item" href="#">Secondary link</a>' +
  91. '<a class="dropdown-item" href="#">Something else here</a>' +
  92. '</div>' +
  93. '</div>' +
  94. '</div>'
  95. var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
  96. $dropdown
  97. .parent('.dropdown')
  98. .on('shown.bs.dropdown', function () {
  99. assert.ok($dropdown.parent('.dropdown').hasClass('position-static'), '"position-static" class added')
  100. done()
  101. })
  102. $dropdown.trigger('click')
  103. })
  104. QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) {
  105. assert.expect(1)
  106. var done = assert.async()
  107. var dropdownHTML = '<div class="tabs">' +
  108. '<div class="dropdown">' +
  109. '<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">Dropdown</a>' +
  110. '<div class="dropdown-menu">' +
  111. '<a class="dropdown-item" href="#">Secondary link</a>' +
  112. '<a class="dropdown-item" href="#">Something else here</a>' +
  113. '<div class="divider"/>' +
  114. '<a class="dropdown-item" href="#">Another link</a>' +
  115. '</div>' +
  116. '</div>' +
  117. '</div>'
  118. var $dropdown = $(dropdownHTML)
  119. .appendTo('#qunit-fixture')
  120. .find('[data-toggle="dropdown"]')
  121. .bootstrapDropdown()
  122. $dropdown
  123. .parent('.dropdown')
  124. .on('shown.bs.dropdown', function () {
  125. assert.strictEqual($dropdown.attr('aria-expanded'), 'true', 'aria-expanded is set to string "true" on click')
  126. done()
  127. })
  128. $dropdown.trigger('click')
  129. })
  130. QUnit.test('should set aria-expanded="false" on target when dropdown menu is hidden', function (assert) {
  131. assert.expect(1)
  132. var done = assert.async()
  133. var dropdownHTML = '<div class="tabs">' +
  134. '<div class="dropdown">' +
  135. '<a href="#" class="dropdown-toggle" aria-expanded="false" data-toggle="dropdown">Dropdown</a>' +
  136. '<div class="dropdown-menu">' +
  137. '<a class="dropdown-item" href="#">Secondary link</a>' +
  138. '<a class="dropdown-item" href="#">Something else here</a>' +
  139. '<div class="divider"/>' +
  140. '<a class="dropdown-item" href="#">Another link</a>' +
  141. '</div>' +
  142. '</div>' +
  143. '</div>'
  144. var $dropdown = $(dropdownHTML)
  145. .appendTo('#qunit-fixture')
  146. .find('[data-toggle="dropdown"]')
  147. .bootstrapDropdown()
  148. $dropdown
  149. .parent('.dropdown')
  150. .on('hidden.bs.dropdown', function () {
  151. assert.strictEqual($dropdown.attr('aria-expanded'), 'false', 'aria-expanded is set to string "false" on hide')
  152. done()
  153. })
  154. $dropdown.trigger('click')
  155. $(document.body).trigger('click')
  156. })
  157. QUnit.test('should not open dropdown if target is disabled via class', function (assert) {
  158. assert.expect(1)
  159. var done = assert.async()
  160. var dropdownHTML = '<div class="tabs">' +
  161. '<div class="dropdown">' +
  162. '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' +
  163. '<div class="dropdown-menu">' +
  164. '<a class="dropdown-item" href="#">Secondary link</a>' +
  165. '<a class="dropdown-item" href="#">Something else here</a>' +
  166. '<div class="divider"/>' +
  167. '<a class="dropdown-item" href="#">Another link</a>' +
  168. '</div>' +
  169. '</div>' +
  170. '</div>'
  171. $(dropdownHTML).appendTo('#qunit-fixture')
  172. var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
  173. $dropdown.on('click', function () {
  174. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
  175. done()
  176. })
  177. $dropdown.trigger($.Event('click'))
  178. })
  179. QUnit.test('should add class show to menu if clicked', function (assert) {
  180. assert.expect(1)
  181. var done = assert.async()
  182. var dropdownHTML = '<div class="tabs">' +
  183. '<div class="dropdown">' +
  184. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  185. '<div class="dropdown-menu">' +
  186. '<a class="dropdown-item" href="#">Secondary link</a>' +
  187. '<a class="dropdown-item" href="#">Something else here</a>' +
  188. '<div class="divider"/>' +
  189. '<a class="dropdown-item" href="#">Another link</a>' +
  190. '</div>' +
  191. '</div>' +
  192. '</div>'
  193. var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
  194. $dropdown
  195. .parent('.dropdown')
  196. .on('shown.bs.dropdown', function () {
  197. assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
  198. done()
  199. })
  200. $dropdown.trigger('click')
  201. })
  202. QUnit.test('should remove "show" class if body is clicked', function (assert) {
  203. assert.expect(2)
  204. var done = assert.async()
  205. var dropdownHTML = '<div class="tabs">' +
  206. '<div class="dropdown">' +
  207. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  208. '<div class="dropdown-menu">' +
  209. '<a class="dropdown-item" href="#">Secondary link</a>' +
  210. '<a class="dropdown-item" href="#">Something else here</a>' +
  211. '<div class="divider"/>' +
  212. '<a class="dropdown-item" href="#">Another link</a>' +
  213. '</div>' +
  214. '</div>' +
  215. '</div>'
  216. var $dropdown = $(dropdownHTML)
  217. .appendTo('#qunit-fixture')
  218. .find('[data-toggle="dropdown"]')
  219. .bootstrapDropdown()
  220. $dropdown
  221. .parent('.dropdown')
  222. .on('shown.bs.dropdown', function () {
  223. assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
  224. $(document.body).trigger('click')
  225. }).on('hidden.bs.dropdown', function () {
  226. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
  227. done()
  228. })
  229. $dropdown.trigger('click')
  230. })
  231. QUnit.test('should remove "show" class if tabbing outside of menu', function (assert) {
  232. assert.expect(2)
  233. var done = assert.async()
  234. var dropdownHTML = '<div class="tabs">' +
  235. '<div class="dropdown">' +
  236. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  237. '<div class="dropdown-menu">' +
  238. '<a class="dropdown-item" href="#">Secondary link</a>' +
  239. '<a class="dropdown-item" href="#">Something else here</a>' +
  240. '<div class="dropdown-divider"/>' +
  241. '<a class="dropdown-item" href="#">Another link</a>' +
  242. '</div>' +
  243. '</div>' +
  244. '</div>'
  245. var $dropdown = $(dropdownHTML)
  246. .appendTo('#qunit-fixture')
  247. .find('[data-toggle="dropdown"]')
  248. .bootstrapDropdown()
  249. $dropdown
  250. .parent('.dropdown')
  251. .on('shown.bs.dropdown', function () {
  252. assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
  253. var e = $.Event('keyup')
  254. e.which = 9 // Tab
  255. $(document.body).trigger(e)
  256. }).on('hidden.bs.dropdown', function () {
  257. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
  258. done()
  259. })
  260. $dropdown.trigger('click')
  261. })
  262. QUnit.test('should remove "show" class if body is clicked, with multiple dropdowns', function (assert) {
  263. assert.expect(7)
  264. var done = assert.async()
  265. var dropdownHTML = '<div class="nav">' +
  266. '<div class="dropdown" id="testmenu">' +
  267. '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>' +
  268. '<div class="dropdown-menu">' +
  269. '<a class="dropdown-item" href="#sub1">Submenu 1</a>' +
  270. '</div>' +
  271. '</div>' +
  272. '</div>' +
  273. '<div class="btn-group">' +
  274. '<button class="btn">Actions</button>' +
  275. '<button class="btn dropdown-toggle" data-toggle="dropdown"></button>' +
  276. '<div class="dropdown-menu">' +
  277. '<a class="dropdown-item" href="#">Action 1</a>' +
  278. '</div>' +
  279. '</div>'
  280. var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
  281. var $first = $dropdowns.first()
  282. var $last = $dropdowns.last()
  283. assert.strictEqual($dropdowns.length, 2, 'two dropdowns')
  284. $first.parent('.dropdown')
  285. .on('shown.bs.dropdown', function () {
  286. assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
  287. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
  288. $(document.body).trigger('click')
  289. }).on('hidden.bs.dropdown', function () {
  290. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
  291. $last.trigger('click')
  292. })
  293. $last.parent('.btn-group')
  294. .on('shown.bs.dropdown', function () {
  295. assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
  296. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
  297. $(document.body).trigger('click')
  298. }).on('hidden.bs.dropdown', function () {
  299. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
  300. done()
  301. })
  302. $first.trigger('click')
  303. })
  304. QUnit.test('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', function (assert) {
  305. assert.expect(7)
  306. var done = assert.async()
  307. var dropdownHTML = '<div class="nav">' +
  308. '<div class="dropdown" id="testmenu">' +
  309. '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>' +
  310. '<div class="dropdown-menu">' +
  311. '<a class="dropdown-item" href="#sub1">Submenu 1</a>' +
  312. '</div>' +
  313. '</div>' +
  314. '</div>' +
  315. '<div class="btn-group">' +
  316. '<button class="btn">Actions</button>' +
  317. '<button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"/></button>' +
  318. '<div class="dropdown-menu">' +
  319. '<a class="dropdown-item" href="#">Action 1</a>' +
  320. '</div>' +
  321. '</div>'
  322. var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
  323. var $first = $dropdowns.first()
  324. var $last = $dropdowns.last()
  325. assert.strictEqual($dropdowns.length, 2, 'two dropdowns')
  326. $first.parent('.dropdown')
  327. .on('shown.bs.dropdown', function () {
  328. assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
  329. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
  330. var e = $.Event('keyup')
  331. e.which = 9 // Tab
  332. $(document.body).trigger(e)
  333. }).on('hidden.bs.dropdown', function () {
  334. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
  335. $last.trigger('click')
  336. })
  337. $last.parent('.btn-group')
  338. .on('shown.bs.dropdown', function () {
  339. assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
  340. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
  341. var e = $.Event('keyup')
  342. e.which = 9 // Tab
  343. $(document.body).trigger(e)
  344. }).on('hidden.bs.dropdown', function () {
  345. assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
  346. done()
  347. })
  348. $first.trigger('click')
  349. })
  350. QUnit.test('should fire show and hide event', function (assert) {
  351. assert.expect(2)
  352. var dropdownHTML = '<div class="tabs">' +
  353. '<div class="dropdown">' +
  354. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  355. '<div class="dropdown-menu">' +
  356. '<a class="dropdown-item" href="#">Secondary link</a>' +
  357. '<a class="dropdown-item" href="#">Something else here</a>' +
  358. '<div class="divider"/>' +
  359. '<a class="dropdown-item" href="#">Another link</a>' +
  360. '</div>' +
  361. '</div>' +
  362. '</div>'
  363. var $dropdown = $(dropdownHTML)
  364. .appendTo('#qunit-fixture')
  365. .find('[data-toggle="dropdown"]')
  366. .bootstrapDropdown()
  367. var done = assert.async()
  368. $dropdown
  369. .parent('.dropdown')
  370. .on('show.bs.dropdown', function () {
  371. assert.ok(true, 'show was fired')
  372. })
  373. .on('hide.bs.dropdown', function () {
  374. assert.ok(true, 'hide was fired')
  375. done()
  376. })
  377. $dropdown.trigger('click')
  378. $(document.body).trigger('click')
  379. })
  380. QUnit.test('should fire shown and hidden event', function (assert) {
  381. assert.expect(2)
  382. var dropdownHTML = '<div class="tabs">' +
  383. '<div class="dropdown">' +
  384. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  385. '<div class="dropdown-menu">' +
  386. '<a class="dropdown-item" href="#">Secondary link</a>' +
  387. '<a class="dropdown-item" href="#">Something else here</a>' +
  388. '<div class="divider"/>' +
  389. '<a class="dropdown-item" href="#">Another link</a>' +
  390. '</div>' +
  391. '</div>' +
  392. '</div>'
  393. var $dropdown = $(dropdownHTML)
  394. .appendTo('#qunit-fixture')
  395. .find('[data-toggle="dropdown"]')
  396. .bootstrapDropdown()
  397. var done = assert.async()
  398. $dropdown
  399. .parent('.dropdown')
  400. .on('shown.bs.dropdown', function () {
  401. assert.ok(true, 'shown was fired')
  402. })
  403. .on('hidden.bs.dropdown', function () {
  404. assert.ok(true, 'hidden was fired')
  405. done()
  406. })
  407. $dropdown.trigger('click')
  408. $(document.body).trigger('click')
  409. })
  410. QUnit.test('should fire shown and hidden event with a relatedTarget', function (assert) {
  411. assert.expect(2)
  412. var dropdownHTML = '<div class="tabs">' +
  413. '<div class="dropdown">' +
  414. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  415. '<div class="dropdown-menu">' +
  416. '<a class="dropdown-item" href="#">Secondary link</a>' +
  417. '<a class="dropdown-item" href="#">Something else here</a>' +
  418. '<div class="divider"/>' +
  419. '<a class="dropdown-item" href="#">Another link</a>' +
  420. '</div>' +
  421. '</div>' +
  422. '</div>'
  423. var $dropdown = $(dropdownHTML)
  424. .appendTo('#qunit-fixture')
  425. .find('[data-toggle="dropdown"]')
  426. .bootstrapDropdown()
  427. var done = assert.async()
  428. $dropdown.parent('.dropdown')
  429. .on('hidden.bs.dropdown', function (e) {
  430. assert.strictEqual(e.relatedTarget, $dropdown[0])
  431. done()
  432. })
  433. .on('shown.bs.dropdown', function (e) {
  434. assert.strictEqual(e.relatedTarget, $dropdown[0])
  435. $(document.body).trigger('click')
  436. })
  437. $dropdown.trigger('click')
  438. })
  439. QUnit.test('should fire hide and hidden event with a clickEvent', function (assert) {
  440. assert.expect(3)
  441. var dropdownHTML = '<div class="tabs">' +
  442. '<div class="dropdown">' +
  443. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  444. '<div class="dropdown-menu">' +
  445. '<a class="dropdown-item" href="#">Secondary link</a>' +
  446. '<a class="dropdown-item" href="#">Something else here</a>' +
  447. '<div class="divider"/>' +
  448. '<a class="dropdown-item" href="#">Another link</a>' +
  449. '</div>' +
  450. '</div>' +
  451. '</div>'
  452. var $dropdown = $(dropdownHTML)
  453. .appendTo('#qunit-fixture')
  454. .find('[data-toggle="dropdown"]')
  455. .bootstrapDropdown()
  456. $dropdown.parent('.dropdown')
  457. .on('hide.bs.dropdown', function (e) {
  458. assert.ok(e.clickEvent)
  459. })
  460. .on('hidden.bs.dropdown', function (e) {
  461. assert.ok(e.clickEvent)
  462. })
  463. .on('shown.bs.dropdown', function () {
  464. assert.ok(true, 'shown was fired')
  465. $(document.body).trigger('click')
  466. })
  467. $dropdown.trigger('click')
  468. })
  469. QUnit.test('should fire hide and hidden event without a clickEvent if event type is not click', function (assert) {
  470. assert.expect(3)
  471. var dropdownHTML = '<div class="tabs">' +
  472. '<div class="dropdown">' +
  473. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  474. '<div class="dropdown-menu">' +
  475. '<a class="dropdown-item" href="#">Secondary link</a>' +
  476. '<a class="dropdown-item" href="#">Something else here</a>' +
  477. '<div class="divider"/>' +
  478. '<a class="dropdown-item" href="#">Another link</a>' +
  479. '</div>' +
  480. '</div>' +
  481. '</div>'
  482. var $dropdown = $(dropdownHTML)
  483. .appendTo('#qunit-fixture')
  484. .find('[data-toggle="dropdown"]')
  485. .bootstrapDropdown()
  486. $dropdown.parent('.dropdown')
  487. .on('hide.bs.dropdown', function (e) {
  488. assert.notOk(e.clickEvent)
  489. })
  490. .on('hidden.bs.dropdown', function (e) {
  491. assert.notOk(e.clickEvent)
  492. })
  493. .on('shown.bs.dropdown', function () {
  494. assert.ok(true, 'shown was fired')
  495. $dropdown.trigger($.Event('keydown', {
  496. which: 27
  497. }))
  498. })
  499. $dropdown.trigger('click')
  500. })
  501. QUnit.test('should ignore keyboard events within <input>s and <textarea>s', function (assert) {
  502. assert.expect(3)
  503. var done = assert.async()
  504. var dropdownHTML = '<div class="tabs">' +
  505. '<div class="dropdown">' +
  506. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  507. '<div class="dropdown-menu">' +
  508. '<a class="dropdown-item" href="#">Secondary link</a>' +
  509. '<a class="dropdown-item" href="#">Something else here</a>' +
  510. '<div class="divider"/>' +
  511. '<a class="dropdown-item" href="#">Another link</a>' +
  512. '<input type="text" id="input">' +
  513. '<textarea id="textarea"/>' +
  514. '</div>' +
  515. '</div>' +
  516. '</div>'
  517. var $dropdown = $(dropdownHTML)
  518. .appendTo('#qunit-fixture')
  519. .find('[data-toggle="dropdown"]')
  520. .bootstrapDropdown()
  521. var $input = $('#input')
  522. var $textarea = $('#textarea')
  523. $dropdown
  524. .parent('.dropdown')
  525. .on('shown.bs.dropdown', function () {
  526. assert.ok(true, 'shown was fired')
  527. $input.trigger('focus').trigger($.Event('keydown', {
  528. which: 38
  529. }))
  530. assert.ok($(document.activeElement).is($input), 'input still focused')
  531. $textarea.trigger('focus').trigger($.Event('keydown', {
  532. which: 38
  533. }))
  534. assert.ok($(document.activeElement).is($textarea), 'textarea still focused')
  535. done()
  536. })
  537. $dropdown.trigger('click')
  538. })
  539. QUnit.test('should skip disabled element when using keyboard navigation', function (assert) {
  540. assert.expect(3)
  541. var done = assert.async()
  542. var dropdownHTML = '<div class="tabs">' +
  543. '<div class="dropdown">' +
  544. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  545. '<div class="dropdown-menu">' +
  546. '<a class="dropdown-item disabled" href="#">Disabled link</a>' +
  547. '<button class="dropdown-item" type="button" disabled>Disabled button</button>' +
  548. '<a id="item1" class="dropdown-item" href="#">Another link</a>' +
  549. '</div>' +
  550. '</div>' +
  551. '</div>'
  552. var $dropdown = $(dropdownHTML)
  553. .appendTo('#qunit-fixture')
  554. .find('[data-toggle="dropdown"]')
  555. .bootstrapDropdown()
  556. $dropdown
  557. .parent('.dropdown')
  558. .on('shown.bs.dropdown', function () {
  559. assert.ok(true, 'shown was fired')
  560. $dropdown.trigger($.Event('keydown', {
  561. which: 40
  562. }))
  563. $dropdown.trigger($.Event('keydown', {
  564. which: 40
  565. }))
  566. assert.ok(!$(document.activeElement).is('.disabled'), '.disabled is not focused')
  567. assert.ok(!$(document.activeElement).is(':disabled'), ':disabled is not focused')
  568. done()
  569. })
  570. $dropdown.trigger('click')
  571. })
  572. QUnit.test('should focus next/previous element when using keyboard navigation', function (assert) {
  573. assert.expect(4)
  574. var done = assert.async()
  575. var dropdownHTML = '<div class="tabs">' +
  576. '<div class="dropdown">' +
  577. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  578. '<div class="dropdown-menu">' +
  579. '<a id="item1" class="dropdown-item" href="#">A link</a>' +
  580. '<a id="item2" class="dropdown-item" href="#">Another link</a>' +
  581. '</div>' +
  582. '</div>' +
  583. '</div>'
  584. var $dropdown = $(dropdownHTML)
  585. .appendTo('#qunit-fixture')
  586. .find('[data-toggle="dropdown"]')
  587. .bootstrapDropdown()
  588. $dropdown
  589. .parent('.dropdown')
  590. .on('shown.bs.dropdown', function () {
  591. assert.ok(true, 'shown was fired')
  592. $dropdown.trigger($.Event('keydown', {
  593. which: 40
  594. }))
  595. assert.ok($(document.activeElement).is($('#item1')), 'item1 is focused')
  596. $(document.activeElement).trigger($.Event('keydown', {
  597. which: 40
  598. }))
  599. assert.ok($(document.activeElement).is($('#item2')), 'item2 is focused')
  600. $(document.activeElement).trigger($.Event('keydown', {
  601. which: 38
  602. }))
  603. assert.ok($(document.activeElement).is($('#item1')), 'item1 is focused')
  604. done()
  605. })
  606. $dropdown.trigger('click')
  607. })
  608. QUnit.test('should not close the dropdown if the user clicks on a text field', function (assert) {
  609. assert.expect(2)
  610. var done = assert.async()
  611. var dropdownHTML = '<div class="dropdown">' +
  612. '<button type="button" data-toggle="dropdown">Dropdown</button>' +
  613. '<div class="dropdown-menu">' +
  614. '<input id="textField" type="text" />' +
  615. '</div>' +
  616. '</div>'
  617. var $dropdown = $(dropdownHTML)
  618. .appendTo('#qunit-fixture')
  619. .find('[data-toggle="dropdown"]')
  620. .bootstrapDropdown()
  621. var $textfield = $('#textField')
  622. $textfield.on('click', function () {
  623. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  624. done()
  625. })
  626. $dropdown
  627. .parent('.dropdown')
  628. .on('shown.bs.dropdown', function () {
  629. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  630. $textfield.trigger($.Event('click'))
  631. })
  632. $dropdown.trigger('click')
  633. })
  634. QUnit.test('should not close the dropdown if the user clicks on a textarea', function (assert) {
  635. assert.expect(2)
  636. var done = assert.async()
  637. var dropdownHTML = '<div class="dropdown">' +
  638. '<button type="button" data-toggle="dropdown">Dropdown</button>' +
  639. '<div class="dropdown-menu">' +
  640. '<textarea id="textArea"></textarea>' +
  641. '</div>' +
  642. '</div>'
  643. var $dropdown = $(dropdownHTML)
  644. .appendTo('#qunit-fixture')
  645. .find('[data-toggle="dropdown"]')
  646. .bootstrapDropdown()
  647. var $textarea = $('#textArea')
  648. $textarea.on('click', function () {
  649. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  650. done()
  651. })
  652. $dropdown
  653. .parent('.dropdown')
  654. .on('shown.bs.dropdown', function () {
  655. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  656. $textarea.trigger($.Event('click'))
  657. })
  658. $dropdown.trigger('click')
  659. })
  660. QUnit.test('Dropdown should not use Popper.js in navbar', function (assert) {
  661. assert.expect(1)
  662. var done = assert.async()
  663. var html = '<nav class="navbar navbar-expand-md navbar-light bg-light">' +
  664. '<div class="dropdown">' +
  665. ' <a class="nav-link dropdown-toggle" href="#" id="dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>' +
  666. ' <div class="dropdown-menu" aria-labelledby="dropdown">' +
  667. ' <a class="dropdown-item" href="#">Action</a>' +
  668. ' <a class="dropdown-item" href="#">Another action</a>' +
  669. ' <a class="dropdown-item" href="#">Something else here</a>' +
  670. ' </div>' +
  671. '</div>' +
  672. '</nav>'
  673. $(html).appendTo('#qunit-fixture')
  674. var $triggerDropdown = $('#qunit-fixture')
  675. .find('[data-toggle="dropdown"]')
  676. .bootstrapDropdown()
  677. var $dropdownMenu = $triggerDropdown.next()
  678. $triggerDropdown
  679. .parent('.dropdown')
  680. .on('shown.bs.dropdown', function () {
  681. assert.ok(typeof $dropdownMenu.attr('style') === 'undefined', 'No inline style applied by Popper.js')
  682. done()
  683. })
  684. $triggerDropdown.trigger($.Event('click'))
  685. })
  686. QUnit.test('should ignore keyboard events for <input>s and <textarea>s within dropdown-menu, except for escape key', function (assert) {
  687. assert.expect(7)
  688. var done = assert.async()
  689. var dropdownHTML = '<div class="tabs">' +
  690. '<div class="dropdown">' +
  691. '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  692. '<div class="dropdown-menu">' +
  693. '<a class="dropdown-item" href="#">Secondary link</a>' +
  694. '<a class="dropdown-item" href="#">Something else here</a>' +
  695. '<div class="divider"/>' +
  696. '<a class="dropdown-item" href="#">Another link</a>' +
  697. '<input type="text" id="input">' +
  698. '<textarea id="textarea"/>' +
  699. '</div>' +
  700. '</div>' +
  701. '</div>'
  702. var $dropdown = $(dropdownHTML)
  703. .appendTo('#qunit-fixture')
  704. .find('[data-toggle="dropdown"]')
  705. .bootstrapDropdown()
  706. var $input = $('#input')
  707. var $textarea = $('#textarea')
  708. $dropdown
  709. .parent('.dropdown')
  710. .on('shown.bs.dropdown', function () {
  711. // Space key
  712. $input.trigger('focus').trigger($.Event('keydown', {
  713. which: 32
  714. }))
  715. assert.ok($(document.activeElement)[0] === $input[0], 'input still focused')
  716. $textarea.trigger('focus').trigger($.Event('keydown', {
  717. which: 32
  718. }))
  719. assert.ok($(document.activeElement)[0] === $textarea[0], 'textarea still focused')
  720. // Key up
  721. $input.trigger('focus').trigger($.Event('keydown', {
  722. which: 38
  723. }))
  724. assert.ok($(document.activeElement)[0] === $input[0], 'input still focused')
  725. $textarea.trigger('focus').trigger($.Event('keydown', {
  726. which: 38
  727. }))
  728. assert.ok($(document.activeElement)[0] === $textarea[0], 'textarea still focused')
  729. // Key down
  730. $input.trigger('focus').trigger($.Event('keydown', {
  731. which: 40
  732. }))
  733. assert.ok($(document.activeElement)[0] === $input[0], 'input still focused')
  734. $textarea.trigger('focus').trigger($.Event('keydown', {
  735. which: 40
  736. }))
  737. assert.ok($(document.activeElement)[0] === $textarea[0], 'textarea still focused')
  738. // Key escape
  739. $input.trigger('focus').trigger($.Event('keydown', {
  740. which: 27
  741. }))
  742. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is not shown')
  743. done()
  744. })
  745. $dropdown.trigger('click')
  746. })
  747. QUnit.test('should ignore space key events for <input>s within dropdown, and accept up, down and escape', function (assert) {
  748. assert.expect(6)
  749. var done = assert.async()
  750. var dropdownHTML =
  751. '<ul class="nav tabs">' +
  752. ' <li class="dropdown">' +
  753. ' <input type="text" id="input" data-toggle="dropdown">' +
  754. ' <div class="dropdown-menu" role="menu">' +
  755. ' <a id="item1" class="dropdown-item" href="#">Secondary link</a>' +
  756. ' <a id="item2" class="dropdown-item" href="#">Something else here</a>' +
  757. ' <div class="divider"></div>' +
  758. ' <a class="dropdown-item" href="#">Another link</a>' +
  759. ' </div>' +
  760. ' </li>' +
  761. '</ul>'
  762. var $dropdown = $(dropdownHTML)
  763. .appendTo('#qunit-fixture')
  764. .find('[data-toggle="dropdown"]')
  765. .bootstrapDropdown()
  766. var $input = $('#input')
  767. $dropdown
  768. .parent('.dropdown')
  769. .one('shown.bs.dropdown', function () {
  770. assert.ok(true, 'shown was fired')
  771. // Key space
  772. $input.trigger('focus').trigger($.Event('keydown', {
  773. which: 32
  774. }))
  775. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  776. assert.ok($(document.activeElement).is($input), 'input is still focused')
  777. // Key escape
  778. $input.trigger('focus').trigger($.Event('keydown', {
  779. which: 27
  780. }))
  781. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is not shown')
  782. $dropdown
  783. .parent('.dropdown')
  784. .one('shown.bs.dropdown', function () {
  785. // Key down
  786. $input.trigger('focus').trigger($.Event('keydown', {
  787. which: 40
  788. }))
  789. assert.ok(document.activeElement === $('#item1')[0], 'item1 is focused')
  790. $dropdown
  791. .parent('.dropdown')
  792. .one('shown.bs.dropdown', function () {
  793. // Key up
  794. $input.trigger('focus').trigger($.Event('keydown', {
  795. which: 38
  796. }))
  797. assert.ok(document.activeElement === $('#item1')[0], 'item1 is focused')
  798. done()
  799. }).bootstrapDropdown('toggle')
  800. $input.trigger('click')
  801. })
  802. $input.trigger('click')
  803. })
  804. $input.trigger('click')
  805. })
  806. QUnit.test('should ignore space key events for <textarea>s within dropdown, and accept up, down and escape', function (assert) {
  807. assert.expect(6)
  808. var done = assert.async()
  809. var dropdownHTML =
  810. '<ul class="nav tabs">' +
  811. ' <li class="dropdown">' +
  812. ' <textarea id="textarea" data-toggle="dropdown"></textarea>' +
  813. ' <div class="dropdown-menu" role="menu">' +
  814. ' <a id="item1" class="dropdown-item" href="#">Secondary link</a>' +
  815. ' <a id="item2" class="dropdown-item" href="#">Something else here</a>' +
  816. ' <div class="divider"></div>' +
  817. ' <a class="dropdown-item" href="#">Another link</a>' +
  818. ' </div>' +
  819. ' </li>' +
  820. '</ul>'
  821. var $dropdown = $(dropdownHTML)
  822. .appendTo('#qunit-fixture')
  823. .find('[data-toggle="dropdown"]')
  824. .bootstrapDropdown()
  825. var $textarea = $('#textarea')
  826. $dropdown
  827. .parent('.dropdown')
  828. .one('shown.bs.dropdown', function () {
  829. assert.ok(true, 'shown was fired')
  830. // Key space
  831. $textarea.trigger('focus').trigger($.Event('keydown', {
  832. which: 32
  833. }))
  834. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  835. assert.ok($(document.activeElement).is($textarea), 'textarea is still focused')
  836. // Key escape
  837. $textarea.trigger('focus').trigger($.Event('keydown', {
  838. which: 27
  839. }))
  840. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is not shown')
  841. $dropdown
  842. .parent('.dropdown')
  843. .one('shown.bs.dropdown', function () {
  844. // Key down
  845. $textarea.trigger('focus').trigger($.Event('keydown', {
  846. which: 40
  847. }))
  848. assert.ok(document.activeElement === $('#item1')[0], 'item1 is focused')
  849. $dropdown
  850. .parent('.dropdown')
  851. .one('shown.bs.dropdown', function () {
  852. // Key up
  853. $textarea.trigger('focus').trigger($.Event('keydown', {
  854. which: 38
  855. }))
  856. assert.ok(document.activeElement === $('#item1')[0], 'item1 is focused')
  857. done()
  858. }).bootstrapDropdown('toggle')
  859. $textarea.trigger('click')
  860. })
  861. $textarea.trigger('click')
  862. })
  863. $textarea.trigger('click')
  864. })
  865. QUnit.test('should not use Popper.js if display set to static', function (assert) {
  866. assert.expect(1)
  867. var dropdownHTML =
  868. '<div class="dropdown">' +
  869. '<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-display="static">Dropdown</a>' +
  870. '<div class="dropdown-menu">' +
  871. '<a class="dropdown-item" href="#">Secondary link</a>' +
  872. '<a class="dropdown-item" href="#">Something else here</a>' +
  873. '<div class="divider"/>' +
  874. '<a class="dropdown-item" href="#">Another link</a>' +
  875. '</div>' +
  876. '</div>'
  877. var $dropdown = $(dropdownHTML)
  878. .appendTo('#qunit-fixture')
  879. .find('[data-toggle="dropdown"]')
  880. .bootstrapDropdown()
  881. var done = assert.async()
  882. var dropdownMenu = $dropdown.next()[0]
  883. $dropdown.parent('.dropdown')
  884. .on('shown.bs.dropdown', function () {
  885. // Popper.js add this attribute when we use it
  886. assert.strictEqual(dropdownMenu.getAttribute('x-placement'), null)
  887. done()
  888. })
  889. $dropdown.trigger('click')
  890. })
  891. QUnit.test('should call Popper.js and detect navbar on update', function (assert) {
  892. assert.expect(3)
  893. var dropdownHTML =
  894. '<div class="dropdown">' +
  895. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  896. ' <div class="dropdown-menu">' +
  897. ' <a class="dropdown-item" href="#">Another link</a>' +
  898. ' </div>' +
  899. '</div>'
  900. var $dropdown = $(dropdownHTML)
  901. .appendTo('#qunit-fixture')
  902. .find('[data-toggle="dropdown"]')
  903. .bootstrapDropdown()
  904. var dropdown = $dropdown.data('bs.dropdown')
  905. dropdown.toggle()
  906. assert.ok(dropdown._popper)
  907. var spyPopper = sinon.spy(dropdown._popper, 'scheduleUpdate')
  908. var spyDetectNavbar = sinon.spy(dropdown, '_detectNavbar')
  909. dropdown.update()
  910. assert.ok(spyPopper.called)
  911. assert.ok(spyDetectNavbar.called)
  912. })
  913. QUnit.test('should just detect navbar on update', function (assert) {
  914. assert.expect(2)
  915. var dropdownHTML =
  916. '<div class="dropdown">' +
  917. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  918. ' <div class="dropdown-menu">' +
  919. ' <a class="dropdown-item" href="#">Another link</a>' +
  920. ' </div>' +
  921. '</div>'
  922. var $dropdown = $(dropdownHTML)
  923. .appendTo('#qunit-fixture')
  924. .find('[data-toggle="dropdown"]')
  925. .bootstrapDropdown()
  926. var dropdown = $dropdown.data('bs.dropdown')
  927. var spyDetectNavbar = sinon.spy(dropdown, '_detectNavbar')
  928. dropdown.update()
  929. assert.notOk(dropdown._popper)
  930. assert.ok(spyDetectNavbar.called)
  931. })
  932. QUnit.test('should dispose dropdown with Popper', function (assert) {
  933. assert.expect(6)
  934. var dropdownHTML =
  935. '<div class="dropdown">' +
  936. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  937. ' <div class="dropdown-menu">' +
  938. ' <a class="dropdown-item" href="#">Another link</a>' +
  939. ' </div>' +
  940. '</div>'
  941. var $dropdown = $(dropdownHTML)
  942. .appendTo('#qunit-fixture')
  943. .find('[data-toggle="dropdown"]')
  944. .bootstrapDropdown()
  945. var dropdown = $dropdown.data('bs.dropdown')
  946. dropdown.toggle()
  947. assert.ok(dropdown._popper)
  948. assert.ok(dropdown._menu !== null)
  949. assert.ok(dropdown._element !== null)
  950. var spyDestroy = sinon.spy(dropdown._popper, 'destroy')
  951. dropdown.dispose()
  952. assert.ok(spyDestroy.called)
  953. assert.ok(dropdown._menu === null)
  954. assert.ok(dropdown._element === null)
  955. })
  956. QUnit.test('should dispose dropdown', function (assert) {
  957. assert.expect(5)
  958. var dropdownHTML =
  959. '<div class="dropdown">' +
  960. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  961. ' <div class="dropdown-menu">' +
  962. ' <a class="dropdown-item" href="#">Another link</a>' +
  963. ' </div>' +
  964. '</div>'
  965. var $dropdown = $(dropdownHTML)
  966. .appendTo('#qunit-fixture')
  967. .find('[data-toggle="dropdown"]')
  968. .bootstrapDropdown()
  969. var dropdown = $dropdown.data('bs.dropdown')
  970. assert.notOk(dropdown._popper)
  971. assert.ok(dropdown._menu !== null)
  972. assert.ok(dropdown._element !== null)
  973. dropdown.dispose()
  974. assert.ok(dropdown._menu === null)
  975. assert.ok(dropdown._element === null)
  976. })
  977. QUnit.test('should show dropdown', function (assert) {
  978. assert.expect(2)
  979. var dropdownHTML =
  980. '<div class="dropdown">' +
  981. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  982. ' <div class="dropdown-menu">' +
  983. ' <a class="dropdown-item" href="#">Another link</a>' +
  984. ' </div>' +
  985. '</div>'
  986. var $dropdown = $(dropdownHTML)
  987. .appendTo('#qunit-fixture')
  988. .find('[data-toggle="dropdown"]')
  989. .bootstrapDropdown()
  990. var dropdown = $dropdown.data('bs.dropdown')
  991. var done = assert.async()
  992. $dropdown
  993. .parent('.dropdown')
  994. .on('show.bs.dropdown', function () {
  995. assert.ok(true, 'show was fired')
  996. })
  997. .on('shown.bs.dropdown', function () {
  998. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  999. done()
  1000. })
  1001. dropdown.show()
  1002. })
  1003. QUnit.test('should hide dropdown', function (assert) {
  1004. assert.expect(2)
  1005. var dropdownHTML =
  1006. '<div class="dropdown">' +
  1007. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1008. ' <div class="dropdown-menu">' +
  1009. ' <a class="dropdown-item" href="#">Another link</a>' +
  1010. ' </div>' +
  1011. '</div>'
  1012. var $dropdown = $(dropdownHTML)
  1013. .appendTo('#qunit-fixture')
  1014. .find('[data-toggle="dropdown"]')
  1015. .bootstrapDropdown()
  1016. var dropdown = $dropdown.data('bs.dropdown')
  1017. var done = assert.async()
  1018. $dropdown.trigger('click')
  1019. $dropdown
  1020. .parent('.dropdown')
  1021. .on('hide.bs.dropdown', function () {
  1022. assert.ok(true, 'hide was fired')
  1023. })
  1024. .on('hidden.bs.dropdown', function () {
  1025. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is hidden')
  1026. done()
  1027. })
  1028. dropdown.hide()
  1029. })
  1030. QUnit.test('should not hide dropdown', function (assert) {
  1031. assert.expect(1)
  1032. var dropdownHTML =
  1033. '<div class="dropdown">' +
  1034. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1035. ' <div class="dropdown-menu">' +
  1036. ' <a class="dropdown-item" href="#">Another link</a>' +
  1037. ' </div>' +
  1038. '</div>'
  1039. var $dropdown = $(dropdownHTML)
  1040. .appendTo('#qunit-fixture')
  1041. .find('[data-toggle="dropdown"]')
  1042. .bootstrapDropdown()
  1043. var dropdown = $dropdown.data('bs.dropdown')
  1044. $dropdown.trigger('click')
  1045. dropdown.show()
  1046. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is still shown')
  1047. })
  1048. QUnit.test('should not show dropdown', function (assert) {
  1049. assert.expect(1)
  1050. var dropdownHTML =
  1051. '<div class="dropdown">' +
  1052. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1053. ' <div class="dropdown-menu">' +
  1054. ' <a class="dropdown-item" href="#">Another link</a>' +
  1055. ' </div>' +
  1056. '</div>'
  1057. var $dropdown = $(dropdownHTML)
  1058. .appendTo('#qunit-fixture')
  1059. .find('[data-toggle="dropdown"]')
  1060. .bootstrapDropdown()
  1061. var dropdown = $dropdown.data('bs.dropdown')
  1062. dropdown.hide()
  1063. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is still hidden')
  1064. })
  1065. QUnit.test('should show dropdown', function (assert) {
  1066. assert.expect(2)
  1067. var dropdownHTML =
  1068. '<div class="dropdown">' +
  1069. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1070. ' <div class="dropdown-menu">' +
  1071. ' <a class="dropdown-item" href="#">Another link</a>' +
  1072. ' </div>' +
  1073. '</div>'
  1074. var $dropdown = $(dropdownHTML)
  1075. .appendTo('#qunit-fixture')
  1076. .find('[data-toggle="dropdown"]')
  1077. .bootstrapDropdown()
  1078. var dropdown = $dropdown.data('bs.dropdown')
  1079. var done = assert.async()
  1080. $dropdown
  1081. .parent('.dropdown')
  1082. .on('show.bs.dropdown', function () {
  1083. assert.ok(true, 'show was fired')
  1084. })
  1085. .on('shown.bs.dropdown', function () {
  1086. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  1087. done()
  1088. })
  1089. dropdown.show()
  1090. })
  1091. QUnit.test('should prevent default event on show method call', function (assert) {
  1092. assert.expect(1)
  1093. var dropdownHTML =
  1094. '<div class="dropdown">' +
  1095. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1096. ' <div class="dropdown-menu">' +
  1097. ' <a class="dropdown-item" href="#">Another link</a>' +
  1098. ' </div>' +
  1099. '</div>'
  1100. var $dropdown = $(dropdownHTML)
  1101. .appendTo('#qunit-fixture')
  1102. .find('[data-toggle="dropdown"]')
  1103. .bootstrapDropdown()
  1104. var dropdown = $dropdown.data('bs.dropdown')
  1105. var done = assert.async()
  1106. $dropdown
  1107. .parent('.dropdown')
  1108. .on('show.bs.dropdown', function (event) {
  1109. event.preventDefault()
  1110. done()
  1111. })
  1112. dropdown.show()
  1113. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is hidden')
  1114. })
  1115. QUnit.test('should prevent default event on hide method call', function (assert) {
  1116. assert.expect(1)
  1117. var dropdownHTML =
  1118. '<div class="dropdown">' +
  1119. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1120. ' <div class="dropdown-menu">' +
  1121. ' <a class="dropdown-item" href="#">Another link</a>' +
  1122. ' </div>' +
  1123. '</div>'
  1124. var $dropdown = $(dropdownHTML)
  1125. .appendTo('#qunit-fixture')
  1126. .find('[data-toggle="dropdown"]')
  1127. .bootstrapDropdown()
  1128. var dropdown = $dropdown.data('bs.dropdown')
  1129. var done = assert.async()
  1130. $dropdown.trigger('click')
  1131. $dropdown
  1132. .parent('.dropdown')
  1133. .on('hide.bs.dropdown', function (event) {
  1134. event.preventDefault()
  1135. done()
  1136. })
  1137. dropdown.hide()
  1138. assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
  1139. })
  1140. QUnit.test('should not open dropdown via show method if target is disabled via attribute', function (assert) {
  1141. assert.expect(1)
  1142. var dropdownHTML =
  1143. '<div class="dropdown">' +
  1144. ' <button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' +
  1145. ' <div class="dropdown-menu">' +
  1146. ' <a class="dropdown-item" href="#">Another link</a>' +
  1147. ' </div>' +
  1148. '</div>'
  1149. $(dropdownHTML).appendTo('#qunit-fixture')
  1150. var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
  1151. $dropdown.show()
  1152. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
  1153. })
  1154. QUnit.test('should not open dropdown via show method if target is disabled via class', function (assert) {
  1155. assert.expect(1)
  1156. var dropdownHTML =
  1157. '<div class="dropdown">' +
  1158. ' <button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' +
  1159. ' <div class="dropdown-menu">' +
  1160. ' <a class="dropdown-item" href="#">Another link</a>' +
  1161. ' </div>' +
  1162. '</div>'
  1163. $(dropdownHTML).appendTo('#qunit-fixture')
  1164. var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
  1165. $dropdown.show()
  1166. assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
  1167. })
  1168. QUnit.test('should not hide dropdown via hide method if target is disabled via attribute', function (assert) {
  1169. assert.expect(1)
  1170. var dropdownHTML =
  1171. '<div class="dropdown show">' +
  1172. ' <button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' +
  1173. ' <div class="dropdown-menu">' +
  1174. ' <a class="dropdown-item" href="#">Another link</a>' +
  1175. ' </div>' +
  1176. '</div>'
  1177. $(dropdownHTML).appendTo('#qunit-fixture')
  1178. var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
  1179. $dropdown.hide()
  1180. assert.ok($dropdown.parent('.dropdown').hasClass('show'))
  1181. })
  1182. QUnit.test('should not hide dropdown via hide method if target is disabled via class', function (assert) {
  1183. assert.expect(1)
  1184. var dropdownHTML =
  1185. '<div class="dropdown show">' +
  1186. ' <button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' +
  1187. ' <div class="dropdown-menu">' +
  1188. ' <a class="dropdown-item" href="#">Another link</a>' +
  1189. ' </div>' +
  1190. '</div>'
  1191. $(dropdownHTML).appendTo('#qunit-fixture')
  1192. var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
  1193. $dropdown.hide()
  1194. assert.ok($dropdown.parent('.dropdown').hasClass('show'))
  1195. })
  1196. QUnit.test('should create offset modifier correctly when offset option is a function', function (assert) {
  1197. assert.expect(2)
  1198. var getOffset = function (offsets) {
  1199. return offsets
  1200. }
  1201. var dropdownHTML =
  1202. '<div class="dropdown">' +
  1203. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1204. ' <div class="dropdown-menu">' +
  1205. ' <a class="dropdown-item" href="#">Another link</a>' +
  1206. ' </div>' +
  1207. '</div>'
  1208. var $dropdown = $(dropdownHTML)
  1209. .appendTo('#qunit-fixture')
  1210. .find('[data-toggle="dropdown"]')
  1211. .bootstrapDropdown({
  1212. offset: getOffset
  1213. })
  1214. var dropdown = $dropdown.data('bs.dropdown')
  1215. var offset = dropdown._getOffset()
  1216. assert.ok(typeof offset.offset === 'undefined')
  1217. assert.ok(typeof offset.fn === 'function')
  1218. })
  1219. QUnit.test('should create offset modifier correctly when offset option is not a function', function (assert) {
  1220. assert.expect(2)
  1221. var dropdownHTML =
  1222. '<div class="dropdown">' +
  1223. ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>' +
  1224. ' <div class="dropdown-menu">' +
  1225. ' <a class="dropdown-item" href="#">Another link</a>' +
  1226. ' </div>' +
  1227. '</div>'
  1228. var myOffset = 42
  1229. var $dropdown = $(dropdownHTML)
  1230. .appendTo('#qunit-fixture')
  1231. .find('[data-toggle="dropdown"]')
  1232. .bootstrapDropdown({
  1233. offset: myOffset
  1234. })
  1235. var dropdown = $dropdown.data('bs.dropdown')
  1236. var offset = dropdown._getOffset()
  1237. assert.strictEqual(offset.offset, myOffset)
  1238. assert.ok(typeof offset.fn === 'undefined')
  1239. })
  1240. })