carousel.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. $(function () {
  2. 'use strict'
  3. window.Carousel = typeof bootstrap !== 'undefined' ? bootstrap.Carousel : Carousel
  4. var originWinPointerEvent = window.PointerEvent
  5. window.MSPointerEvent = null
  6. var supportPointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent)
  7. function clearPointerEvents() {
  8. window.PointerEvent = null
  9. }
  10. function restorePointerEvents() {
  11. window.PointerEvent = originWinPointerEvent
  12. }
  13. var stylesCarousel = [
  14. '<style>',
  15. ' .carousel.pointer-event { -ms-touch-action: none; touch-action: none; }',
  16. '</style>'
  17. ].join('')
  18. QUnit.module('carousel plugin')
  19. QUnit.test('should be defined on jQuery object', function (assert) {
  20. assert.expect(1)
  21. assert.ok($(document.body).carousel, 'carousel method is defined')
  22. })
  23. QUnit.module('carousel', {
  24. beforeEach: function () {
  25. // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
  26. $.fn.bootstrapCarousel = $.fn.carousel.noConflict()
  27. },
  28. afterEach: function () {
  29. $.fn.carousel = $.fn.bootstrapCarousel
  30. delete $.fn.bootstrapCarousel
  31. $('#qunit-fixture').html('')
  32. }
  33. })
  34. QUnit.test('should provide no conflict', function (assert) {
  35. assert.expect(1)
  36. assert.strictEqual(typeof $.fn.carousel, 'undefined', 'carousel was set back to undefined (orig value)')
  37. })
  38. QUnit.test('should return version', function (assert) {
  39. assert.expect(1)
  40. assert.strictEqual(typeof Carousel.VERSION, 'string')
  41. })
  42. QUnit.test('should return default parameters', function (assert) {
  43. assert.expect(1)
  44. var defaultConfig = Carousel.Default
  45. assert.strictEqual(defaultConfig.touch, true)
  46. })
  47. QUnit.test('should throw explicit error on undefined method', function (assert) {
  48. assert.expect(1)
  49. var $el = $('<div/>')
  50. $el.bootstrapCarousel()
  51. try {
  52. $el.bootstrapCarousel('noMethod')
  53. } catch (err) {
  54. assert.strictEqual(err.message, 'No method named "noMethod"')
  55. }
  56. })
  57. QUnit.test('should return jquery collection containing the element', function (assert) {
  58. assert.expect(2)
  59. var $el = $('<div/>')
  60. var $carousel = $el.bootstrapCarousel()
  61. assert.ok($carousel instanceof $, 'returns jquery collection')
  62. assert.strictEqual($carousel[0], $el[0], 'collection contains element')
  63. })
  64. QUnit.test('should type check config options', function (assert) {
  65. assert.expect(2)
  66. var message
  67. var expectedMessage = 'CAROUSEL: Option "interval" provided type "string" but expected type "(number|boolean)".'
  68. var config = {
  69. interval: 'fat sux'
  70. }
  71. try {
  72. $('<div/>').bootstrapCarousel(config)
  73. } catch (err) {
  74. message = err.message
  75. }
  76. assert.ok(message === expectedMessage, 'correct error message')
  77. config = {
  78. keyboard: document.createElement('div')
  79. }
  80. expectedMessage = 'CAROUSEL: Option "keyboard" provided type "element" but expected type "boolean".'
  81. try {
  82. $('<div/>').bootstrapCarousel(config)
  83. } catch (err) {
  84. message = err.message
  85. }
  86. assert.ok(message === expectedMessage, 'correct error message')
  87. })
  88. QUnit.test('should not fire slid when slide is prevented', function (assert) {
  89. assert.expect(1)
  90. var done = assert.async()
  91. $('<div class="carousel"/>')
  92. .on('slide.bs.carousel', function (e) {
  93. e.preventDefault()
  94. assert.ok(true, 'slide event fired')
  95. done()
  96. })
  97. .on('slid.bs.carousel', function () {
  98. assert.ok(false, 'slid event fired')
  99. })
  100. .bootstrapCarousel('next')
  101. })
  102. QUnit.test('should reset when slide is prevented', function (assert) {
  103. assert.expect(6)
  104. var carouselHTML = '<div id="carousel-example-generic" class="carousel slide">' +
  105. '<ol class="carousel-indicators">' +
  106. '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
  107. '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
  108. '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
  109. '</ol>' +
  110. '<div class="carousel-inner">' +
  111. '<div class="carousel-item active">' +
  112. '<div class="carousel-caption"/>' +
  113. '</div>' +
  114. '<div class="carousel-item">' +
  115. '<div class="carousel-caption"/>' +
  116. '</div>' +
  117. '<div class="carousel-item">' +
  118. '<div class="carousel-caption"/>' +
  119. '</div>' +
  120. '</div>' +
  121. '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
  122. '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
  123. '</div>'
  124. var $carousel = $(carouselHTML)
  125. var done = assert.async()
  126. $carousel
  127. .one('slide.bs.carousel', function (e) {
  128. e.preventDefault()
  129. setTimeout(function () {
  130. assert.ok($carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
  131. assert.ok($carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
  132. $carousel.bootstrapCarousel('next')
  133. }, 0)
  134. })
  135. .one('slid.bs.carousel', function () {
  136. setTimeout(function () {
  137. assert.ok(!$carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
  138. assert.ok(!$carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
  139. assert.ok($carousel.find('.carousel-item:nth-child(2)').is('.active'), 'second item active')
  140. assert.ok($carousel.find('.carousel-indicators li:nth-child(2)').is('.active'), 'second indicator active')
  141. done()
  142. }, 0)
  143. })
  144. .bootstrapCarousel('next')
  145. })
  146. QUnit.test('should fire slide event with direction', function (assert) {
  147. assert.expect(4)
  148. var carouselHTML = '<div id="myCarousel" class="carousel slide">' +
  149. '<div class="carousel-inner">' +
  150. '<div class="carousel-item active">' +
  151. '<img alt="">' +
  152. '<div class="carousel-caption">' +
  153. '<h4>First Thumbnail label</h4>' +
  154. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  155. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  156. 'ultricies vehicula ut id elit.</p>' +
  157. '</div>' +
  158. '</div>' +
  159. '<div class="carousel-item">' +
  160. '<img alt="">' +
  161. '<div class="carousel-caption">' +
  162. '<h4>Second Thumbnail label</h4>' +
  163. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  164. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  165. 'ultricies vehicula ut id elit.</p>' +
  166. '</div>' +
  167. '</div>' +
  168. '<div class="carousel-item">' +
  169. '<img alt="">' +
  170. '<div class="carousel-caption">' +
  171. '<h4>Third Thumbnail label</h4>' +
  172. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  173. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  174. 'ultricies vehicula ut id elit.</p>' +
  175. '</div>' +
  176. '</div>' +
  177. '</div>' +
  178. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  179. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  180. '</div>'
  181. var $carousel = $(carouselHTML)
  182. var done = assert.async()
  183. $carousel
  184. .one('slide.bs.carousel', function (e) {
  185. assert.ok(e.direction, 'direction present on next')
  186. assert.strictEqual(e.direction, 'left', 'direction is left on next')
  187. $carousel
  188. .one('slide.bs.carousel', function (e) {
  189. assert.ok(e.direction, 'direction present on prev')
  190. assert.strictEqual(e.direction, 'right', 'direction is right on prev')
  191. done()
  192. })
  193. .bootstrapCarousel('prev')
  194. })
  195. .bootstrapCarousel('next')
  196. })
  197. QUnit.test('should fire slid event with direction', function (assert) {
  198. assert.expect(4)
  199. var carouselHTML = '<div id="myCarousel" class="carousel slide">' +
  200. '<div class="carousel-inner">' +
  201. '<div class="carousel-item active">' +
  202. '<img alt="">' +
  203. '<div class="carousel-caption">' +
  204. '<h4>First Thumbnail label</h4>' +
  205. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  206. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  207. 'ultricies vehicula ut id elit.</p>' +
  208. '</div>' +
  209. '</div>' +
  210. '<div class="carousel-item">' +
  211. '<img alt="">' +
  212. '<div class="carousel-caption">' +
  213. '<h4>Second Thumbnail label</h4>' +
  214. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  215. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  216. 'ultricies vehicula ut id elit.</p>' +
  217. '</div>' +
  218. '</div>' +
  219. '<div class="carousel-item">' +
  220. '<img alt="">' +
  221. '<div class="carousel-caption">' +
  222. '<h4>Third Thumbnail label</h4>' +
  223. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  224. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  225. 'ultricies vehicula ut id elit.</p>' +
  226. '</div>' +
  227. '</div>' +
  228. '</div>' +
  229. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  230. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  231. '</div>'
  232. var $carousel = $(carouselHTML)
  233. var done = assert.async()
  234. $carousel
  235. .one('slid.bs.carousel', function (e) {
  236. assert.ok(e.direction, 'direction present on next')
  237. assert.strictEqual(e.direction, 'left', 'direction is left on next')
  238. $carousel
  239. .one('slid.bs.carousel', function (e) {
  240. assert.ok(e.direction, 'direction present on prev')
  241. assert.strictEqual(e.direction, 'right', 'direction is right on prev')
  242. done()
  243. })
  244. .bootstrapCarousel('prev')
  245. })
  246. .bootstrapCarousel('next')
  247. })
  248. QUnit.test('should fire slide event with relatedTarget', function (assert) {
  249. assert.expect(2)
  250. var template = '<div id="myCarousel" class="carousel slide">' +
  251. '<div class="carousel-inner">' +
  252. '<div class="carousel-item active">' +
  253. '<img alt="">' +
  254. '<div class="carousel-caption">' +
  255. '<h4>First Thumbnail label</h4>' +
  256. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  257. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  258. 'ultricies vehicula ut id elit.</p>' +
  259. '</div>' +
  260. '</div>' +
  261. '<div class="carousel-item">' +
  262. '<img alt="">' +
  263. '<div class="carousel-caption">' +
  264. '<h4>Second Thumbnail label</h4>' +
  265. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  266. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  267. 'ultricies vehicula ut id elit.</p>' +
  268. '</div>' +
  269. '</div>' +
  270. '<div class="carousel-item">' +
  271. '<img alt="">' +
  272. '<div class="carousel-caption">' +
  273. '<h4>Third Thumbnail label</h4>' +
  274. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  275. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  276. 'ultricies vehicula ut id elit.</p>' +
  277. '</div>' +
  278. '</div>' +
  279. '</div>' +
  280. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  281. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  282. '</div>'
  283. var done = assert.async()
  284. $(template)
  285. .on('slide.bs.carousel', function (e) {
  286. assert.ok(e.relatedTarget, 'relatedTarget present')
  287. assert.ok($(e.relatedTarget).hasClass('carousel-item'), 'relatedTarget has class "item"')
  288. done()
  289. })
  290. .bootstrapCarousel('next')
  291. })
  292. QUnit.test('should fire slid event with relatedTarget', function (assert) {
  293. assert.expect(2)
  294. var template = '<div id="myCarousel" class="carousel slide">' +
  295. '<div class="carousel-inner">' +
  296. '<div class="carousel-item active">' +
  297. '<img alt="">' +
  298. '<div class="carousel-caption">' +
  299. '<h4>First Thumbnail label</h4>' +
  300. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  301. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  302. 'ultricies vehicula ut id elit.</p>' +
  303. '</div>' +
  304. '</div>' +
  305. '<div class="carousel-item">' +
  306. '<img alt="">' +
  307. '<div class="carousel-caption">' +
  308. '<h4>Second Thumbnail label</h4>' +
  309. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  310. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  311. 'ultricies vehicula ut id elit.</p>' +
  312. '</div>' +
  313. '</div>' +
  314. '<div class="carousel-item">' +
  315. '<img alt="">' +
  316. '<div class="carousel-caption">' +
  317. '<h4>Third Thumbnail label</h4>' +
  318. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  319. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  320. 'ultricies vehicula ut id elit.</p>' +
  321. '</div>' +
  322. '</div>' +
  323. '</div>' +
  324. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  325. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  326. '</div>'
  327. var done = assert.async()
  328. $(template)
  329. .on('slid.bs.carousel', function (e) {
  330. assert.ok(e.relatedTarget, 'relatedTarget present')
  331. assert.ok($(e.relatedTarget).hasClass('carousel-item'), 'relatedTarget has class "item"')
  332. done()
  333. })
  334. .bootstrapCarousel('next')
  335. })
  336. QUnit.test('should fire slid and slide events with from and to', function (assert) {
  337. assert.expect(4)
  338. var template = '<div id="myCarousel" class="carousel slide">' +
  339. '<div class="carousel-inner">' +
  340. '<div class="carousel-item active">' +
  341. '<img alt="">' +
  342. '<div class="carousel-caption">' +
  343. '<h4>First Thumbnail label</h4>' +
  344. '</div>' +
  345. '</div>' +
  346. '<div class="carousel-item">' +
  347. '<img alt="">' +
  348. '<div class="carousel-caption">' +
  349. '<h4>Second Thumbnail label</h4>' +
  350. '</div>' +
  351. '</div>' +
  352. '<div class="carousel-item">' +
  353. '<img alt="">' +
  354. '<div class="carousel-caption">' +
  355. '<h4>Third Thumbnail label</h4>' +
  356. '</div>' +
  357. '</div>' +
  358. '</div>' +
  359. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  360. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  361. '</div>'
  362. var done = assert.async()
  363. $(template)
  364. .on('slid.bs.carousel', function (e) {
  365. assert.ok(typeof e.from !== 'undefined', 'from present')
  366. assert.ok(typeof e.to !== 'undefined', 'to present')
  367. $(this).off()
  368. done()
  369. })
  370. .on('slide.bs.carousel', function (e) {
  371. assert.ok(typeof e.from !== 'undefined', 'from present')
  372. assert.ok(typeof e.to !== 'undefined', 'to present')
  373. $(this).off('slide.bs.carousel')
  374. })
  375. .bootstrapCarousel('next')
  376. })
  377. QUnit.test('should set interval from data attribute', function (assert) {
  378. assert.expect(4)
  379. var templateHTML = '<div id="myCarousel" class="carousel slide">' +
  380. '<div class="carousel-inner">' +
  381. '<div class="carousel-item active">' +
  382. '<img alt="">' +
  383. '<div class="carousel-caption">' +
  384. '<h4>First Thumbnail label</h4>' +
  385. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  386. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  387. 'ultricies vehicula ut id elit.</p>' +
  388. '</div>' +
  389. '</div>' +
  390. '<div class="carousel-item">' +
  391. '<img alt="">' +
  392. '<div class="carousel-caption">' +
  393. '<h4>Second Thumbnail label</h4>' +
  394. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  395. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  396. 'ultricies vehicula ut id elit.</p>' +
  397. '</div>' +
  398. '</div>' +
  399. '<div class="carousel-item">' +
  400. '<img alt="">' +
  401. '<div class="carousel-caption">' +
  402. '<h4>Third Thumbnail label</h4>' +
  403. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  404. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  405. 'ultricies vehicula ut id elit.</p>' +
  406. '</div>' +
  407. '</div>' +
  408. '</div>' +
  409. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  410. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  411. '</div>'
  412. var $carousel = $(templateHTML)
  413. $carousel.attr('data-interval', 1814)
  414. $carousel.appendTo('body')
  415. $('[data-slide]').first().trigger('click')
  416. assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814)
  417. $carousel.remove()
  418. $carousel.appendTo('body').attr('data-modal', 'foobar')
  419. $('[data-slide]').first().trigger('click')
  420. assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'even if there is an data-modal attribute set')
  421. $carousel.remove()
  422. $carousel.appendTo('body')
  423. $('[data-slide]').first().trigger('click')
  424. $carousel.attr('data-interval', 1860)
  425. $('[data-slide]').first().trigger('click')
  426. assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'attributes should be read only on initialization')
  427. $carousel.remove()
  428. $carousel.attr('data-interval', false)
  429. $carousel.appendTo('body')
  430. $carousel.bootstrapCarousel(1)
  431. assert.strictEqual($carousel.data('bs.carousel')._config.interval, false, 'data attribute has higher priority than default options')
  432. $carousel.remove()
  433. })
  434. QUnit.test('should set interval from data attribute on individual carousel-item', function (assert) {
  435. assert.expect(2)
  436. var templateHTML = '<div id="myCarousel" class="carousel slide" data-interval="1814">' +
  437. '<div class="carousel-inner">' +
  438. '<div class="carousel-item active" data-interval="2814">' +
  439. '<img alt="">' +
  440. '<div class="carousel-caption">' +
  441. '<h4>First Thumbnail label</h4>' +
  442. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  443. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  444. 'ultricies vehicula ut id elit.</p>' +
  445. '</div>' +
  446. '</div>' +
  447. '<div class="carousel-item" data-interval="3814">' +
  448. '<img alt="">' +
  449. '<div class="carousel-caption">' +
  450. '<h4>Second Thumbnail label</h4>' +
  451. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  452. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  453. 'ultricies vehicula ut id elit.</p>' +
  454. '</div>' +
  455. '</div>' +
  456. '<div class="carousel-item">' +
  457. '<img alt="">' +
  458. '<div class="carousel-caption">' +
  459. '<h4>Third Thumbnail label</h4>' +
  460. '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
  461. 'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
  462. 'ultricies vehicula ut id elit.</p>' +
  463. '</div>' +
  464. '</div>' +
  465. '</div>' +
  466. '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  467. '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  468. '</div>'
  469. var $carousel = $(templateHTML)
  470. $carousel.appendTo('body')
  471. $carousel.bootstrapCarousel(1)
  472. assert.strictEqual($carousel.data('bs.carousel')._config.interval, 3814)
  473. $carousel.remove()
  474. $carousel.appendTo('body')
  475. $carousel.bootstrapCarousel(2)
  476. assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'reverts to default interval if no data-interval is set')
  477. $carousel.remove()
  478. })
  479. QUnit.test('should skip over non-items when using item indices', function (assert) {
  480. assert.expect(2)
  481. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="1814">' +
  482. '<div class="carousel-inner">' +
  483. '<div class="carousel-item active">' +
  484. '<img alt="">' +
  485. '</div>' +
  486. '<script type="text/x-metamorph" id="thingy"/>' +
  487. '<div class="carousel-item">' +
  488. '<img alt="">' +
  489. '</div>' +
  490. '<div class="carousel-item">' +
  491. '</div>' +
  492. '</div>' +
  493. '</div>'
  494. var $template = $(templateHTML)
  495. $template.bootstrapCarousel()
  496. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
  497. $template.bootstrapCarousel(1)
  498. assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
  499. })
  500. QUnit.test('should skip over non-items when using next/prev methods', function (assert) {
  501. assert.expect(2)
  502. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="1814">' +
  503. '<div class="carousel-inner">' +
  504. '<div class="carousel-item active">' +
  505. '<img alt="">' +
  506. '</div>' +
  507. '<script type="text/x-metamorph" id="thingy"/>' +
  508. '<div class="carousel-item">' +
  509. '<img alt="">' +
  510. '</div>' +
  511. '<div class="carousel-item">' +
  512. '</div>' +
  513. '</div>' +
  514. '</div>'
  515. var $template = $(templateHTML)
  516. $template.bootstrapCarousel()
  517. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
  518. $template.bootstrapCarousel('next')
  519. assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
  520. })
  521. QUnit.test('should go to previous item if left arrow key is pressed', function (assert) {
  522. assert.expect(2)
  523. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
  524. '<div class="carousel-inner">' +
  525. '<div id="first" class="carousel-item">' +
  526. '<img alt="">' +
  527. '</div>' +
  528. '<div id="second" class="carousel-item active">' +
  529. '<img alt="">' +
  530. '</div>' +
  531. '<div id="third" class="carousel-item">' +
  532. '<img alt="">' +
  533. '</div>' +
  534. '</div>' +
  535. '</div>'
  536. var $template = $(templateHTML)
  537. $template.bootstrapCarousel()
  538. assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
  539. $template.trigger($.Event('keydown', {
  540. which: 37
  541. }))
  542. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
  543. })
  544. QUnit.test('should go to next item if right arrow key is pressed', function (assert) {
  545. assert.expect(2)
  546. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
  547. '<div class="carousel-inner">' +
  548. '<div id="first" class="carousel-item active">' +
  549. '<img alt="">' +
  550. '</div>' +
  551. '<div id="second" class="carousel-item">' +
  552. '<img alt="">' +
  553. '</div>' +
  554. '<div id="third" class="carousel-item">' +
  555. '<img alt="">' +
  556. '</div>' +
  557. '</div>' +
  558. '</div>'
  559. var $template = $(templateHTML)
  560. $template.bootstrapCarousel()
  561. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
  562. $template.trigger($.Event('keydown', {
  563. which: 39
  564. }))
  565. assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
  566. })
  567. QUnit.test('should not prevent keydown if key is not ARROW_LEFT or ARROW_RIGHT', function (assert) {
  568. assert.expect(2)
  569. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
  570. '<div class="carousel-inner">' +
  571. '<div id="first" class="carousel-item active">' +
  572. '<img alt="">' +
  573. '</div>' +
  574. '</div>' +
  575. '</div>'
  576. var $template = $(templateHTML)
  577. $template.bootstrapCarousel()
  578. var done = assert.async()
  579. var eventArrowDown = $.Event('keydown', {
  580. which: 40
  581. })
  582. var eventArrowUp = $.Event('keydown', {
  583. which: 38
  584. })
  585. $template.one('keydown', function (event) {
  586. assert.strictEqual(event.isDefaultPrevented(), false)
  587. })
  588. $template.trigger(eventArrowDown)
  589. $template.one('keydown', function (event) {
  590. assert.strictEqual(event.isDefaultPrevented(), false)
  591. done()
  592. })
  593. $template.trigger(eventArrowUp)
  594. })
  595. QUnit.test('should support disabling the keyboard navigation', function (assert) {
  596. assert.expect(3)
  597. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-keyboard="false">' +
  598. '<div class="carousel-inner">' +
  599. '<div id="first" class="carousel-item active">' +
  600. '<img alt="">' +
  601. '</div>' +
  602. '<div id="second" class="carousel-item">' +
  603. '<img alt="">' +
  604. '</div>' +
  605. '<div id="third" class="carousel-item">' +
  606. '<img alt="">' +
  607. '</div>' +
  608. '</div>' +
  609. '</div>'
  610. var $template = $(templateHTML)
  611. $template.bootstrapCarousel()
  612. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
  613. $template.trigger($.Event('keydown', {
  614. which: 39
  615. }))
  616. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press')
  617. $template.trigger($.Event('keydown', {
  618. which: 37
  619. }))
  620. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press')
  621. })
  622. QUnit.test('should ignore keyboard events within <input>s and <textarea>s', function (assert) {
  623. assert.expect(7)
  624. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
  625. '<div class="carousel-inner">' +
  626. '<div id="first" class="carousel-item active">' +
  627. '<img alt="">' +
  628. '<input type="text" id="in-put">' +
  629. '<textarea id="text-area"></textarea>' +
  630. '</div>' +
  631. '<div id="second" class="carousel-item">' +
  632. '<img alt="">' +
  633. '</div>' +
  634. '<div id="third" class="carousel-item">' +
  635. '<img alt="">' +
  636. '</div>' +
  637. '</div>' +
  638. '</div>'
  639. var $template = $(templateHTML)
  640. var $input = $template.find('#in-put')
  641. var $textarea = $template.find('#text-area')
  642. assert.strictEqual($input.length, 1, 'found <input>')
  643. assert.strictEqual($textarea.length, 1, 'found <textarea>')
  644. $template.bootstrapCarousel()
  645. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
  646. $input.trigger($.Event('keydown', {
  647. which: 39
  648. }))
  649. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press in <input>')
  650. $input.trigger($.Event('keydown', {
  651. which: 37
  652. }))
  653. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <input>')
  654. $textarea.trigger($.Event('keydown', {
  655. which: 39
  656. }))
  657. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press in <textarea>')
  658. $textarea.trigger($.Event('keydown', {
  659. which: 37
  660. }))
  661. assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <textarea>')
  662. })
  663. QUnit.test('should wrap around from end to start when wrap option is true', function (assert) {
  664. assert.expect(3)
  665. var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
  666. '<ol class="carousel-indicators">' +
  667. '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
  668. '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
  669. '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
  670. '</ol>' +
  671. '<div class="carousel-inner">' +
  672. '<div class="carousel-item active" id="one">' +
  673. '<div class="carousel-caption"/>' +
  674. '</div>' +
  675. '<div class="carousel-item" id="two">' +
  676. '<div class="carousel-caption"/>' +
  677. '</div>' +
  678. '<div class="carousel-item" id="three">' +
  679. '<div class="carousel-caption"/>' +
  680. '</div>' +
  681. '</div>' +
  682. '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
  683. '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
  684. '</div>'
  685. var $carousel = $(carouselHTML)
  686. var getActiveId = function () {
  687. return $carousel.find('.carousel-item.active').attr('id')
  688. }
  689. var done = assert.async()
  690. $carousel
  691. .one('slid.bs.carousel', function () {
  692. assert.strictEqual(getActiveId(), 'two', 'carousel slid from 1st to 2nd slide')
  693. $carousel
  694. .one('slid.bs.carousel', function () {
  695. assert.strictEqual(getActiveId(), 'three', 'carousel slid from 2nd to 3rd slide')
  696. $carousel
  697. .one('slid.bs.carousel', function () {
  698. assert.strictEqual(getActiveId(), 'one', 'carousel wrapped around and slid from 3rd to 1st slide')
  699. done()
  700. })
  701. .bootstrapCarousel('next')
  702. })
  703. .bootstrapCarousel('next')
  704. })
  705. .bootstrapCarousel('next')
  706. })
  707. QUnit.test('should wrap around from start to end when wrap option is true', function (assert) {
  708. assert.expect(1)
  709. var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
  710. '<ol class="carousel-indicators">' +
  711. '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
  712. '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
  713. '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
  714. '</ol>' +
  715. '<div class="carousel-inner">' +
  716. '<div class="carousel-item active" id="one">' +
  717. '<div class="carousel-caption"/>' +
  718. '</div>' +
  719. '<div class="carousel-item" id="two">' +
  720. '<div class="carousel-caption"/>' +
  721. '</div>' +
  722. '<div class="carousel-item" id="three">' +
  723. '<div class="carousel-caption"/>' +
  724. '</div>' +
  725. '</div>' +
  726. '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
  727. '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
  728. '</div>'
  729. var $carousel = $(carouselHTML)
  730. var done = assert.async()
  731. $carousel
  732. .on('slid.bs.carousel', function () {
  733. assert.strictEqual($carousel.find('.carousel-item.active').attr('id'), 'three', 'carousel wrapped around and slid from 1st to 3rd slide')
  734. done()
  735. })
  736. .bootstrapCarousel('prev')
  737. })
  738. QUnit.test('should stay at the end when the next method is called and wrap is false', function (assert) {
  739. assert.expect(3)
  740. var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
  741. '<ol class="carousel-indicators">' +
  742. '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
  743. '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
  744. '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
  745. '</ol>' +
  746. '<div class="carousel-inner">' +
  747. '<div class="carousel-item active" id="one">' +
  748. '<div class="carousel-caption"/>' +
  749. '</div>' +
  750. '<div class="carousel-item" id="two">' +
  751. '<div class="carousel-caption"/>' +
  752. '</div>' +
  753. '<div class="carousel-item" id="three">' +
  754. '<div class="carousel-caption"/>' +
  755. '</div>' +
  756. '</div>' +
  757. '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
  758. '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
  759. '</div>'
  760. var $carousel = $(carouselHTML)
  761. var getActiveId = function () {
  762. return $carousel.find('.carousel-item.active').attr('id')
  763. }
  764. var done = assert.async()
  765. $carousel
  766. .one('slid.bs.carousel', function () {
  767. assert.strictEqual(getActiveId(), 'two', 'carousel slid from 1st to 2nd slide')
  768. $carousel
  769. .one('slid.bs.carousel', function () {
  770. assert.strictEqual(getActiveId(), 'three', 'carousel slid from 2nd to 3rd slide')
  771. $carousel
  772. .one('slid.bs.carousel', function () {
  773. assert.ok(false, 'carousel slid when it should not have slid')
  774. })
  775. .bootstrapCarousel('next')
  776. assert.strictEqual(getActiveId(), 'three', 'carousel did not wrap around and stayed on 3rd slide')
  777. done()
  778. })
  779. .bootstrapCarousel('next')
  780. })
  781. .bootstrapCarousel('next')
  782. })
  783. QUnit.test('should stay at the start when the prev method is called and wrap is false', function (assert) {
  784. assert.expect(1)
  785. var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
  786. '<ol class="carousel-indicators">' +
  787. '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
  788. '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
  789. '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
  790. '</ol>' +
  791. '<div class="carousel-inner">' +
  792. '<div class="carousel-item active" id="one">' +
  793. '<div class="carousel-caption"/>' +
  794. '</div>' +
  795. '<div class="carousel-item" id="two">' +
  796. '<div class="carousel-caption"/>' +
  797. '</div>' +
  798. '<div class="carousel-item" id="three">' +
  799. '<div class="carousel-caption"/>' +
  800. '</div>' +
  801. '</div>' +
  802. '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
  803. '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
  804. '</div>'
  805. var $carousel = $(carouselHTML)
  806. $carousel
  807. .on('slid.bs.carousel', function () {
  808. assert.ok(false, 'carousel slid when it should not have slid')
  809. })
  810. .bootstrapCarousel('prev')
  811. assert.strictEqual($carousel.find('.carousel-item.active').attr('id'), 'one', 'carousel did not wrap around and stayed on 1st slide')
  812. })
  813. QUnit.test('should not prevent keydown for inputs and textareas', function (assert) {
  814. assert.expect(2)
  815. var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
  816. '<div class="carousel-inner">' +
  817. '<div id="first" class="carousel-item">' +
  818. '<input type="text" id="inputText" />' +
  819. '</div>' +
  820. '<div id="second" class="carousel-item active">' +
  821. '<textarea id="txtArea"></textarea>' +
  822. '</div>' +
  823. '</div>' +
  824. '</div>'
  825. var $template = $(templateHTML)
  826. var done = assert.async()
  827. $template.appendTo('#qunit-fixture')
  828. var $inputText = $template.find('#inputText')
  829. var $textArea = $template.find('#txtArea')
  830. $template.bootstrapCarousel()
  831. var eventKeyDown = $.Event('keydown', {
  832. which: 65
  833. }) // 65 for "a"
  834. $inputText.on('keydown', function (event) {
  835. assert.strictEqual(event.isDefaultPrevented(), false)
  836. })
  837. $inputText.trigger(eventKeyDown)
  838. $textArea.on('keydown', function (event) {
  839. assert.strictEqual(event.isDefaultPrevented(), false)
  840. done()
  841. })
  842. $textArea.trigger(eventKeyDown)
  843. })
  844. QUnit.test('should not go to the next item when the carousel is not visible', function (assert) {
  845. assert.expect(2)
  846. var done = assert.async()
  847. var html = '<div id="myCarousel" class="carousel slide" data-interval="50" style="display: none;">' +
  848. ' <div class="carousel-inner">' +
  849. ' <div id="firstItem" class="carousel-item active">' +
  850. ' <img alt="">' +
  851. ' </div>' +
  852. ' <div class="carousel-item">' +
  853. ' <img alt="">' +
  854. ' </div>' +
  855. ' <div class="carousel-item">' +
  856. ' <img alt="">' +
  857. ' </div>' +
  858. ' <a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  859. ' <a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  860. '</div>'
  861. var $html = $(html)
  862. $html
  863. .appendTo('#qunit-fixture')
  864. .bootstrapCarousel()
  865. var $firstItem = $('#firstItem')
  866. setTimeout(function () {
  867. assert.ok($firstItem.hasClass('active'))
  868. $html
  869. .bootstrapCarousel('dispose')
  870. .attr('style', 'visibility: hidden;')
  871. .bootstrapCarousel()
  872. setTimeout(function () {
  873. assert.ok($firstItem.hasClass('active'))
  874. done()
  875. }, 80)
  876. }, 80)
  877. })
  878. QUnit.test('should not go to the next item when the parent of the carousel is not visible', function (assert) {
  879. assert.expect(2)
  880. var done = assert.async()
  881. var html = '<div id="parent" style="display: none;">' +
  882. ' <div id="myCarousel" class="carousel slide" data-interval="50" style="display: none;">' +
  883. ' <div class="carousel-inner">' +
  884. ' <div id="firstItem" class="carousel-item active">' +
  885. ' <img alt="">' +
  886. ' </div>' +
  887. ' <div class="carousel-item">' +
  888. ' <img alt="">' +
  889. ' </div>' +
  890. ' <div class="carousel-item">' +
  891. ' <img alt="">' +
  892. ' </div>' +
  893. ' <a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
  894. ' <a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
  895. ' </div>' +
  896. '</div>'
  897. var $html = $(html)
  898. $html.appendTo('#qunit-fixture')
  899. var $parent = $html.find('#parent')
  900. var $carousel = $html.find('#myCarousel')
  901. $carousel.bootstrapCarousel()
  902. var $firstItem = $('#firstItem')
  903. setTimeout(function () {
  904. assert.ok($firstItem.hasClass('active'))
  905. $carousel.bootstrapCarousel('dispose')
  906. $parent.attr('style', 'visibility: hidden;')
  907. $carousel.bootstrapCarousel()
  908. setTimeout(function () {
  909. assert.ok($firstItem.hasClass('active'))
  910. done()
  911. }, 80)
  912. }, 80)
  913. })
  914. QUnit.test('should allow swiperight and call prev with pointer events', function (assert) {
  915. if (!supportPointerEvent) {
  916. assert.expect(0)
  917. return
  918. }
  919. document.documentElement.ontouchstart = $.noop
  920. Simulator.setType('pointer')
  921. assert.expect(3)
  922. var $styles = $(stylesCarousel).appendTo('head')
  923. var done = assert.async()
  924. var carouselHTML =
  925. '<div class="carousel" data-interval="false">' +
  926. ' <div class="carousel-inner">' +
  927. ' <div id="item" class="carousel-item">' +
  928. ' <img alt="">' +
  929. ' </div>' +
  930. ' <div class="carousel-item active">' +
  931. ' <img alt="">' +
  932. ' </div>' +
  933. ' </div>' +
  934. '</div>'
  935. var $carousel = $(carouselHTML).appendTo('#qunit-fixture')
  936. var $item = $('#item')
  937. $carousel.bootstrapCarousel()
  938. var carousel = $carousel.data('bs.carousel')
  939. var spy = sinon.spy(carousel, 'prev')
  940. $carousel.one('slid.bs.carousel', function () {
  941. assert.ok(true, 'slid event fired')
  942. assert.ok($item.hasClass('active'))
  943. assert.ok(spy.called)
  944. $styles.remove()
  945. delete document.documentElement.ontouchstart
  946. done()
  947. })
  948. Simulator.gestures.swipe($carousel[0], {
  949. deltaX: 300,
  950. deltaY: 0
  951. })
  952. })
  953. QUnit.test('should allow swiperight and call prev with touch events', function (assert) {
  954. Simulator.setType('touch')
  955. clearPointerEvents()
  956. assert.expect(3)
  957. var done = assert.async()
  958. document.documentElement.ontouchstart = $.noop
  959. var carouselHTML =
  960. '<div class="carousel" data-interval="false">' +
  961. ' <div class="carousel-inner">' +
  962. ' <div id="item" class="carousel-item">' +
  963. ' <img alt="">' +
  964. ' </div>' +
  965. ' <div class="carousel-item active">' +
  966. ' <img alt="">' +
  967. ' </div>' +
  968. ' </div>' +
  969. '</div>'
  970. var $carousel = $(carouselHTML)
  971. $carousel.appendTo('#qunit-fixture')
  972. var $item = $('#item')
  973. $carousel.bootstrapCarousel()
  974. var carousel = $carousel.data('bs.carousel')
  975. var spy = sinon.spy(carousel, 'prev')
  976. $carousel.one('slid.bs.carousel', function () {
  977. assert.ok(true, 'slid event fired')
  978. assert.ok($item.hasClass('active'))
  979. assert.ok(spy.called)
  980. delete document.documentElement.ontouchstart
  981. restorePointerEvents()
  982. done()
  983. })
  984. Simulator.gestures.swipe($carousel[0], {
  985. deltaX: 300,
  986. deltaY: 0
  987. })
  988. })
  989. QUnit.test('should allow swipeleft and call next with pointer events', function (assert) {
  990. if (!supportPointerEvent) {
  991. assert.expect(0)
  992. return
  993. }
  994. document.documentElement.ontouchstart = $.noop
  995. assert.expect(3)
  996. Simulator.setType('pointer')
  997. var $styles = $(stylesCarousel).appendTo('head')
  998. var done = assert.async()
  999. var carouselHTML =
  1000. '<div class="carousel" data-interval="false">' +
  1001. ' <div class="carousel-inner">' +
  1002. ' <div id="item" class="carousel-item active">' +
  1003. ' <img alt="">' +
  1004. ' </div>' +
  1005. ' <div class="carousel-item">' +
  1006. ' <img alt="">' +
  1007. ' </div>' +
  1008. ' </div>' +
  1009. '</div>'
  1010. var $carousel = $(carouselHTML)
  1011. $carousel.appendTo('#qunit-fixture')
  1012. var $item = $('#item')
  1013. $carousel.bootstrapCarousel()
  1014. var carousel = $carousel.data('bs.carousel')
  1015. var spy = sinon.spy(carousel, 'next')
  1016. $carousel.one('slid.bs.carousel', function () {
  1017. assert.ok(true, 'slid event fired')
  1018. assert.ok(!$item.hasClass('active'))
  1019. assert.ok(spy.called)
  1020. $styles.remove()
  1021. delete document.documentElement.ontouchstart
  1022. done()
  1023. })
  1024. Simulator.gestures.swipe($carousel[0], {
  1025. pos: [300, 10],
  1026. deltaX: -300,
  1027. deltaY: 0
  1028. })
  1029. })
  1030. QUnit.test('should allow swipeleft and call next with touch events', function (assert) {
  1031. assert.expect(3)
  1032. clearPointerEvents()
  1033. Simulator.setType('touch')
  1034. document.documentElement.ontouchstart = $.noop
  1035. var done = assert.async()
  1036. var carouselHTML =
  1037. '<div class="carousel" data-interval="false">' +
  1038. ' <div class="carousel-inner">' +
  1039. ' <div id="item" class="carousel-item active">' +
  1040. ' <img alt="">' +
  1041. ' </div>' +
  1042. ' <div class="carousel-item">' +
  1043. ' <img alt="">' +
  1044. ' </div>' +
  1045. ' </div>' +
  1046. '</div>'
  1047. var $carousel = $(carouselHTML)
  1048. $carousel.appendTo('#qunit-fixture')
  1049. var $item = $('#item')
  1050. $carousel.bootstrapCarousel()
  1051. var carousel = $carousel.data('bs.carousel')
  1052. var spy = sinon.spy(carousel, 'next')
  1053. $carousel.one('slid.bs.carousel', function () {
  1054. assert.ok(true, 'slid event fired')
  1055. assert.ok(!$item.hasClass('active'))
  1056. assert.ok(spy.called)
  1057. restorePointerEvents()
  1058. delete document.documentElement.ontouchstart
  1059. done()
  1060. })
  1061. Simulator.gestures.swipe($carousel[0], {
  1062. pos: [300, 10],
  1063. deltaX: -300,
  1064. deltaY: 0
  1065. })
  1066. })
  1067. QUnit.test('should not allow pinch with touch events', function (assert) {
  1068. assert.expect(0)
  1069. clearPointerEvents()
  1070. Simulator.setType('touch')
  1071. var done = assert.async()
  1072. document.documentElement.ontouchstart = $.noop
  1073. var carouselHTML = '<div class="carousel" data-interval="false"></div>'
  1074. var $carousel = $(carouselHTML)
  1075. $carousel.appendTo('#qunit-fixture')
  1076. $carousel.bootstrapCarousel()
  1077. Simulator.gestures.swipe($carousel[0], {
  1078. pos: [300, 10],
  1079. deltaX: -300,
  1080. deltaY: 0,
  1081. touches: 2
  1082. }, function () {
  1083. restorePointerEvents()
  1084. delete document.documentElement.ontouchstart
  1085. done()
  1086. })
  1087. })
  1088. QUnit.test('should not call _slide if the carousel is sliding', function (assert) {
  1089. assert.expect(1)
  1090. var carouselHTML = '<div class="carousel" data-interval="false"></div>'
  1091. var $carousel = $(carouselHTML)
  1092. $carousel.appendTo('#qunit-fixture')
  1093. $carousel.bootstrapCarousel()
  1094. var carousel = $carousel.data('bs.carousel')
  1095. var spy = sinon.spy(carousel, '_slide')
  1096. carousel._isSliding = true
  1097. carousel.next()
  1098. assert.strictEqual(spy.called, false)
  1099. })
  1100. QUnit.test('should call next when the page is visible', function (assert) {
  1101. assert.expect(1)
  1102. var carouselHTML = '<div class="carousel" data-interval="false"></div>'
  1103. var $carousel = $(carouselHTML)
  1104. $carousel.appendTo('#qunit-fixture')
  1105. $carousel.bootstrapCarousel()
  1106. var carousel = $carousel.data('bs.carousel')
  1107. var spy = sinon.spy(carousel, 'next')
  1108. var sandbox = sinon.createSandbox()
  1109. sandbox.replaceGetter(document, 'hidden', function () {
  1110. return false
  1111. })
  1112. sandbox.stub($carousel, 'is').returns(true)
  1113. sandbox.stub($carousel, 'css').returns('block')
  1114. carousel.nextWhenVisible()
  1115. assert.strictEqual(spy.called, true)
  1116. sandbox.restore()
  1117. })
  1118. QUnit.test('should not cycle when there is no attribute data-ride', function (assert) {
  1119. assert.expect(1)
  1120. var spy = sinon.spy(Carousel.prototype, 'cycle')
  1121. var carouselHTML = '<div class="carousel"></div>'
  1122. var $carousel = $(carouselHTML)
  1123. $carousel.appendTo('#qunit-fixture')
  1124. $carousel.bootstrapCarousel()
  1125. assert.strictEqual(spy.called, false)
  1126. spy.restore()
  1127. })
  1128. QUnit.test('should cycle when there is data-ride attribute', function (assert) {
  1129. assert.expect(1)
  1130. var spy = sinon.spy(Carousel.prototype, 'cycle')
  1131. var carouselHTML = '<div class="carousel" data-ride="carousel"></div>'
  1132. var $carousel = $(carouselHTML)
  1133. $carousel.appendTo('#qunit-fixture')
  1134. $carousel.bootstrapCarousel()
  1135. assert.strictEqual(spy.called, true)
  1136. spy.restore()
  1137. })
  1138. QUnit.test('should init carousels with data-ride on load event', function (assert) {
  1139. assert.expect(1)
  1140. var done = assert.async()
  1141. var spy = sinon.spy(Carousel, '_jQueryInterface')
  1142. var carouselHTML = '<div class="carousel" data-ride="carousel"></div>'
  1143. var $carousel = $(carouselHTML)
  1144. $carousel.appendTo('#qunit-fixture')
  1145. $(window).trigger($.Event('load'))
  1146. setTimeout(function () {
  1147. assert.strictEqual(spy.called, true)
  1148. spy.restore()
  1149. done()
  1150. }, 5)
  1151. })
  1152. QUnit.test('should not add touch event listeners when touch option set to false', function (assert) {
  1153. assert.expect(1)
  1154. var spy = sinon.spy(Carousel.prototype, '_addTouchEventListeners')
  1155. var $carousel = $('<div class="carousel" data-ride="carousel" data-touch="false"></div>')
  1156. $carousel.appendTo('#qunit-fixture')
  1157. $carousel.bootstrapCarousel()
  1158. assert.strictEqual(spy.called, false)
  1159. spy.restore()
  1160. })
  1161. })