carousel.js 41.1 KB
Newer Older
1
$(function () {
2
  'use strict'
3

4
5
6
7
  window.Carousel = typeof bootstrap !== 'undefined' ? bootstrap.Carousel : Carousel

  var touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0

fat's avatar
fat committed
8
  QUnit.module('carousel plugin')
9

fat's avatar
fat committed
10
11
12
  QUnit.test('should be defined on jQuery object', function (assert) {
    assert.expect(1)
    assert.ok($(document.body).carousel, 'carousel method is defined')
XhmikosR's avatar
XhmikosR committed
13
  })
14

fat's avatar
fat committed
15
16
  QUnit.module('carousel', {
    beforeEach: function () {
17
18
19
      // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
      $.fn.bootstrapCarousel = $.fn.carousel.noConflict()
    },
fat's avatar
fat committed
20
    afterEach: function () {
21
22
      $.fn.carousel = $.fn.bootstrapCarousel
      delete $.fn.bootstrapCarousel
23
      $('#qunit-fixture').html('')
24
25
26
    }
  })

fat's avatar
fat committed
27
28
  QUnit.test('should provide no conflict', function (assert) {
    assert.expect(1)
XhmikosR's avatar
XhmikosR committed
29
    assert.strictEqual(typeof $.fn.carousel, 'undefined', 'carousel was set back to undefined (orig value)')
30
31
  })

32
33
34
35
36
37
38
39
40
41
42
43
44
45
  QUnit.test('should return version', function (assert) {
    assert.expect(1)

    assert.strictEqual(typeof Carousel.VERSION, 'string')
  })

  QUnit.test('should return default parameters', function (assert) {
    assert.expect(1)

    var defaultConfig = Carousel.Default

    assert.strictEqual(defaultConfig.touch, true)
  })

46
47
48
49
50
51
  QUnit.test('should throw explicit error on undefined method', function (assert) {
    assert.expect(1)
    var $el = $('<div/>')
    $el.bootstrapCarousel()
    try {
      $el.bootstrapCarousel('noMethod')
XhmikosR's avatar
XhmikosR committed
52
    } catch (err) {
53
54
55
56
      assert.strictEqual(err.message, 'No method named "noMethod"')
    }
  })

fat's avatar
fat committed
57
58
  QUnit.test('should return jquery collection containing the element', function (assert) {
    assert.expect(2)
59
60
    var $el = $('<div/>')
    var $carousel = $el.bootstrapCarousel()
fat's avatar
fat committed
61
62
    assert.ok($carousel instanceof $, 'returns jquery collection')
    assert.strictEqual($carousel[0], $el[0], 'collection contains element')
XhmikosR's avatar
XhmikosR committed
63
  })
64

fat's avatar
fat committed
65
  QUnit.test('should type check config options', function (assert) {
66
67
    assert.expect(2)

fat's avatar
fat committed
68
69
70
71
72
73
74
75
    var message
    var expectedMessage = 'CAROUSEL: Option "interval" provided type "string" but expected type "(number|boolean)".'
    var config = {
      interval: 'fat sux'
    }

    try {
      $('<div/>').bootstrapCarousel(config)
XhmikosR's avatar
XhmikosR committed
76
77
    } catch (err) {
      message = err.message
fat's avatar
fat committed
78
79
80
81
82
    }

    assert.ok(message === expectedMessage, 'correct error message')

    config = {
83
      keyboard: document.createElement('div')
fat's avatar
fat committed
84
85
86
87
88
    }
    expectedMessage = 'CAROUSEL: Option "keyboard" provided type "element" but expected type "boolean".'

    try {
      $('<div/>').bootstrapCarousel(config)
XhmikosR's avatar
XhmikosR committed
89
90
    } catch (err) {
      message = err.message
fat's avatar
fat committed
91
92
93
94
95
    }

    assert.ok(message === expectedMessage, 'correct error message')
  })

fat's avatar
fat committed
96
97
  QUnit.test('should not fire slid when slide is prevented', function (assert) {
    assert.expect(1)
98
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
99
100
    $('<div class="carousel"/>')
      .on('slide.bs.carousel', function (e) {
101
        e.preventDefault()
fat's avatar
fat committed
102
        assert.ok(true, 'slide event fired')
103
        done()
XhmikosR's avatar
XhmikosR committed
104
105
      })
      .on('slid.bs.carousel', function () {
fat's avatar
fat committed
106
        assert.ok(false, 'slid event fired')
107
      })
108
      .bootstrapCarousel('next')
XhmikosR's avatar
XhmikosR committed
109
  })
110

fat's avatar
fat committed
111
112
  QUnit.test('should reset when slide is prevented', function (assert) {
    assert.expect(6)
XhmikosR's avatar
XhmikosR committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    var carouselHTML = '<div id="carousel-example-generic" class="carousel slide">' +
        '<ol class="carousel-indicators">' +
        '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
        '</ol>' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
        '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
        '</div>'
133
134
    var $carousel = $(carouselHTML)

135
    var done = assert.async()
136
137
138
139
    $carousel
      .one('slide.bs.carousel', function (e) {
        e.preventDefault()
        setTimeout(function () {
140
141
          assert.ok($carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
          assert.ok($carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
142
143
144
145
146
          $carousel.bootstrapCarousel('next')
        }, 0)
      })
      .one('slid.bs.carousel', function () {
        setTimeout(function () {
147
148
149
150
          assert.ok(!$carousel.find('.carousel-item:nth-child(1)').is('.active'), 'first item still active')
          assert.ok(!$carousel.find('.carousel-indicators li:nth-child(1)').is('.active'), 'first indicator still active')
          assert.ok($carousel.find('.carousel-item:nth-child(2)').is('.active'), 'second item active')
          assert.ok($carousel.find('.carousel-indicators li:nth-child(2)').is('.active'), 'second indicator active')
151
          done()
152
153
154
        }, 0)
      })
      .bootstrapCarousel('next')
XhmikosR's avatar
XhmikosR committed
155
  })
156

fat's avatar
fat committed
157
158
  QUnit.test('should fire slide event with direction', function (assert) {
    assert.expect(4)
XhmikosR's avatar
XhmikosR committed
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    var carouselHTML = '<div id="myCarousel" class="carousel slide">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
192
193
    var $carousel = $(carouselHTML)

194
    var done = assert.async()
195
196
197

    $carousel
      .one('slide.bs.carousel', function (e) {
fat's avatar
fat committed
198
199
        assert.ok(e.direction, 'direction present on next')
        assert.strictEqual(e.direction, 'left', 'direction is left on next')
200
201
202

        $carousel
          .one('slide.bs.carousel', function (e) {
fat's avatar
fat committed
203
204
            assert.ok(e.direction, 'direction present on prev')
            assert.strictEqual(e.direction, 'right', 'direction is right on prev')
205
            done()
206
207
208
209
          })
          .bootstrapCarousel('prev')
      })
      .bootstrapCarousel('next')
XhmikosR's avatar
XhmikosR committed
210
  })
211

fat's avatar
fat committed
212
213
  QUnit.test('should fire slid event with direction', function (assert) {
    assert.expect(4)
XhmikosR's avatar
XhmikosR committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    var carouselHTML = '<div id="myCarousel" class="carousel slide">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
247
248
    var $carousel = $(carouselHTML)

249
    var done = assert.async()
250
251
252

    $carousel
      .one('slid.bs.carousel', function (e) {
fat's avatar
fat committed
253
254
        assert.ok(e.direction, 'direction present on next')
        assert.strictEqual(e.direction, 'left', 'direction is left on next')
255
256
257

        $carousel
          .one('slid.bs.carousel', function (e) {
fat's avatar
fat committed
258
259
            assert.ok(e.direction, 'direction present on prev')
            assert.strictEqual(e.direction, 'right', 'direction is right on prev')
260
            done()
261
262
263
264
          })
          .bootstrapCarousel('prev')
      })
      .bootstrapCarousel('next')
265
266
  })

fat's avatar
fat committed
267
268
  QUnit.test('should fire slide event with relatedTarget', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
    var template = '<div id="myCarousel" class="carousel slide">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
302

303
    var done = assert.async()
304

XhmikosR's avatar
XhmikosR committed
305
306
    $(template)
      .on('slide.bs.carousel', function (e) {
fat's avatar
fat committed
307
        assert.ok(e.relatedTarget, 'relatedTarget present')
fat's avatar
fat committed
308
        assert.ok($(e.relatedTarget).hasClass('carousel-item'), 'relatedTarget has class "item"')
309
        done()
Dmitriy Budnik's avatar
Dmitriy Budnik committed
310
      })
311
      .bootstrapCarousel('next')
XhmikosR's avatar
XhmikosR committed
312
  })
313

fat's avatar
fat committed
314
315
  QUnit.test('should fire slid event with relatedTarget', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
    var template = '<div id="myCarousel" class="carousel slide">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
349

350
    var done = assert.async()
351

352
353
    $(template)
      .on('slid.bs.carousel', function (e) {
fat's avatar
fat committed
354
        assert.ok(e.relatedTarget, 'relatedTarget present')
fat's avatar
fat committed
355
        assert.ok($(e.relatedTarget).hasClass('carousel-item'), 'relatedTarget has class "item"')
356
        done()
357
      })
358
      .bootstrapCarousel('next')
359
  })
360

361
362
  QUnit.test('should fire slid and slide events with from and to', function (assert) {
    assert.expect(4)
XhmikosR's avatar
XhmikosR committed
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    var template = '<div id="myCarousel" class="carousel slide">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
387
388
389
390

    var done = assert.async()
    $(template)
      .on('slid.bs.carousel', function (e) {
XhmikosR's avatar
XhmikosR committed
391
392
        assert.ok(typeof e.from !== 'undefined', 'from present')
        assert.ok(typeof e.to !== 'undefined', 'to present')
393
394
395
396
        $(this).off()
        done()
      })
      .on('slide.bs.carousel', function (e) {
XhmikosR's avatar
XhmikosR committed
397
398
        assert.ok(typeof e.from !== 'undefined', 'from present')
        assert.ok(typeof e.to !== 'undefined', 'to present')
399
400
401
402
403
        $(this).off('slide.bs.carousel')
      })
      .bootstrapCarousel('next')
  })

fat's avatar
fat committed
404
405
  QUnit.test('should set interval from data attribute', function (assert) {
    assert.expect(4)
XhmikosR's avatar
XhmikosR committed
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
    var templateHTML = '<div id="myCarousel" class="carousel slide">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
439
440
    var $carousel = $(templateHTML)
    $carousel.attr('data-interval', 1814)
Dmitriy Budnik's avatar
Dmitriy Budnik committed
441

442
    $carousel.appendTo('body')
fat's avatar
fat committed
443
    $('[data-slide]').first().trigger('click')
fat's avatar
fat committed
444
    assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814)
445
    $carousel.remove()
dmitriybudnik's avatar
dmitriybudnik committed
446

447
    $carousel.appendTo('body').attr('data-modal', 'foobar')
fat's avatar
fat committed
448
    $('[data-slide]').first().trigger('click')
fat's avatar
fat committed
449
    assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'even if there is an data-modal attribute set')
450
    $carousel.remove()
Dmitriy Budnik's avatar
Dmitriy Budnik committed
451

452
    $carousel.appendTo('body')
fat's avatar
fat committed
453
    $('[data-slide]').first().trigger('click')
454
    $carousel.attr('data-interval', 1860)
fat's avatar
fat committed
455
    $('[data-slide]').first().trigger('click')
fat's avatar
fat committed
456
    assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'attributes should be read only on initialization')
457
458
459
460
461
    $carousel.remove()

    $carousel.attr('data-interval', false)
    $carousel.appendTo('body')
    $carousel.bootstrapCarousel(1)
fat's avatar
fat committed
462
    assert.strictEqual($carousel.data('bs.carousel')._config.interval, false, 'data attribute has higher priority than default options')
463
    $carousel.remove()
XhmikosR's avatar
XhmikosR committed
464
  })
