diff options
| author | Gleb Mazovetskiy <[email protected]> | 2015-08-31 13:03:09 +0100 |
|---|---|---|
| committer | Gleb Mazovetskiy <[email protected]> | 2015-08-31 13:03:09 +0100 |
| commit | 33a510c63c9a898d68da807205afbbb8e1dfce16 (patch) | |
| tree | c953ef46e464dd1556c3b11fab8b10b300bc8b29 | |
| parent | 8941bdfbda237bed621935cac439520eddc79150 (diff) | |
| parent | c7d8e7a0777da91df2359655a7132e2b55482c0a (diff) | |
| download | bootstrap-33a510c63c9a898d68da807205afbbb8e1dfce16.tar.xz bootstrap-33a510c63c9a898d68da807205afbbb8e1dfce16.zip | |
Merge pull request #17402 from twbs/pr-14552-v4
Accept elements as the tooltip / popover content
| -rw-r--r-- | docs/components/popovers.md | 4 | ||||
| -rw-r--r-- | docs/components/tooltips.md | 2 | ||||
| -rw-r--r-- | js/src/popover.js | 21 | ||||
| -rw-r--r-- | js/src/tooltip.js | 26 | ||||
| -rw-r--r-- | js/tests/unit/popover.js | 36 | ||||
| -rw-r--r-- | js/tests/unit/tooltip.js | 29 |
6 files changed, 93 insertions, 25 deletions
diff --git a/docs/components/popovers.md b/docs/components/popovers.md index 98672d23e..f48d860ea 100644 --- a/docs/components/popovers.md +++ b/docs/components/popovers.md @@ -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> @@ -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> diff --git a/docs/components/tooltips.md b/docs/components/tooltips.md index 65bd2703b..f2936469b 100644 --- a/docs/components/tooltips.md +++ b/docs/components/tooltips.md @@ -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> diff --git a/js/src/popover.js b/js/src/popover.js index 99e48e64f..b8b24a1c4 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -34,7 +34,7 @@ const Popover = (($) => { }) const DefaultType = $.extend({}, Tooltip.DefaultType, { - content : '(string|function)' + content : '(string|element|function)' }) const ClassName = { @@ -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) diff --git a/js/src/tooltip.js b/js/src/tooltip.js index aa5c73945..151cd6f51 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -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', @@ -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') diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js index 8347e9f03..894468695 100644 --- a/js/tests/unit/popover.js +++ b/js/tests/unit/popover.js @@ -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 (╯°□°)╯︵ ┻━┻') diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js index f4deb29f8..934e26b9e 100644 --- a/js/tests/unit/tooltip.js +++ b/js/tests/unit/tooltip.js @@ -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"/>') |
