diff --git a/js/bootstrap-tooltip.js b/js/bootstrap-tooltip.js
index 5a574fcf09f0b34e2e20ebfcfedab956797d75a5..179d926038f4392234fde4467989c646c306796e 100644
--- a/js/bootstrap-tooltip.js
+++ b/js/bootstrap-tooltip.js
@@ -103,8 +103,11 @@
         , actualHeight
         , placement
         , tp
+        , e
 
       if (this.hasContent() && this.enabled) {
+        this.$element.trigger(e = $.Event('show'))
+        if (e.isDefaultPrevented()) return
         $tip = this.tip()
         this.setContent()
 
@@ -147,6 +150,8 @@
           .offset(tp)
           .addClass(placement)
           .addClass('in')
+
+        this.$element.trigger('shown')
       }
     }
 
@@ -161,6 +166,10 @@
   , hide: function () {
       var that = this
         , $tip = this.tip()
+        , e
+
+      this.$element.trigger(e = $.Event('hide'))
+      if (e.isDefaultPrevented()) return
 
       $tip.removeClass('in')
 
@@ -179,6 +188,8 @@
         removeWithAnimation() :
         $tip.detach()
 
+      this.$element.trigger('hidden')
+
       return this
     }
 
diff --git a/js/tests/unit/bootstrap-tooltip.js b/js/tests/unit/bootstrap-tooltip.js
index ba51347433ffaa12bfbaad5023fd71865089e390..4a205ffda07a02c66f9d8808bcc3685123a5be70 100644
--- a/js/tests/unit/bootstrap-tooltip.js
+++ b/js/tests/unit/bootstrap-tooltip.js
@@ -66,6 +66,83 @@ $(function () {
         ok(!$(".tooltip").length, 'tooltip removed')
       })
 
+      test("should fire show event", function () {
+        stop()
+        var tooltip = $('<div title="tooltip title"></div>')
+          .bind("show", function() {
+            ok(true, "show was called")
+            start()
+          })
+          .tooltip('show')
+      })
+
+      test("should fire shown event", function () {
+        stop()
+        var tooltip = $('<div title="tooltip title"></div>')
+          .bind("shown", function() {
+            ok(true, "shown was called")
+            start()
+          })
+          .tooltip('show')
+      })
+
+      test("should not fire shown event when default prevented", function () {
+        stop()
+        var tooltip = $('<div title="tooltip title"></div>')
+          .bind("show", function(e) {
+            e.preventDefault()
+            ok(true, "show was called")
+            start()
+          })
+          .bind("shown", function() {
+            ok(false, "shown was called")
+          })
+          .tooltip('show')
+      })
+
+      test("should fire hide event", function () {
+        stop()
+        var tooltip = $('<div title="tooltip title"></div>')
+          .bind("shown", function() {
+            $(this).tooltip('hide')
+          })
+          .bind("hide", function() {
+            ok(true, "hide was called")
+            start()
+          })
+          .tooltip('show')
+      })
+
+      test("should fire hidden event", function () {
+        stop()
+        var tooltip = $('<div title="tooltip title"></div>')
+          .bind("shown", function() {
+            $(this).tooltip('hide')
+          })
+          .bind("hidden", function() {
+            ok(true, "hidden was called")
+            start()
+          })
+          .tooltip('show')
+      })
+
+      test("should not fire hidden event when default prevented", function () {
+        stop()
+        var tooltip = $('<div title="tooltip title"></div>')
+          .bind("shown", function() {
+            $(this).tooltip('hide')
+          })
+          .bind("hide", function(e) {
+            e.preventDefault()
+            ok(true, "hide was called")
+            start()
+          })
+          .bind("hidden", function() {
+            ok(false, "hidden was called")
+          })
+          .tooltip('show')
+      })
+
       test("should not show tooltip if leave event occurs before delay expires", function () {
         var tooltip = $('<a href="#" rel="tooltip" title="Another tooltip"></a>')
           .appendTo('#qunit-fixture')