465

466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  QUnit.test('should set interval from data attribute on individual carousel-item', function (assert) {
    assert.expect(2)
    var templateHTML = '<div id="myCarousel" class="carousel slide" data-interval="1814">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active" data-interval="2814">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>First Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item" data-interval="3814">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Second Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '<div class="carousel-caption">' +
        '<h4>Third Thumbnail label</h4>' +
        '<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec ' +
        'id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ' +
        'ultricies vehicula ut id elit.</p>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
        '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
        '</div>'
    var $carousel = $(templateHTML)

    $carousel.appendTo('body')
    $carousel.bootstrapCarousel(1)
    assert.strictEqual($carousel.data('bs.carousel')._config.interval, 3814)
    $carousel.remove()

    $carousel.appendTo('body')
    $carousel.bootstrapCarousel(2)
    assert.strictEqual($carousel.data('bs.carousel')._config.interval, 1814, 'reverts to default interval if no data-interval is set')
    $carousel.remove()
  })

fat's avatar
fat committed
514
515
  QUnit.test('should skip over non-items when using item indices', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
516
517
518
519
520
521
522
523
524
525
526
527
528
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="1814">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '</div>' +
        '<script type="text/x-metamorph" id="thingy"/>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '<div class="carousel-item">' +
        '</div>' +
        '</div>' +
        '</div>'
529
    var $template = $(templateHTML)
530

531
    $template.bootstrapCarousel()
532

fat's avatar
fat committed
533
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
534

535
    $template.bootstrapCarousel(1)
536

fat's avatar
fat committed
537
    assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
538
  })
