diff --git a/docs/assets/bootstrap.zip b/docs/assets/bootstrap.zip
index 954f4d3e1668ebc1dbeaff18cf93151cdf66d279..8ad9a0695f35dbc9fc933318dd661d1ed85f5cac 100644
Binary files a/docs/assets/bootstrap.zip and b/docs/assets/bootstrap.zip differ
diff --git a/docs/assets/js/bootstrap-modal.js b/docs/assets/js/bootstrap-modal.js
index e92970627951f9ff811a763908af0e7ff5741c5f..3e0fb1481873dfcaf970edc5afc1d5774cb14b76 100644
--- a/docs/assets/js/bootstrap-modal.js
+++ b/docs/assets/js/bootstrap-modal.js
@@ -41,13 +41,15 @@
 
     , show: function () {
         var that = this
+          , e = $.Event('show')
 
-        if (this.isShown) return
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
 
         $('body').addClass('modal-open')
 
         this.isShown = true
-        this.$element.trigger('show')
 
         escape.call(this)
         backdrop.call(this, function () {
@@ -74,18 +76,21 @@
     , hide: function ( e ) {
         e && e.preventDefault()
 
-        if (!this.isShown) return
-
         var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
         this.isShown = false
 
         $('body').removeClass('modal-open')
 
         escape.call(this)
 
-        this.$element
-          .trigger('hide')
-          .removeClass('in')
+        this.$element.removeClass('in')
 
         $.support.transition && this.$element.hasClass('fade') ?
           hideWithTransition.call(this) :
diff --git a/js/bootstrap-modal.js b/js/bootstrap-modal.js
index e92970627951f9ff811a763908af0e7ff5741c5f..3e0fb1481873dfcaf970edc5afc1d5774cb14b76 100644
--- a/js/bootstrap-modal.js
+++ b/js/bootstrap-modal.js
@@ -41,13 +41,15 @@
 
     , show: function () {
         var that = this
+          , e = $.Event('show')
 
-        if (this.isShown) return
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
 
         $('body').addClass('modal-open')
 
         this.isShown = true
-        this.$element.trigger('show')
 
         escape.call(this)
         backdrop.call(this, function () {
@@ -74,18 +76,21 @@
     , hide: function ( e ) {
         e && e.preventDefault()
 
-        if (!this.isShown) return
-
         var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
         this.isShown = false
 
         $('body').removeClass('modal-open')
 
         escape.call(this)
 
-        this.$element
-          .trigger('hide')
-          .removeClass('in')
+        this.$element.removeClass('in')
 
         $.support.transition && this.$element.hasClass('fade') ?
           hideWithTransition.call(this) :
diff --git a/js/tests/unit/bootstrap-modal.js b/js/tests/unit/bootstrap-modal.js
index 22f5781ea6528c4b76891ea9fdea06be22723276..0851f64a72918b53d1f80effc63865b29c1103ec 100644
--- a/js/tests/unit/bootstrap-modal.js
+++ b/js/tests/unit/bootstrap-modal.js
@@ -29,6 +29,35 @@ $(function () {
           .modal("show")
       })
 
+      test("should fire show event", function () {
+        stop()
+        $.support.transition = false
+        $("<div id='modal-test'></div>")
+          .bind("show", function () {
+            ok(true, "show was called")
+          })
+          .bind("shown", function () {
+            $(this).remove()
+            start()
+          })
+          .modal("show")
+      })
+
+      test("should not fire shown when default prevented", function () {
+        stop()
+        $.support.transition = false
+        $("<div id='modal-test'></div>")
+          .bind("show", function (e) {
+            e.preventDefault()
+            ok(true, "show was called")
+            start()
+          })
+          .bind("shown", function () {
+            ok(false, "shown was called")
+          })
+          .modal("show")
+      })
+
       test("should hide modal when hide is called", function () {
         stop()
         $.support.transition = false