4 QUnit.module('tooltip plugin')
6 QUnit.test('should be defined on jquery object', function (assert) {
8 assert.ok($(document.body).tooltip, 'tooltip method is defined')
11 QUnit.module('tooltip', {
12 beforeEach: function () {
13 // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
14 $.fn.bootstrapTooltip = $.fn.tooltip.noConflict()
16 afterEach: function () {
17 $.fn.tooltip = $.fn.bootstrapTooltip
18 delete $.fn.bootstrapTooltip
22 QUnit.test('should provide no conflict', function (assert) {
24 assert.strictEqual($.fn.tooltip, undefined, 'tooltip was set back to undefined (org value)')
27 QUnit.test('should return jquery collection containing the element', function (assert) {
30 var $tooltip = $el.bootstrapTooltip()
31 assert.ok($tooltip instanceof $, 'returns jquery collection')
32 assert.strictEqual($tooltip[0], $el[0], 'collection contains element')
35 QUnit.test('should expose default settings', function (assert) {
37 assert.ok($.fn.bootstrapTooltip.Constructor.DEFAULTS, 'defaults is defined')
40 QUnit.test('should empty title attribute', function (assert) {
42 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>').bootstrapTooltip()
43 assert.strictEqual($trigger.attr('title'), '', 'title attribute was emptied')
46 QUnit.test('should add data attribute for referencing original title', function (assert) {
48 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>').bootstrapTooltip()
49 assert.strictEqual($trigger.attr('data-original-title'), 'Another tooltip', 'original title preserved in data attribute')
52 QUnit.test('should add aria-describedby to the trigger on show', function (assert) {
54 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
56 .appendTo('#qunit-fixture')
57 .bootstrapTooltip('show')
59 var id = $('.tooltip').attr('id')
61 assert.strictEqual($('#' + id).length, 1, 'has a unique id')
62 assert.strictEqual($('.tooltip').attr('aria-describedby'), $trigger.attr('id'), 'tooltip id and aria-describedby on trigger match')
63 assert.ok($trigger[0].hasAttribute('aria-describedby'), 'trigger has aria-describedby')
66 QUnit.test('should remove aria-describedby from trigger on hide', function (assert) {
68 var $trigger = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
70 .appendTo('#qunit-fixture')
72 $trigger.bootstrapTooltip('show')
73 assert.ok($trigger[0].hasAttribute('aria-describedby'), 'trigger has aria-describedby')
75 $trigger.bootstrapTooltip('hide')
76 assert.ok(!$trigger[0].hasAttribute('aria-describedby'), 'trigger does not have aria-describedby')
79 QUnit.test('should assign a unique id tooltip element', function (assert) {
81 $('<a href="#" rel="tooltip" title="Another tooltip"/>')
82 .appendTo('#qunit-fixture')
83 .bootstrapTooltip('show')
85 var id = $('.tooltip').attr('id')
87 assert.strictEqual($('#' + id).length, 1, 'tooltip has unique id')
88 assert.strictEqual(id.indexOf('tooltip'), 0, 'tooltip id has prefix')
91 QUnit.test('should place tooltips relative to placement option', function (assert) {
93 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
94 .appendTo('#qunit-fixture')
95 .bootstrapTooltip({ placement: 'bottom' })
97 $tooltip.bootstrapTooltip('show')
98 assert.ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
100 $tooltip.bootstrapTooltip('hide')
101 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed')
104 QUnit.test('should allow html entities', function (assert) {
106 var $tooltip = $('<a href="#" rel="tooltip" title="<b>@fat</b>"/>')
107 .appendTo('#qunit-fixture')
108 .bootstrapTooltip({ html: true })
110 $tooltip.bootstrapTooltip('show')
111 assert.notEqual($('.tooltip b').length, 0, 'b tag was inserted')
113 $tooltip.bootstrapTooltip('hide')
114 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed')
117 QUnit.test('should respect custom classes', function (assert) {
119 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
120 .appendTo('#qunit-fixture')
121 .bootstrapTooltip({ template: '<div class="tooltip some-class"><div class="tooltip-arrow"/><div class="tooltip-inner"/></div>' })
123 $tooltip.bootstrapTooltip('show')
124 assert.ok($('.tooltip').hasClass('some-class'), 'custom class is present')
126 $tooltip.bootstrapTooltip('hide')
127 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed')
130 QUnit.test('should fire show event', function (assert) {
132 var done = assert.async()
134 $('<div title="tooltip title"/>')
135 .on('show.bs.tooltip', function () {
136 assert.ok(true, 'show event fired')
139 .bootstrapTooltip('show')
142 QUnit.test('should fire shown event', function (assert) {
144 var done = assert.async()
146 $('<div title="tooltip title"></div>')
147 .appendTo('#qunit-fixture')
148 .on('shown.bs.tooltip', function () {
149 assert.ok(true, 'shown was called')
152 .bootstrapTooltip('show')
155 QUnit.test('should not fire shown event when show was prevented', function (assert) {
157 var done = assert.async()
159 $('<div title="tooltip title"/>')
160 .on('show.bs.tooltip', function (e) {
162 assert.ok(true, 'show event fired')
165 .on('shown.bs.tooltip', function () {
166 assert.ok(false, 'shown event fired')
168 .bootstrapTooltip('show')
171 QUnit.test('should fire hide event', function (assert) {
173 var done = assert.async()
175 $('<div title="tooltip title"/>')
176 .appendTo('#qunit-fixture')
177 .on('shown.bs.tooltip', function () {
178 $(this).bootstrapTooltip('hide')
180 .on('hide.bs.tooltip', function () {
181 assert.ok(true, 'hide event fired')
184 .bootstrapTooltip('show')
187 QUnit.test('should fire hidden event', function (assert) {
189 var done = assert.async()
191 $('<div title="tooltip title"/>')
192 .appendTo('#qunit-fixture')
193 .on('shown.bs.tooltip', function () {
194 $(this).bootstrapTooltip('hide')
196 .on('hidden.bs.tooltip', function () {
197 assert.ok(true, 'hidden event fired')
200 .bootstrapTooltip('show')
203 QUnit.test('should not fire hidden event when hide was prevented', function (assert) {
205 var done = assert.async()
207 $('<div title="tooltip title"/>')
208 .appendTo('#qunit-fixture')
209 .on('shown.bs.tooltip', function () {
210 $(this).bootstrapTooltip('hide')
212 .on('hide.bs.tooltip', function (e) {
214 assert.ok(true, 'hide event fired')
217 .on('hidden.bs.tooltip', function () {
218 assert.ok(false, 'hidden event fired')
220 .bootstrapTooltip('show')
223 QUnit.test('should destroy tooltip', function (assert) {
225 var $tooltip = $('<div/>')
227 .on('click.foo', function () {})
229 assert.ok($tooltip.data('bs.tooltip'), 'tooltip has data')
230 assert.ok($._data($tooltip[0], 'events').mouseover && $._data($tooltip[0], 'events').mouseout, 'tooltip has hover events')
231 assert.strictEqual($._data($tooltip[0], 'events').click[0].namespace, 'foo', 'tooltip has extra click.foo event')
233 $tooltip.bootstrapTooltip('show')
234 $tooltip.bootstrapTooltip('destroy')
236 assert.ok(!$tooltip.hasClass('in'), 'tooltip is hidden')
237 assert.ok(!$._data($tooltip[0], 'bs.tooltip'), 'tooltip does not have data')
238 assert.strictEqual($._data($tooltip[0], 'events').click[0].namespace, 'foo', 'tooltip still has click.foo')
239 assert.ok(!$._data($tooltip[0], 'events').mouseover && !$._data($tooltip[0], 'events').mouseout, 'tooltip does not have hover events')
242 QUnit.test('should show tooltip with delegate selector on click', function (assert) {
244 var $div = $('<div><a href="#" rel="tooltip" title="Another tooltip"/></div>')
245 .appendTo('#qunit-fixture')
247 selector: 'a[rel="tooltip"]',
251 $div.find('a').trigger('click')
252 assert.ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
254 $div.find('a').trigger('click')
255 assert.strictEqual($('.tooltip').length, 0, 'tooltip was removed from dom')
258 QUnit.test('should show tooltip when toggle is called', function (assert) {
260 $('<a href="#" rel="tooltip" title="tooltip on toggle"/>')
261 .appendTo('#qunit-fixture')
262 .bootstrapTooltip({ trigger: 'manual' })
263 .bootstrapTooltip('toggle')
265 assert.ok($('.tooltip').is('.fade.in'), 'tooltip is faded in')
268 QUnit.test('should hide previously shown tooltip when toggle is called on tooltip', function (assert) {
270 $('<a href="#" rel="tooltip" title="tooltip on toggle">@ResentedHook</a>')
271 .appendTo('#qunit-fixture')
272 .bootstrapTooltip({ trigger: 'manual' })
273 .bootstrapTooltip('show')
275 $('.tooltip').bootstrapTooltip('toggle')
276 assert.ok($('.tooltip').not('.fade.in'), 'tooltip was faded out')
279 QUnit.test('should place tooltips inside body when container is body', function (assert) {
281 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
282 .appendTo('#qunit-fixture')
283 .bootstrapTooltip({ container: 'body' })
284 .bootstrapTooltip('show')
286 assert.notEqual($('body > .tooltip').length, 0, 'tooltip is direct descendant of body')
287 assert.strictEqual($('#qunit-fixture > .tooltip').length, 0, 'tooltip is not in parent')
289 $tooltip.bootstrapTooltip('hide')
290 assert.strictEqual($('body > .tooltip').length, 0, 'tooltip was removed from dom')
293 QUnit.test('should add position class before positioning so that position-specific styles are taken into account', function (assert) {
295 var styles = '<style>'
296 + '.tooltip.right { white-space: nowrap; }'
297 + '.tooltip.right .tooltip-inner { max-width: none; }'
299 var $styles = $(styles).appendTo('head')
301 var $container = $('<div/>').appendTo('#qunit-fixture')
302 var $target = $('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"/>')
303 .appendTo($container)
308 .bootstrapTooltip('show')
309 var $tooltip = $container.find('.tooltip')
311 // this is some dumb hack shit because sub pixels in firefox
312 var top = Math.round($target.offset().top + ($target[0].offsetHeight / 2) - ($tooltip[0].offsetHeight / 2))
313 var top2 = Math.round($tooltip.offset().top)
314 var topDiff = top - top2
315 assert.ok(topDiff <= 1 && topDiff >= -1)
316 $target.bootstrapTooltip('hide')
322 QUnit.test('should use title attribute for tooltip text', function (assert) {
324 var $tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip"/>')
325 .appendTo('#qunit-fixture')
328 $tooltip.bootstrapTooltip('show')
329 assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title from title attribute is set')
331 $tooltip.bootstrapTooltip('hide')
332 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
335 QUnit.test('should prefer title attribute over title option', function (assert) {
337 var $tooltip = $('<a href="#" rel="tooltip" title="Simple tooltip"/>')
338 .appendTo('#qunit-fixture')
340 title: 'This is a tooltip with some content'
343 $tooltip.bootstrapTooltip('show')
344 assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'Simple tooltip', 'title is set from title attribute while preferred over title option')
346 $tooltip.bootstrapTooltip('hide')
347 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
350 QUnit.test('should use title option', function (assert) {
352 var $tooltip = $('<a href="#" rel="tooltip"/>')
353 .appendTo('#qunit-fixture')
355 title: 'This is a tooltip with some content'
358 $tooltip.bootstrapTooltip('show')
359 assert.strictEqual($('.tooltip').children('.tooltip-inner').text(), 'This is a tooltip with some content', 'title from title option is set')
361 $tooltip.bootstrapTooltip('hide')
362 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
365 QUnit.test('should be placed dynamically with the dynamic placement option', function (assert) {
367 var $style = $('<style> a[rel="tooltip"] { display: inline-block; position: absolute; } </style>')
368 var $container = $('<div/>')
370 position: 'absolute',
377 .appendTo(document.body)
379 var $topTooltip = $('<div style="left: 0; top: 0;" rel="tooltip" title="Top tooltip">Top Dynamic Tooltip</div>')
380 .appendTo($container)
381 .bootstrapTooltip({ placement: 'auto' })
383 $topTooltip.bootstrapTooltip('show')
384 assert.ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned to bottom')
386 $topTooltip.bootstrapTooltip('hide')
387 assert.strictEqual($('.tooltip').length, 0, 'top positioned tooltip removed from dom')
389 var $rightTooltip = $('<div style="right: 0;" rel="tooltip" title="Right tooltip">Right Dynamic Tooltip</div>')
390 .appendTo($container)
391 .bootstrapTooltip({ placement: 'right auto' })
393 $rightTooltip.bootstrapTooltip('show')
394 assert.ok($('.tooltip').is('.left'), 'right positioned tooltip is dynamically positioned left')
396 $rightTooltip.bootstrapTooltip('hide')
397 assert.strictEqual($('.tooltip').length, 0, 'right positioned tooltip removed from dom')
399 var $leftTooltip = $('<div style="left: 0;" rel="tooltip" title="Left tooltip">Left Dynamic Tooltip</div>')
400 .appendTo($container)
401 .bootstrapTooltip({ placement: 'auto left' })
403 $leftTooltip.bootstrapTooltip('show')
404 assert.ok($('.tooltip').is('.right'), 'left positioned tooltip is dynamically positioned right')
406 $leftTooltip.bootstrapTooltip('hide')
407 assert.strictEqual($('.tooltip').length, 0, 'left positioned tooltip removed from dom')
413 QUnit.test('should position tip on top if viewport has enough space and placement is "auto top"', function (assert) {
415 var styles = '<style>'
416 + 'body { padding-top: 100px; }'
417 + '#section { height: 300px; border: 1px solid red; padding-top: 50px }'
418 + 'div[rel="tooltip"] { width: 150px; border: 1px solid blue; }'
420 var $styles = $(styles).appendTo('head')
422 var $container = $('<div id="section"/>').appendTo('#qunit-fixture')
423 var $target = $('<div rel="tooltip" title="tip"/>')
424 .appendTo($container)
426 placement: 'auto top',
430 $target.bootstrapTooltip('show')
431 assert.ok($('.tooltip').is('.top'), 'top positioned tooltip is dynamically positioned to top')
433 $target.bootstrapTooltip('hide')
434 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
439 QUnit.test('should position tip on bottom if the tip\'s dimension exceeds the viewport area and placement is "auto top"', function (assert) {
441 var styles = '<style>'
442 + 'body { padding-top: 100px; }'
443 + '#section { height: 300px; border: 1px solid red; }'
444 + 'div[rel="tooltip"] { width: 150px; border: 1px solid blue; }'
446 var $styles = $(styles).appendTo('head')
448 var $container = $('<div id="section"/>').appendTo('#qunit-fixture')
449 var $target = $('<div rel="tooltip" title="tip"/>')
450 .appendTo($container)
452 placement: 'auto top',
456 $target.bootstrapTooltip('show')
457 assert.ok($('.tooltip').is('.bottom'), 'top positioned tooltip is dynamically positioned to bottom')
459 $target.bootstrapTooltip('hide')
460 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
465 QUnit.test('should display the tip on top whenever scrollable viewport has enough room if the given placement is "auto top"', function (assert) {
467 var styles = '<style>'
468 + '#scrollable-div { height: 200px; overflow: auto; }'
469 + '.tooltip-item { margin: 200px 0 400px; width: 150px; }'
471 var $styles = $(styles).appendTo('head')
473 var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
474 var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
475 .appendTo($container)
477 placement: 'top auto',
478 viewport: '#scrollable-div'
481 $('#scrollable-div').scrollTop(100)
483 $target.bootstrapTooltip('show')
484 assert.ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
486 $target.bootstrapTooltip('hide')
487 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
492 QUnit.test('should display the tip on bottom whenever scrollable viewport doesn\'t have enough room if the given placement is "auto top"', function (assert) {
494 var styles = '<style>'
495 + '#scrollable-div { height: 200px; overflow: auto; }'
496 + '.tooltip-item { padding: 200px 0 400px; width: 150px; }'
498 var $styles = $(styles).appendTo('head')
500 var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
501 var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
502 .appendTo($container)
504 placement: 'top auto',
505 viewport: '#scrollable-div'
508 $('#scrollable-div').scrollTop(200)
510 $target.bootstrapTooltip('show')
511 assert.ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
513 $target.bootstrapTooltip('hide')
514 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
519 QUnit.test('should display the tip on bottom whenever scrollable viewport has enough room if the given placement is "auto bottom"', function (assert) {
521 var styles = '<style>'
522 + '#scrollable-div { height: 200px; overflow: auto; }'
523 + '.spacer { height: 400px; }'
524 + '.spacer:first-child { height: 200px; }'
525 + '.tooltip-item { width: 150px; }'
527 var $styles = $(styles).appendTo('head')
529 var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
530 var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
531 .appendTo($container)
532 .before('<div class="spacer"/>')
533 .after('<div class="spacer"/>')
535 placement: 'bottom auto',
536 viewport: '#scrollable-div'
539 $('#scrollable-div').scrollTop(200)
541 $target.bootstrapTooltip('show')
542 assert.ok($('.tooltip').is('.fade.bottom.in'), 'has correct classes applied')
544 $target.bootstrapTooltip('hide')
545 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
550 QUnit.test('should display the tip on top whenever scrollable viewport doesn\'t have enough room if the given placement is "auto bottom"', function (assert) {
552 var styles = '<style>'
553 + '#scrollable-div { height: 200px; overflow: auto; }'
554 + '.tooltip-item { margin-top: 400px; width: 150px; }'
556 var $styles = $(styles).appendTo('head')
558 var $container = $('<div id="scrollable-div"/>').appendTo('#qunit-fixture')
559 var $target = $('<div rel="tooltip" title="tip" class="tooltip-item">Tooltip Item</div>')
560 .appendTo($container)
562 placement: 'bottom auto',
563 viewport: '#scrollable-div'
566 $('#scrollable-div').scrollTop(400)
568 $target.bootstrapTooltip('show')
569 assert.ok($('.tooltip').is('.fade.top.in'), 'has correct classes applied')
571 $target.bootstrapTooltip('hide')
572 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
577 QUnit.test('should adjust the tip\'s top position when up against the top of the viewport', function (assert) {
579 var styles = '<style>'
580 + '.tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
581 + 'a[rel="tooltip"] { position: fixed; }'
583 var $styles = $(styles).appendTo('head')
585 var $container = $('<div/>').appendTo('#qunit-fixture')
586 var $target = $('<a href="#" rel="tooltip" title="tip" style="top: 0px; left: 0px;"/>')
587 .appendTo($container)
596 $target.bootstrapTooltip('show')
597 assert.strictEqual(Math.round($container.find('.tooltip').offset().top), 12)
599 $target.bootstrapTooltip('hide')
600 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
605 QUnit.test('should adjust the tip\'s top position when up against the bottom of the viewport', function (assert) {
607 var styles = '<style>'
608 + '.tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
609 + 'a[rel="tooltip"] { position: fixed; }'
611 var $styles = $(styles).appendTo('head')
613 var $container = $('<div/>').appendTo('#qunit-fixture')
614 var $target = $('<a href="#" rel="tooltip" title="tip" style="bottom: 0px; left: 0px;"/>')
615 .appendTo($container)
624 $target.bootstrapTooltip('show')
625 var $tooltip = $container.find('.tooltip')
626 assert.strictEqual(Math.round($tooltip.offset().top), Math.round($(window).height() - 12 - $tooltip[0].offsetHeight))
628 $target.bootstrapTooltip('hide')
629 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
635 QUnit.test('should adjust the tip\'s left position when up against the left of the viewport', function (assert) {
637 var styles = '<style>'
638 + '.tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
639 + 'a[rel="tooltip"] { position: fixed; }'
641 var $styles = $(styles).appendTo('head')
643 var $container = $('<div/>').appendTo('#qunit-fixture')
644 var $target = $('<a href="#" rel="tooltip" title="tip" style="top: 0px; left: 0px;"/>')
645 .appendTo($container)
654 $target.bootstrapTooltip('show')
655 assert.strictEqual(Math.round($container.find('.tooltip').offset().left), 12)
657 $target.bootstrapTooltip('hide')
658 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
664 QUnit.test('should adjust the tip\'s left position when up against the right of the viewport', function (assert) {
666 var styles = '<style>'
667 + '.tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
668 + 'a[rel="tooltip"] { position: fixed; }'
670 var $styles = $(styles).appendTo('head')
672 var $container = $('<div/>').appendTo('body')
673 var $target = $('<a href="#" rel="tooltip" title="tip" style="top: 0px; right: 0px;"/>')
674 .appendTo($container)
683 $target.bootstrapTooltip('show')
684 var $tooltip = $container.find('.tooltip')
685 assert.strictEqual(Math.round($tooltip.offset().left), Math.round($(window).width() - 12 - $tooltip[0].offsetWidth))
687 $target.bootstrapTooltip('hide')
688 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
694 QUnit.test('should adjust the tip when up against the right of an arbitrary viewport', function (assert) {
696 var styles = '<style>'
697 + '.tooltip, .tooltip .tooltip-inner { width: 200px; height: 200px; max-width: none; }'
698 + '.container-viewport { position: absolute; top: 50px; left: 60px; width: 300px; height: 300px; }'
699 + 'a[rel="tooltip"] { position: fixed; }'
701 var $styles = $(styles).appendTo('head')
703 var $container = $('<div class="container-viewport"/>').appendTo(document.body)
704 var $target = $('<a href="#" rel="tooltip" title="tip" style="top: 50px; left: 350px;"/>')
705 .appendTo($container)
708 viewport: '.container-viewport'
711 $target.bootstrapTooltip('show')
712 var $tooltip = $container.find('.tooltip')
713 assert.strictEqual(Math.round($tooltip.offset().left), Math.round(60 + $container.width() - $tooltip[0].offsetWidth))
715 $target.bootstrapTooltip('hide')
716 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
722 QUnit.test('should not error when trying to show an auto-placed tooltip that has been removed from the dom', function (assert) {
725 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
726 .appendTo('#qunit-fixture')
727 .one('show.bs.tooltip', function () {
730 .bootstrapTooltip({ placement: 'auto' })
733 $tooltip.bootstrapTooltip('show')
739 assert.ok(passed, '.tooltip(\'show\') should not throw an error if element no longer is in dom')
742 QUnit.test('should place tooltip on top of element', function (assert) {
744 var done = assert.async()
746 var containerHTML = '<div>'
747 + '<p style="margin-top: 200px">'
748 + '<a href="#" title="very very very very very very very long tooltip">Hover me</a>'
752 var $container = $(containerHTML)
754 position: 'absolute',
761 .appendTo('#qunit-fixture')
763 var $trigger = $container
765 .css('margin-top', 200)
770 .bootstrapTooltip('show')
772 var $tooltip = $container.find('.tooltip')
774 setTimeout(function () {
775 assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) <= Math.round($trigger.offset().top))
780 QUnit.test('should place tooltip inside viewport', function (assert) {
782 var done = assert.async()
784 var $container = $('<div/>')
786 position: 'absolute',
792 .appendTo('#qunit-fixture')
794 $('<a href="#" title="Very very very very very very very very long tooltip">Hover me</a>')
796 position: 'absolute',
800 .appendTo($container)
804 .bootstrapTooltip('show')
806 setTimeout(function () {
807 assert.ok($('.tooltip').offset().left >= 0)
812 QUnit.test('should show tooltip if leave event hasn\'t occurred before delay expires', function (assert) {
814 var done = assert.async()
816 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
817 .appendTo('#qunit-fixture')
818 .bootstrapTooltip({ delay: 150 })
820 setTimeout(function () {
821 assert.ok(!$('.tooltip').is('.fade.in'), '100ms: tooltip is not faded in')
824 setTimeout(function () {
825 assert.ok($('.tooltip').is('.fade.in'), '200ms: tooltip is faded in')
829 $tooltip.trigger('mouseenter')
832 QUnit.test('should not show tooltip if leave event occurs before delay expires', function (assert) {
834 var done = assert.async()
836 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
837 .appendTo('#qunit-fixture')
838 .bootstrapTooltip({ delay: 150 })
840 setTimeout(function () {
841 assert.ok(!$('.tooltip').is('.fade.in'), '100ms: tooltip not faded in')
842 $tooltip.trigger('mouseout')
845 setTimeout(function () {
846 assert.ok(!$('.tooltip').is('.fade.in'), '200ms: tooltip not faded in')
850 $tooltip.trigger('mouseenter')
853 QUnit.test('should not hide tooltip if leave event occurs and enter event occurs within the hide delay', function (assert) {
855 var done = assert.async()
857 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
858 .appendTo('#qunit-fixture')
859 .bootstrapTooltip({ delay: { show: 0, hide: 150 }})
861 setTimeout(function () {
862 assert.ok($('.tooltip').is('.fade.in'), '1ms: tooltip faded in')
863 $tooltip.trigger('mouseout')
865 setTimeout(function () {
866 assert.ok($('.tooltip').is('.fade.in'), '100ms: tooltip still faded in')
867 $tooltip.trigger('mouseenter')
870 setTimeout(function () {
871 assert.ok($('.tooltip').is('.fade.in'), '200ms: tooltip still faded in')
876 $tooltip.trigger('mouseenter')
879 QUnit.test('should not show tooltip if leave event occurs before delay expires', function (assert) {
881 var done = assert.async()
883 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
884 .appendTo('#qunit-fixture')
885 .bootstrapTooltip({ delay: 150 })
887 setTimeout(function () {
888 assert.ok(!$('.tooltip').is('.fade.in'), '100ms: tooltip not faded in')
889 $tooltip.trigger('mouseout')
892 setTimeout(function () {
893 assert.ok(!$('.tooltip').is('.fade.in'), '200ms: tooltip not faded in')
897 $tooltip.trigger('mouseenter')
900 QUnit.test('should not show tooltip if leave event occurs before delay expires, even if hide delay is 0', function (assert) {
902 var done = assert.async()
904 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
905 .appendTo('#qunit-fixture')
906 .bootstrapTooltip({ delay: { show: 150, hide: 0 }})
908 setTimeout(function () {
909 assert.ok(!$('.tooltip').is('.fade.in'), '100ms: tooltip not faded in')
910 $tooltip.trigger('mouseout')
913 setTimeout(function () {
914 assert.ok(!$('.tooltip').is('.fade.in'), '250ms: tooltip not faded in')
918 $tooltip.trigger('mouseenter')
921 QUnit.test('should wait 200ms before hiding the tooltip', function (assert) {
923 var done = assert.async()
925 var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
926 .appendTo('#qunit-fixture')
927 .bootstrapTooltip({ delay: { show: 0, hide: 150 }})
929 setTimeout(function () {
930 assert.ok($tooltip.data('bs.tooltip').$tip.is('.fade.in'), '1ms: tooltip faded in')
932 $tooltip.trigger('mouseout')
934 setTimeout(function () {
935 assert.ok($tooltip.data('bs.tooltip').$tip.is('.fade.in'), '100ms: tooltip still faded in')
938 setTimeout(function () {
939 assert.ok(!$tooltip.data('bs.tooltip').$tip.is('.in'), '200ms: tooltip removed')
945 $tooltip.trigger('mouseenter')
948 QUnit.test('should correctly position tooltips on SVG elements', function (assert) {
949 if (!window.SVGElement) {
950 // Skip IE8 since it doesn't support SVG
956 var done = assert.async()
958 var styles = '<style>'
959 + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
960 + '.tooltip { position: absolute; }'
961 + '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
963 var $styles = $(styles).appendTo('head')
965 $('#qunit-fixture').append(
966 '<div style="position: fixed; top: 0; left: 0;">'
967 + ' <svg width="200" height="200">'
968 + ' <circle cx="100" cy="100" r="10" title="m" id="theCircle" />'
971 var $circle = $('#theCircle')
974 .on('shown.bs.tooltip', function () {
975 var offset = $('.tooltip').offset()
977 assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
978 $circle.bootstrapTooltip('hide')
979 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
982 .bootstrapTooltip({ container: 'body', placement: 'top', trigger: 'manual' })
984 $circle.bootstrapTooltip('show')
987 QUnit.test('should correctly determine auto placement based on container rather than parent', function (assert) {
989 var done = assert.async()
991 var styles = '<style>'
992 + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
993 + '.tooltip { position: absolute; display: block; font-size: 12px; line-height: 1.4; }'
994 + '.tooltip .tooltip-inner { max-width: 200px; padding: 3px 8px; font-family: Helvetica; text-align: center; }'
995 + '#trigger-parent {'
996 + ' position: fixed;'
1001 var $styles = $(styles).appendTo('head')
1003 $('#qunit-fixture').append('<span id="trigger-parent"><a id="tt-trigger" title="If a_larger_text is written here, it won\'t fit using older broken version of BS">HOVER OVER ME</a></span>')
1004 var $trigger = $('#tt-trigger')
1007 .on('shown.bs.tooltip', function () {
1008 var $tip = $('.tooltip-inner')
1009 var tipXrightEdge = $tip.offset().left + $tip.width()
1010 var triggerXleftEdge = $trigger.offset().left
1011 assert.ok(tipXrightEdge < triggerXleftEdge, 'tooltip with auto left placement, when near the right edge of the viewport, gets left placement')
1012 $trigger.bootstrapTooltip('hide')
1014 .on('hidden.bs.tooltip', function () {
1017 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
1022 placement: 'auto left',
1026 $trigger.bootstrapTooltip('show')
1029 QUnit.test('should not reload the tooltip on subsequent mouseenter events', function (assert) {
1031 var titleHtml = function () {
1032 var uid = $.fn.bootstrapTooltip.Constructor.prototype.getUID('tooltip')
1033 return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
1036 var $tooltip = $('<span id="tt-outer" rel="tooltip" data-trigger="hover" data-placement="top">some text</span>')
1037 .appendTo('#qunit-fixture')
1039 $tooltip.bootstrapTooltip({
1043 delay: { show: 0, hide: 500 },
1044 container: $tooltip,
1048 $('#tt-outer').trigger('mouseenter')
1050 var currentUid = $('#tt-content').text()
1052 $('#tt-content').trigger('mouseenter')
1053 assert.strictEqual(currentUid, $('#tt-content').text())
1056 QUnit.test('should not reload the tooltip if the mouse leaves and re-enters before hiding', function (assert) {
1058 var titleHtml = function () {
1059 var uid = $.fn.bootstrapTooltip.Constructor.prototype.getUID('tooltip')
1060 return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
1063 var $tooltip = $('<span id="tt-outer" rel="tooltip" data-trigger="hover" data-placement="top">some text</span>')
1064 .appendTo('#qunit-fixture')
1066 $tooltip.bootstrapTooltip({
1070 delay: { show: 0, hide: 500 },
1071 container: $tooltip,
1075 var obj = $tooltip.data('bs.tooltip')
1077 $('#tt-outer').trigger('mouseenter')
1079 var currentUid = $('#tt-content').text()
1081 $('#tt-outer').trigger('mouseleave')
1082 assert.strictEqual(currentUid, $('#tt-content').text())
1084 assert.ok(obj.hoverState == 'out', 'the tooltip hoverState should be set to "out"')
1086 $('#tt-content').trigger('mouseenter')
1087 assert.ok(obj.hoverState == 'in', 'the tooltip hoverState should be set to "in"')
1089 assert.strictEqual(currentUid, $('#tt-content').text())
1092 QUnit.test('should position arrow correctly when tooltip is moved to not appear offscreen', function (assert) {
1094 var done = assert.async()
1096 var styles = '<style>'
1097 + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
1098 + '.tooltip { position: absolute; }'
1099 + '.tooltip-arrow { position: absolute; width: 0; height: 0; }'
1100 + '.tooltip .tooltip-inner { max-width: 200px; padding: 3px 8px; }'
1102 var $styles = $(styles).appendTo('head')
1104 $('<a href="#" title="tooltip title" style="position: absolute; bottom: 0; right: 0;">Foobar</a>')
1106 .on('shown.bs.tooltip', function () {
1107 var arrowStyles = $(this).data('bs.tooltip').$tip.find('.tooltip-arrow').attr('style')
1108 assert.ok(/left/i.test(arrowStyles) && !/top/i.test(arrowStyles), 'arrow positioned correctly')
1109 $(this).bootstrapTooltip('hide')
1111 .on('hidden.bs.tooltip', function () {
1114 assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
1122 .bootstrapTooltip('show')
1125 QUnit.test('should correctly position tooltips on transformed elements', function (assert) {
1126 var styleProps = document.documentElement.style
1127 if (!('transform' in styleProps) && !('webkitTransform' in styleProps) && !('msTransform' in styleProps)) {
1133 var done = assert.async()
1135 var styles = '<style>'
1136 + '#qunit-fixture { top: 0; left: 0; }'
1137 + '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
1138 + '.tooltip { position: absolute; }'
1139 + '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
1140 + '#target { position: absolute; top: 100px; left: 50px; width: 100px; height: 200px; -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }'
1142 var $styles = $(styles).appendTo('head')
1144 var $element = $('<div id="target" title="1"/>').appendTo('#qunit-fixture')
1147 .on('shown.bs.tooltip', function () {
1148 var offset = $('.tooltip').offset()
1150 assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
1151 assert.ok(Math.abs(offset.top - 126) <= 1, 'tooltip has correct vertical location')
1152 $element.bootstrapTooltip('hide')
1161 $element.bootstrapTooltip('show')
1164 QUnit.test('should throw an error when initializing tooltip on the document object without specifying a delegation selector', function (assert) {
1166 assert.throws(function () {
1167 $(document).bootstrapTooltip({ title: 'What am I on?' })
1168 }, new Error('`selector` option must be specified when initializing tooltip on the window.document object!'))
1171 QUnit.test('should do nothing when an attempt is made to hide an uninitialized tooltip', function (assert) {
1174 var $tooltip = $('<span data-toggle="tooltip" title="some tip">some text</span>')
1175 .appendTo('#qunit-fixture')
1176 .on('hidden.bs.tooltip shown.bs.tooltip', function () {
1177 assert.ok(false, 'should not fire any tooltip events')
1179 .bootstrapTooltip('hide')
1180 assert.strictEqual($tooltip.data('bs.tooltip'), undefined, 'should not initialize the tooltip')