539

fat's avatar
fat committed
540
541
  QUnit.test('should skip over non-items when using next/prev methods', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
542
543
544
545
546
547
548
549
550
551
552
553
554
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="1814">' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active">' +
        '<img alt="">' +
        '</div>' +
        '<script type="text/x-metamorph" id="thingy"/>' +
        '<div class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '<div class="carousel-item">' +
        '</div>' +
        '</div>' +
        '</div>'
555
556
557
558
    var $template = $(templateHTML)

    $template.bootstrapCarousel()

fat's avatar
fat committed
559
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
560
561
562

    $template.bootstrapCarousel('next')

fat's avatar
fat committed
563
    assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
564
  })
565

fat's avatar
fat committed
566
567
  QUnit.test('should go to previous item if left arrow key is pressed', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
568
569
570
571
572
573
574
575
576
577
578
579
580
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
        '<div class="carousel-inner">' +
        '<div id="first" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '<div id="second" class="carousel-item active">' +
        '<img alt="">' +
        '</div>' +
        '<div id="third" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '</div>' +
        '</div>'
581
582
583
584
    var $template = $(templateHTML)

    $template.bootstrapCarousel()

fat's avatar
fat committed
585
    assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
586

XhmikosR's avatar
XhmikosR committed
587
588
589
    $template.trigger($.Event('keydown', {
      which: 37
    }))
590

fat's avatar
fat committed
591
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
592
593
  })

