diff --git a/docs/_includes/js/popovers.html b/docs/_includes/js/popovers.html index 9e2532733f2cf45045811bd53a4278a954c6f71d..bd1074b29e550e4f1d6e0fcd24d7e7d29af07bfe 100644 --- a/docs/_includes/js/popovers.html +++ b/docs/_includes/js/popovers.html @@ -166,7 +166,7 @@ sagittis lacus vel augue laoreet rutrum faucibus."> </tr> <tr> <td>content</td> - <td>string | function</td> + <td>string | HTMLElement | jQuery node | function</td> <td>''</td> <td> <p>Default content value if <code>data-content</code> attribute isn't present.</p> @@ -218,7 +218,7 @@ sagittis lacus vel augue laoreet rutrum faucibus."> </tr> <tr> <td>title</td> - <td>string | function</td> + <td>string | HTMLElement | jQuery node | function</td> <td>''</td> <td> <p>Default title value if <code>title</code> attribute isn't present.</p> diff --git a/docs/_includes/js/tooltips.html b/docs/_includes/js/tooltips.html index 991c0c9c94c42430df06e35af16bb0aea82b1545..208aed56a118257c47c46b19f2c57a89255c7882 100644 --- a/docs/_includes/js/tooltips.html +++ b/docs/_includes/js/tooltips.html @@ -184,7 +184,7 @@ $('#example').tooltip(options) </tr> <tr> <td>title</td> - <td>string | function</td> + <td>string | HTMLElement | jQuery node | function</td> <td>''</td> <td> <p>Default title value if <code>title</code> attribute isn't present.</p> diff --git a/js/popover.js b/js/popover.js index 0b0755ee27bb7882fa6786c13408e2e8b0b3b7a7..d2343e73e18eeb4cc71eca2885ba79fc01134b94 100644 --- a/js/popover.js +++ b/js/popover.js @@ -41,14 +41,10 @@ } Popover.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - var content = this.getContent() - - $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events - this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' - ](content) + var $tip = this.tip() + + this.setElementContent($tip.find('.popover-title'), this.getTitle()) + this.setElementContent($tip.find('.popover-content'), this.getContent()) $tip.removeClass('fade top bottom left right in') diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js index d4c016fc71a83c61d6d6cb330c947e0feeb43775..a332c44c5c1e375e754be22029655baacc3474a9 100644 --- a/js/tests/unit/popover.js +++ b/js/tests/unit/popover.js @@ -84,6 +84,41 @@ $(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 (╯°□°)╯︵ â”»â”â”»') @@ -98,14 +133,14 @@ $(function () { $popover.bootstrapPopover('show') assert.notEqual($('.popover').length, 0, 'popover was inserted') - assert.equal($('.popover .popover-content').html(), $div, 'content correctly inserted') + assert.strictEqual($('.popover .popover-content').html(), $div.html(), 'content correctly inserted') $popover.bootstrapPopover('hide') assert.strictEqual($('.popover').length, 0, 'popover was removed') $popover.bootstrapPopover('show') assert.notEqual($('.popover').length, 0, 'popover was inserted') - assert.equal($('.popover .popover-content').html(), $div, 'content correctly inserted') + assert.strictEqual($('.popover .popover-content').html(), $div.html(), 'content correctly inserted') $popover.bootstrapPopover('hide') assert.strictEqual($('.popover').length, 0, 'popover was removed') diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js index 27ce6208e7279dfb96f365df9046419467cbdca2..b9b83a5f3b15999a0e1f3fdd9c8ef36d2de817f3 100644 --- a/js/tests/unit/tooltip.js +++ b/js/tests/unit/tooltip.js @@ -114,6 +114,34 @@ $(function () { assert.strictEqual($('.tooltip').length, 0, '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"/>') diff --git a/js/tooltip.js b/js/tooltip.js index 0779f139d6ccd8349f5ac1a2a8610a4a2515047e..3d26f47f39d00e0254f944139facc86522db058d 100644 --- a/js/tooltip.js +++ b/js/tooltip.js @@ -304,12 +304,25 @@ Tooltip.prototype.setContent = function () { var $tip = this.tip() - var title = this.getTitle() - $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + this.setElementContent($tip.find('.tooltip-inner'), this.getTitle()) $tip.removeClass('fade in top bottom left right') } + Tooltip.prototype.setElementContent = function ($element, content) { + var html = this.options.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) + } + } + Tooltip.prototype.hide = function (callback) { var that = this var $tip = $(this.$tip)