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)