fat's avatar
fat committed
594
595
  QUnit.test('should go to next item if right arrow key is pressed', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
596
597
598
599
600
601
602
603
604
605
606
607
608
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
        '<div class="carousel-inner">' +
        '<div id="first" class="carousel-item active">' +
        '<img alt="">' +
        '</div>' +
        '<div id="second" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '<div id="third" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '</div>' +
        '</div>'
609
610
611
612
    var $template = $(templateHTML)

    $template.bootstrapCarousel()

fat's avatar
fat committed
613
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
614

XhmikosR's avatar
XhmikosR committed
615
616
617
    $template.trigger($.Event('keydown', {
      which: 39
    }))
618

fat's avatar
fat committed
619
    assert.strictEqual($template.find('.carousel-item')[1], $template.find('.active')[0], 'second item active')
620
621
  })

622
623
  QUnit.test('should not prevent keydown if key is not ARROW_LEFT or ARROW_RIGHT', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
624
625
626
627
628
629
630
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
        '<div class="carousel-inner">' +
        '<div id="first" class="carousel-item active">' +
        '<img alt="">' +
        '</div>' +
        '</div>' +
        '</div>'
631
632
633
634
635
    var $template = $(templateHTML)

    $template.bootstrapCarousel()
    var done = assert.async()

XhmikosR's avatar
XhmikosR committed
636
637
638
639
640
641
    var eventArrowDown = $.Event('keydown', {
      which: 40
    })
    var eventArrowUp   = $.Event('keydown', {
      which: 38
    })
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

    $template.one('keydown', function (event) {
      assert.strictEqual(event.isDefaultPrevented(), false)
    })

    $template.trigger(eventArrowDown)

    $template.one('keydown', function (event) {
      assert.strictEqual(event.isDefaultPrevented(), false)
      done()
    })

    $template.trigger(eventArrowUp)
  })

