Skip to content

Commit

Permalink
Merge pull request #17402 from twbs/pr-14552-v4
Browse files Browse the repository at this point in the history
Accept elements as the tooltip / popover content
  • Loading branch information
glebm committed Aug 31, 2015
2 parents 8941bdf + c7d8e7a commit 33a510c
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 25 deletions.
4 changes: 2 additions & 2 deletions docs/components/popovers.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
</tr>
<tr>
<td>content</td>
<td>string | function</td>
<td>string | element | function</td>
<td>''</td>
<td>
<p>Default content value if <code>data-content</code> attribute isn't present.</p>
Expand Down Expand Up @@ -245,7 +245,7 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
</tr>
<tr>
<td>title</td>
<td>string | function</td>
<td>string | element | function</td>
<td>''</td>
<td>
<p>Default title value if <code>title</code> attribute isn't present.</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/components/tooltips.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
</tr>
<tr>
<td>title</td>
<td>string | function</td>
<td>string | element | function</td>
<td>''</td>
<td>
<p>Default title value if <code>title</code> attribute isn't present.</p>
Expand Down
21 changes: 5 additions & 16 deletions js/src/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const Popover = (($) => {
})

const DefaultType = $.extend({}, Tooltip.DefaultType, {
content : '(string|function)'
content : '(string|element|function)'
})

const ClassName = {
Expand Down Expand Up @@ -113,24 +113,13 @@ const Popover = (($) => {
}

setContent() {
let tip = this.getTipElement()
let title = this.getTitle()
let content = this._getContent()
let $titleElement = $(tip).find(Selector.TITLE)

if ($titleElement) {
$titleElement[
this.config.html ? 'html' : 'text'
](title)
}
let $tip = $(this.getTipElement())

// we use append for html objects to maintain js events
$(tip).find(Selector.CONTENT).children().detach().end()[
this.config.html ?
(typeof content === 'string' ? 'html' : 'append') : 'text'
](content)
this.setElementContent($tip.find(Selector.TITLE), this.getTitle())
this.setElementContent($tip.find(Selector.CONTENT), this._getContent())

$(tip)
$tip
.removeClass(ClassName.FADE)
.removeClass(ClassName.IN)

Expand Down
26 changes: 20 additions & 6 deletions js/src/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const Tooltip = (($) => {
const DefaultType = {
animation : 'boolean',
template : 'string',
title : '(string|function)',
title : '(string|element|function)',
trigger : 'string',
delay : '(number|object)',
html : 'boolean',
Expand Down Expand Up @@ -356,19 +356,33 @@ const Tooltip = (($) => {
}

setContent() {
let tip = this.getTipElement()
let title = this.getTitle()
let method = this.config.html ? 'html' : 'text'
let $tip = $(this.getTipElement())

$(tip).find(Selector.TOOLTIP_INNER)[method](title)
this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle())

$(tip)
$tip
.removeClass(ClassName.FADE)
.removeClass(ClassName.IN)

this.cleanupTether()
}

setElementContent($element, content) {
let html = this.config.html
if (typeof content === 'object' && (content.nodeType || content.jquery)) {
// content is a DOM node or a jQuery
if (html) {
if (!$(content).parent().is($element)) {
$element.empty().append(content)
}
} else {
$element.text($(content).text())
}
} else {
$element[html ? 'html' : 'text'](content)
}
}

getTitle() {
let title = this.element.getAttribute('data-original-title')

Expand Down
36 changes: 36 additions & 0 deletions js/tests/unit/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,42 @@ $(function () {
assert.strictEqual($('.popover').length, 0, 'popover was removed')
})

QUnit.test('should allow DOMElement title and content (html: true)', function (assert) {
assert.expect(5)
var title = document.createTextNode('@glebm <3 writing tests')
var content = $('<i>¯\\_(ツ)_/¯</i>').get(0)
var $popover = $('<a href="#" rel="tooltip"/>')
.appendTo('#qunit-fixture')
.bootstrapPopover({ html: true, title: title, content: content })

$popover.bootstrapPopover('show')

assert.notEqual($('.popover').length, 0, 'popover inserted')
assert.strictEqual($('.popover .popover-title').text(), '@glebm <3 writing tests', 'title inserted')
assert.ok($.contains($('.popover').get(0), title), 'title node moved, not copied')
// toLowerCase because IE8 will return <I>...</I>
assert.strictEqual($('.popover .popover-content').html().toLowerCase(), '<i>¯\\_(ツ)_/¯</i>', 'content inserted')
assert.ok($.contains($('.popover').get(0), content), 'content node moved, not copied')
})

QUnit.test('should allow DOMElement title and content (html: false)', function (assert) {
assert.expect(5)
var title = document.createTextNode('@glebm <3 writing tests')
var content = $('<i>¯\\_(ツ)_/¯</i>').get(0)
var $popover = $('<a href="#" rel="tooltip"/>')
.appendTo('#qunit-fixture')
.bootstrapPopover({ title: title, content: content })

$popover.bootstrapPopover('show')

assert.notEqual($('.popover').length, 0, 'popover inserted')
assert.strictEqual($('.popover .popover-title').text(), '@glebm <3 writing tests', 'title inserted')
assert.ok(!$.contains($('.popover').get(0), title), 'title node copied, not moved')
assert.strictEqual($('.popover .popover-content').html(), '¯\\_(ツ)_/¯', 'content inserted')
assert.ok(!$.contains($('.popover').get(0), content), 'content node copied, not moved')
})


QUnit.test('should not duplicate HTML object', function (assert) {
assert.expect(6)
var $div = $('<div/>').html('loves writing tests (╯°□°)╯︵ ┻━┻')
Expand Down
29 changes: 29 additions & 0 deletions js/tests/unit/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,35 @@ $(function () {
assert.strictEqual($tooltip.data('bs.tooltip').tip.parentNode, null, 'tooltip removed')
})

QUnit.test('should allow DOMElement title (html: false)', function (assert) {
assert.expect(3)
var title = document.createTextNode('<3 writing tests')
var $tooltip = $('<a href="#" rel="tooltip"/>')
.appendTo('#qunit-fixture')
.bootstrapTooltip({ title: title })

$tooltip.bootstrapTooltip('show')

assert.notEqual($('.tooltip').length, 0, 'tooltip inserted')
assert.strictEqual($('.tooltip').text(), '<3 writing tests', 'title inserted')
assert.ok(!$.contains($('.tooltip').get(0), title), 'title node copied, not moved')
})

QUnit.test('should allow DOMElement title (html: true)', function (assert) {
assert.expect(3)
var title = document.createTextNode('<3 writing tests')
var $tooltip = $('<a href="#" rel="tooltip"/>')
.appendTo('#qunit-fixture')
.bootstrapTooltip({ html: true, title: title })

$tooltip.bootstrapTooltip('show')

assert.notEqual($('.tooltip').length, 0, 'tooltip inserted')
assert.strictEqual($('.tooltip').text(), '<3 writing tests', 'title inserted')
assert.ok($.contains($('.tooltip').get(0), title), 'title node moved, not copied')
})


QUnit.test('should respect custom classes', function (assert) {
assert.expect(2)
var $tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"/>')
Expand Down

0 comments on commit 33a510c

Please sign in to comment.