fat's avatar
fat committed
657
658
  QUnit.test('should support disabling the keyboard navigation', function (assert) {
    assert.expect(3)
XhmikosR's avatar
XhmikosR committed
659
660
661
662
663
664
665
666
667
668
669
670
671
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-keyboard="false">' +
        '<div class="carousel-inner">' +
        '<div id="first" class="carousel-item active">' +
        '<img alt="">' +
        '</div>' +
        '<div id="second" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '<div id="third" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '</div>' +
        '</div>'
672
673
674
675
    var $template = $(templateHTML)

    $template.bootstrapCarousel()

fat's avatar
fat committed
676
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
677

XhmikosR's avatar
XhmikosR committed
678
679
680
    $template.trigger($.Event('keydown', {
      which: 39
    }))
681

fat's avatar
fat committed
682
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press')
683

XhmikosR's avatar
XhmikosR committed
684
685
686
    $template.trigger($.Event('keydown', {
      which: 37
    }))
687

fat's avatar
fat committed
688
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press')
689
690
  })

fat's avatar
fat committed
691
692
  QUnit.test('should ignore keyboard events within <input>s and <textarea>s', function (assert) {
    assert.expect(7)
XhmikosR's avatar
XhmikosR committed
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
        '<div class="carousel-inner">' +
        '<div id="first" class="carousel-item active">' +
        '<img alt="">' +
        '<input type="text" id="in-put">' +
        '<textarea id="text-area"></textarea>' +
        '</div>' +
        '<div id="second" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '<div id="third" class="carousel-item">' +
        '<img alt="">' +
        '</div>' +
        '</div>' +
        '</div>'
708
709
710
711
    var $template = $(templateHTML)
    var $input = $template.find('#in-put')
    var $textarea = $template.find('#text-area')

fat's avatar
fat committed
712
713
    assert.strictEqual($input.length, 1, 'found <input>')
    assert.strictEqual($textarea.length, 1, 'found <textarea>')
714
715
716

    $template.bootstrapCarousel()

fat's avatar
fat committed
717
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item active')
718

XhmikosR's avatar
XhmikosR committed
719
720
721
    $input.trigger($.Event('keydown', {
      which: 39
    }))
fat's avatar
fat committed
722
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press in <input>')
723

XhmikosR's avatar
XhmikosR committed
724
725
726
    $input.trigger($.Event('keydown', {
      which: 37
    }))
fat's avatar
fat committed
727
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <input>')
728

XhmikosR's avatar
XhmikosR committed
729
730
731
    $textarea.trigger($.Event('keydown', {
      which: 39
    }))
fat's avatar
fat committed
732
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after right arrow press in <textarea>')
733

XhmikosR's avatar
XhmikosR committed
734
735
736
    $textarea.trigger($.Event('keydown', {
      which: 37
    }))
fat's avatar
fat committed
737
    assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <textarea>')
738
739
  })

fat's avatar
fat committed
740
741
  QUnit.test('should wrap around from end to start when wrap option is true', function (assert) {
    assert.expect(3)
XhmikosR's avatar
XhmikosR committed
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
    var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
        '<ol class="carousel-indicators">' +
        '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
        '</ol>' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active" id="one">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="two">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="three">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
        '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
        '</div>'
762
    var $carousel = $(carouselHTML)
XhmikosR's avatar
XhmikosR committed
763
764
765
    var getActiveId = function () {
      return $carousel.find('.carousel-item.active').attr('id')
    }
766

767
    var done = assert.async()
768
769
770

    $carousel
      .one('slid.bs.carousel', function () {
fat's avatar
fat committed
771
        assert.strictEqual(getActiveId(), 'two', 'carousel slid from 1st to 2nd slide')
772
773
        $carousel
          .one('slid.bs.carousel', function () {
fat's avatar
fat committed
774
            assert.strictEqual(getActiveId(), 'three', 'carousel slid from 2nd to 3rd slide')
775
776
            $carousel
              .one('slid.bs.carousel', function () {
fat's avatar
fat committed
777
                assert.strictEqual(getActiveId(), 'one', 'carousel wrapped around and slid from 3rd to 1st slide')
778
                done()
779
780
781
782
783
784
785
786
              })
              .bootstrapCarousel('next')
          })
          .bootstrapCarousel('next')
      })
      .bootstrapCarousel('next')
  })

fat's avatar
fat committed
787
788
  QUnit.test('should wrap around from start to end when wrap option is true', function (assert) {
    assert.expect(1)
XhmikosR's avatar
XhmikosR committed
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
    var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">' +
        '<ol class="carousel-indicators">' +
        '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
        '</ol>' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active" id="one">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="two">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="three">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
        '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
        '</div>'
809
810
    var $carousel = $(carouselHTML)

811
    var done = assert.async()
812
813
814

    $carousel
      .on('slid.bs.carousel', function () {
fat's avatar
fat committed
815
        assert.strictEqual($carousel.find('.carousel-item.active').attr('id'), 'three', 'carousel wrapped around and slid from 1st to 3rd slide')
816
        done()
817
818
819
820
      })
      .bootstrapCarousel('prev')
  })

fat's avatar
fat committed
821
822
  QUnit.test('should stay at the end when the next method is called and wrap is false', function (assert) {
    assert.expect(3)
XhmikosR's avatar
XhmikosR committed
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
    var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
        '<ol class="carousel-indicators">' +
        '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
        '</ol>' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active" id="one">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="two">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="three">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
        '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
        '</div>'
843
    var $carousel = $(carouselHTML)
XhmikosR's avatar
XhmikosR committed
844
845
846
    var getActiveId = function () {
      return $carousel.find('.carousel-item.active').attr('id')
    }
847

848
    var done = assert.async()
849
850
851

    $carousel
      .one('slid.bs.carousel', function () {
fat's avatar
fat committed
852
        assert.strictEqual(getActiveId(), 'two', 'carousel slid from 1st to 2nd slide')
853
854
        $carousel
          .one('slid.bs.carousel', function () {
fat's avatar
fat committed
855
            assert.strictEqual(getActiveId(), 'three', 'carousel slid from 2nd to 3rd slide')
856
857
            $carousel
              .one('slid.bs.carousel', function () {
fat's avatar
fat committed
858
                assert.ok(false, 'carousel slid when it should not have slid')
859
860
              })
              .bootstrapCarousel('next')
fat's avatar
fat committed
861
            assert.strictEqual(getActiveId(), 'three', 'carousel did not wrap around and stayed on 3rd slide')
862
            done()
863
864
865
866
867
868
          })
          .bootstrapCarousel('next')
      })
      .bootstrapCarousel('next')
  })

fat's avatar
fat committed
869
870
  QUnit.test('should stay at the start when the prev method is called and wrap is false', function (assert) {
    assert.expect(1)
XhmikosR's avatar
XhmikosR committed
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
    var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="false">' +
        '<ol class="carousel-indicators">' +
        '<li data-target="#carousel-example-generic" data-slide-to="0" class="active"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="1"/>' +
        '<li data-target="#carousel-example-generic" data-slide-to="2"/>' +
        '</ol>' +
        '<div class="carousel-inner">' +
        '<div class="carousel-item active" id="one">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="two">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '<div class="carousel-item" id="three">' +
        '<div class="carousel-caption"/>' +
        '</div>' +
        '</div>' +
        '<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev"/>' +
        '<a class="right carousel-control" href="#carousel-example-generic" data-slide="next"/>' +
        '</div>'
891
892
893
894
    var $carousel = $(carouselHTML)

    $carousel
      .on('slid.bs.carousel', function () {
fat's avatar
fat committed
895
        assert.ok(false, 'carousel slid when it should not have slid')
896
897
      })
      .bootstrapCarousel('prev')
fat's avatar
fat committed
898
    assert.strictEqual($carousel.find('.carousel-item.active').attr('id'), 'one', 'carousel did not wrap around and stayed on 1st slide')
899
  })
900
901
902

  QUnit.test('should not prevent keydown for inputs and textareas', function (assert) {
    assert.expect(2)
XhmikosR's avatar
XhmikosR committed
903
904
905
906
907
908
909
910
911
912
    var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false">' +
        '<div class="carousel-inner">' +
          '<div id="first" class="carousel-item">' +
            '<input type="text" id="inputText" />' +
          '</div>' +
          '<div id="second" class="carousel-item active">' +
            '<textarea id="txtArea"></textarea>' +
          '</div>' +
        '</div>' +
        '</div>'
913
914
915
916
917
918
919
    var $template = $(templateHTML)
    var done = assert.async()
    $template.appendTo('#qunit-fixture')
    var $inputText = $template.find('#inputText')
    var $textArea = $template.find('#txtArea')
    $template.bootstrapCarousel()

XhmikosR's avatar
XhmikosR committed
920
921
922
    var eventKeyDown = $.Event('keydown', {
      which: 65
    }) // 65 for "a"
923
924
925
926
927
928
929
930
931
932
933
    $inputText.on('keydown', function (event) {
      assert.strictEqual(event.isDefaultPrevented(), false)
    })
    $inputText.trigger(eventKeyDown)

    $textArea.on('keydown', function (event) {
      assert.strictEqual(event.isDefaultPrevented(), false)
      done()
    })
    $textArea.trigger(eventKeyDown)
  })
934
935
936
937

  QUnit.test('Should not go to the next item when the carousel is not visible', function (assert) {
    assert.expect(2)
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
938
939
940
941
942
943
944
945
946
947
948
949
950
951
    var html = '<div id="myCarousel" class="carousel slide" data-interval="50" style="display: none;">' +
             '  <div class="carousel-inner">' +
             '    <div id="firstItem" class="carousel-item active">' +
             '      <img alt="">' +
             '    </div>' +
             '    <div class="carousel-item">' +
             '      <img alt="">' +
             '    </div>' +
             '    <div class="carousel-item">' +
             '      <img alt="">' +
             '    </div>' +
             '  <a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
             '  <a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
             '</div>'
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
    var $html = $(html)
    $html
      .appendTo('#qunit-fixture')
      .bootstrapCarousel()

    var $firstItem = $('#firstItem')
    setTimeout(function () {
      assert.ok($firstItem.hasClass('active'))
      $html
        .bootstrapCarousel('dispose')
        .attr('style', 'visibility: hidden;')
        .bootstrapCarousel()

      setTimeout(function () {
        assert.ok($firstItem.hasClass('active'))
        done()
      }, 80)
    }, 80)
  })
971
972
973
974

  QUnit.test('Should not go to the next item when the parent of the carousel is not visible', function (assert) {
    assert.expect(2)
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
    var html = '<div id="parent" style="display: none;">' +
             '  <div id="myCarousel" class="carousel slide" data-interval="50" style="display: none;">' +
             '    <div class="carousel-inner">' +
             '      <div id="firstItem" class="carousel-item active">' +
             '        <img alt="">' +
             '      </div>' +
             '      <div class="carousel-item">' +
             '        <img alt="">' +
             '      </div>' +
             '      <div class="carousel-item">' +
             '        <img alt="">' +
             '      </div>' +
             '    <a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' +
             '    <a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' +
             '  </div>' +
             '</div>'
991
992
993
994
995
996
997
998
999
1000
    var $html = $(html)
    $html.appendTo('#qunit-fixture')
    var $parent = $html.find('#parent')
    var $carousel = $html.find('#myCarousel')
    $carousel.bootstrapCarousel()
    var $firstItem = $('#firstItem')

    setTimeout(function () {
      assert.ok($firstItem.hasClass('active'))
      $carousel.bootstrapCarousel('dispose')
For faster browsing, not all history is shown. View entire blame