diff --git a/docs/_includes/callout-danger-async-methods.md b/docs/_includes/callout-danger-async-methods.md
new file mode 100644
index 0000000000000000000000000000000000000000..f7a76aa4d3ea2cffdf73972df357e0b00d07335b
--- /dev/null
+++ b/docs/_includes/callout-danger-async-methods.md
@@ -0,0 +1,7 @@
+{% callout danger %}
+#### Asynchronous methods and transitions
+
+All API methods are **asynchronous** and start a **transition**. They returns to the caller as soon as the transition is started but **before it ends**. In addition, a method call on a **transitioning component will be ignored**.
+
+[See our Javascript documentation for more informations.]({{ site.baseurl }}/getting-started/javascript/#content)
+{% endcallout %}
diff --git a/docs/components/carousel.md b/docs/components/carousel.md
index 5649dfac9a65aca1c2efa5f287d99930c09d2def..405aee18cbc5e53c6663d5dde500478c125cda58 100644
--- a/docs/components/carousel.md
+++ b/docs/components/carousel.md
@@ -229,6 +229,9 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
 
 ### Methods
 
+{% capture callout-include %}{% include callout-danger-async-methods.md %}{% endcapture %}
+{{ callout-include | markdownify }}
+
 #### `.carousel(options)`
 
 Initializes the carousel with an optional options `object` and starts cycling through items.
@@ -249,15 +252,15 @@ Stops the carousel from cycling through items.
 
 #### `.carousel(number)`
 
-Cycles the carousel to a particular frame (0 based, similar to an array).
+Cycles the carousel to a particular frame (0 based, similar to an array). **Returns to the caller before the target item has been shown** (i.e. before the `slid.bs.carousel` event occurs).
 
 #### `.carousel('prev')`
 
-Cycles to the previous item.
+Cycles to the previous item. **Returns to the caller before the previous item has been shown** (i.e. before the `slid.bs.carousel` event occurs).
 
 #### `.carousel('next')`
 
-Cycles to the next item.
+Cycles to the next item. **Returns to the caller before the next item has been shown** (i.e. before the `slid.bs.carousel` event occurs).
 
 ### Events
 
diff --git a/docs/components/collapse.md b/docs/components/collapse.md
index 370cb760efaa00657aa3c11259fba9c5264d0b9e..0a49db562f54bb2e54e1ff2da4ba1be7dc44d5c2 100644
--- a/docs/components/collapse.md
+++ b/docs/components/collapse.md
@@ -178,6 +178,9 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
 
 ### Methods
 
+{% capture callout-include %}{% include callout-danger-async-methods.md %}{% endcapture %}
+{{ callout-include | markdownify }}
+
 #### `.collapse(options)`
 
 Activates your content as a collapsible element. Accepts an optional options `object`.
@@ -190,15 +193,15 @@ $('#myCollapsible').collapse({
 
 #### `.collapse('toggle')`
 
-Toggles a collapsible element to shown or hidden.
+Toggles a collapsible element to shown or hidden. **Returns to the caller before the collapsible element has actually been shown or hidden (i.e. before the `shown.bs.collapse` or `hidden.bs.collapse` event occurs).
 
 #### `.collapse('show')`
 
-Shows a collapsible element.
+Shows a collapsible element. **Returns to the caller before the collapsible element has actually been shown** (i.e. before the `shown.bs.collapse` event occurs).
 
 #### `.collapse('hide')`
 
-Hides a collapsible element.
+Hides a collapsible element. **Returns to the caller before the collapsible element has actually been hidden** (i.e. before the `hidden.bs.collapse` event occurs).
 
 ### Events
 
diff --git a/docs/components/modal.md b/docs/components/modal.md
index a4e28bcec5de0b796db55ff3bbdc844a51bac9f5..19254b8808d15404b18f02b96c2a79bc748e8819 100644
--- a/docs/components/modal.md
+++ b/docs/components/modal.md
@@ -547,6 +547,9 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
 
 ### Methods
 
+{% capture callout-include %}{% include callout-danger-async-methods.md %}{% endcapture %}
+{{ callout-include | markdownify }}
+
 #### `.modal(options)`
 
 Activates your content as a modal. Accepts an optional options `object`.
diff --git a/docs/components/navs.md b/docs/components/navs.md
index 047eb22054aa7b88a33af606fb4bb1fc61d4b81e..e47a5a9e6ccc87afeae2630238aae7df652d689b 100644
--- a/docs/components/navs.md
+++ b/docs/components/navs.md
@@ -404,6 +404,9 @@ To make tabs fade in, add `.fade` to each `.tab-pane`. The first tab pane must a
 
 ### Methods
 
+{% capture callout-include %}{% include callout-danger-async-methods.md %}{% endcapture %}
+{{ callout-include | markdownify }}
+
 #### $().tab
 
 Activates a tab element and content container. Tab should have either a `data-target` or an `href` targeting a container node in the DOM.
diff --git a/docs/components/popovers.md b/docs/components/popovers.md
index ec5b4970d378629aa065d610f27750e21f92f53a..5f26e4bbd36a0c40f8493199b2de0a4d4a23af03 100644
--- a/docs/components/popovers.md
+++ b/docs/components/popovers.md
@@ -277,6 +277,9 @@ Options for individual popovers can alternatively be specified through the use o
 
 ### Methods
 
+{% capture callout-include %}{% include callout-danger-async-methods.md %}{% endcapture %}
+{{ callout-include | markdownify }}
+
 #### `$().popover(options)`
 
 Initializes popovers for an element collection.
diff --git a/docs/components/tooltips.md b/docs/components/tooltips.md
index eaab24da51df77cff924ac6fbc6689cd32a3887e..a8b251c09a2abd5da3c21e87971343f6cbb11ba8 100644
--- a/docs/components/tooltips.md
+++ b/docs/components/tooltips.md
@@ -254,6 +254,9 @@ Options for individual tooltips can alternatively be specified through the use o
 
 ### Methods
 
+{% capture callout-include %}{% include callout-danger-async-methods.md %}{% endcapture %}
+{{ callout-include | markdownify }}
+
 #### `$().tooltip(options)`
 
 Attaches a tooltip handler to an element collection.
diff --git a/docs/getting-started/javascript.md b/docs/getting-started/javascript.md
index b6a38fb7a2c50ef258630515ca3ec2a704754148..d65fba09850f0894f61659afa65252ec5b82ac0c 100644
--- a/docs/getting-started/javascript.md
+++ b/docs/getting-started/javascript.md
@@ -36,6 +36,18 @@ Alternatively, to target a specific plugin, just include the plugin's name as a
 $(document).off('.alert.data-api')
 {% endhighlight %}
 
+## Events
+
+Bootstrap provides custom events for most plugins' unique actions. Generally, these come in an infinitive and past participle form - where the infinitive (ex. `show`) is triggered at the start of an event, and its past participle form (ex. `shown`) is triggered on the completion of an action.
+
+All infinitive events provide [`preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) functionality. This provides the ability to stop the execution of an action before it starts.
+
+{% highlight js %}
+$('#myModal').on('show.bs.modal', function (e) {
+  if (!data) return e.preventDefault() // stops modal from being shown
+})
+{% endhighlight %}
+
 ## Programmatic API
 
 We also believe you should be able to use all Bootstrap plugins purely through the JavaScript API. All public APIs are single, chainable methods, and return the collection acted upon.
@@ -54,32 +66,41 @@ $('#myModal').modal('show')                // initializes and invokes show immed
 
 Each plugin also exposes its raw constructor on a `Constructor` property: `$.fn.popover.Constructor`. If you'd like to get a particular plugin instance, retrieve it directly from an element: `$('[rel="popover"]').data('popover')`.
 
-### Default settings
-You can change the default settings for a plugin by modifying the plugin's `Constructor.DEFAULTS` object:
+### Asynchronous functions and transitions
+
+All programmatic API methods are **asynchronous** and returns to the caller once the transition is started but **before it ends**.
 
+In order to execute an action once the transition is complete, you can listen to the corresponding event.
 {% highlight js %}
-$.fn.modal.Constructor.DEFAULTS.keyboard = false // changes default for the modal plugin's `keyboard` option to false
+$('#myCollapse').on('shown.bs.collapse', function (e) {
+  // Action to execute once the collapsible area is expanded
+})
 {% endhighlight %}
 
-## No conflict
+In addition a method call on a **transitioning component will be ignored**.
+{% highlight js %}
+$('#myCarousel').on('slid.bs.carousel', function (e) {
+  $('#myCarousel').carousel('2') // Will slide to the slide 2 as soon as the transition to slide 1 is finished
+})
 
-Sometimes it is necessary to use Bootstrap plugins with other UI frameworks. In these circumstances, namespace collisions can occasionally occur. If this happens, you may call `.noConflict` on the plugin you wish to revert the value of.
+$('#myCarousel').carousel('1') // Will start sliding to the slide 1 and returns to the caller
+$('#myCarousel').carousel('2') // !! Will be ignored, as the transition to the slide 1 is not finished !!
+{% endhighlight %}
+
+### Default settings
+You can change the default settings for a plugin by modifying the plugin's `Constructor.Default` object:
 
 {% highlight js %}
-var bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value
-$.fn.bootstrapBtn = bootstrapButton            // give $().bootstrapBtn the Bootstrap functionality
+$.fn.modal.Constructor.Default.keyboard = false // changes default for the modal plugin's `keyboard` option to false
 {% endhighlight %}
 
-## Events
-
-Bootstrap provides custom events for most plugins' unique actions. Generally, these come in an infinitive and past participle form - where the infinitive (ex. `show`) is triggered at the start of an event, and its past participle form (ex. `shown`) is triggered on the completion of an action.
+## No conflict
 
-All infinitive events provide [`preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) functionality. This provides the ability to stop the execution of an action before it starts.
+Sometimes it is necessary to use Bootstrap plugins with other UI frameworks. In these circumstances, namespace collisions can occasionally occur. If this happens, you may call `.noConflict` on the plugin you wish to revert the value of.
 
 {% highlight js %}
-$('#myModal').on('show.bs.modal', function (e) {
-  if (!data) return e.preventDefault() // stops modal from being shown
-})
+var bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value
+$.fn.bootstrapBtn = bootstrapButton            // give $().bootstrapBtn the Bootstrap functionality
 {% endhighlight %}
 
 ## Version numbers
@@ -100,8 +121,8 @@ Bootstrap's plugins don't fall back particularly gracefully when JavaScript is d
 **Bootstrap does not officially support third-party JavaScript libraries** like Prototype or jQuery UI. Despite `.noConflict` and namespaced events, there may be compatibility problems that you need to fix on your own.
 {% endcallout %}
 
-## Transitions
+## Util
 
-For simple transition effects, include `transition.js` once alongside the other JS files. If you're using the compiled (or minified) `bootstrap.js`, there is no need to include this—it's already there.
+All Bootstrap Javascript depend on `util.js` and it has to be included alongside the other JS files. If you're using the compiled (or minified) `bootstrap.js`, there is no need to include this—it's already there.
 
-Transition.js is a basic helper for `transitionEnd` events as well as a CSS transition emulator. It's used by the other plugins to check for CSS transition support and to catch hanging transitions.
+`util.js` includes utility functions and a basic helper for `transitionEnd` events as well as a CSS transition emulator. It's used by the other plugins to check for CSS transition support and to catch hanging transitions.
diff --git a/js/src/carousel.js b/js/src/carousel.js
index 1aca817f1214d60645244e18abee275c0bdea8d2..7c2da45ad79ef0a663ca9ed352814cd861837c96 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -120,10 +120,9 @@ const Carousel = (($) => {
     // public
 
     next() {
-      if (this._isSliding) {
-        throw new Error('Carousel is sliding')
+      if (!this._isSliding) {
+        this._slide(Direction.NEXT)
       }
-      this._slide(Direction.NEXT)
     }
 
     nextWhenVisible() {
@@ -134,10 +133,9 @@ const Carousel = (($) => {
     }
 
     prev() {
-      if (this._isSliding) {
-        throw new Error('Carousel is sliding')
+      if (!this._isSliding) {
+        this._slide(Direction.PREV)
       }
-      this._slide(Direction.PREV)
     }
 
     pause(event) {
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 6f09fcadd8d1dc7e742c79187a83d6d4e61c027a..dc2e2a67d7d83c4f417ab8e343e60518bd37bd31 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -120,11 +120,8 @@ const Collapse = (($) => {
     }
 
     show() {
-      if (this._isTransitioning) {
-        throw new Error('Collapse is transitioning')
-      }
-
-      if ($(this._element).hasClass(ClassName.SHOW)) {
+      if (this._isTransitioning ||
+        $(this._element).hasClass(ClassName.SHOW)) {
         return
       }
 
@@ -204,11 +201,8 @@ const Collapse = (($) => {
     }
 
     hide() {
-      if (this._isTransitioning) {
-        throw new Error('Collapse is transitioning')
-      }
-
-      if (!$(this._element).hasClass(ClassName.SHOW)) {
+      if (this._isTransitioning ||
+        !$(this._element).hasClass(ClassName.SHOW)) {
         return
       }
 
diff --git a/js/src/modal.js b/js/src/modal.js
index 7f010b8e09b2a7a9648a0f5ce508f109272764a0..5e9941444998fafdb29e837beea10260d38457d0 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -87,7 +87,6 @@ const Modal = (($) => {
       this._isShown             = false
       this._isBodyOverflowing   = false
       this._ignoreBackdropClick = false
-      this._isTransitioning     = false
       this._originalBodyPadding = 0
       this._scrollbarWidth      = 0
     }
@@ -112,13 +111,13 @@ const Modal = (($) => {
 
     show(relatedTarget) {
       if (this._isTransitioning) {
-        throw new Error('Modal is transitioning')
+        return
       }
 
-      if (Util.supportsTransitionEnd() &&
-        $(this._element).hasClass(ClassName.FADE)) {
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
         this._isTransitioning = true
       }
+
       const showEvent = $.Event(Event.SHOW, {
         relatedTarget
       })
@@ -161,17 +160,18 @@ const Modal = (($) => {
         event.preventDefault()
       }
 
-      if (this._isTransitioning) {
-        throw new Error('Modal is transitioning')
+      if (this._isTransitioning || !this._isShown) {
+        return
       }
 
-      const transition = Util.supportsTransitionEnd() &&
-        $(this._element).hasClass(ClassName.FADE)
+      const transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)
+
       if (transition) {
         this._isTransitioning = true
       }
 
       const hideEvent = $.Event(Event.HIDE)
+
       $(this._element).trigger(hideEvent)
 
       if (!this._isShown || hideEvent.isDefaultPrevented()) {
@@ -191,6 +191,7 @@ const Modal = (($) => {
       $(this._dialog).off(Event.MOUSEDOWN_DISMISS)
 
       if (transition) {
+
         $(this._element)
           .one(Util.TRANSITION_END, (event) => this._hideModal(event))
           .emulateTransitionEnd(TRANSITION_DURATION)
@@ -307,7 +308,7 @@ const Modal = (($) => {
 
     _hideModal() {
       this._element.style.display = 'none'
-      this._element.setAttribute('aria-hidden', 'true')
+      this._element.setAttribute('aria-hidden', true)
       this._isTransitioning = false
       this._showBackdrop(() => {
         $(document.body).removeClass(ClassName.OPEN)
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index fe913e66086158e7926b38b10a43bcd8fba3ad0b..5fd4987b90d90df9f2f208a613ddc3e0faaf41c7 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -124,12 +124,11 @@ const Tooltip = (($) => {
     constructor(element, config) {
 
       // private
-      this._isEnabled        = true
-      this._timeout          = 0
-      this._hoverState       = ''
-      this._activeTrigger    = {}
-      this._isTransitioning  = false
-      this._tether           = null
+      this._isEnabled     = true
+      this._timeout       = 0
+      this._hoverState    = ''
+      this._activeTrigger = {}
+      this._tether        = null
 
       // protected
       this.element = element
@@ -250,9 +249,6 @@ const Tooltip = (($) => {
 
       const showEvent = $.Event(this.constructor.Event.SHOW)
       if (this.isWithContent() && this._isEnabled) {
-        if (this._isTransitioning) {
-          throw new Error('Tooltip is transitioning')
-        }
         $(this.element).trigger(showEvent)
 
         const isInTheDom = $.contains(
@@ -284,9 +280,11 @@ const Tooltip = (($) => {
 
         const container = this.config.container === false ? document.body : $(this.config.container)
 
-        $(tip)
-          .data(this.constructor.DATA_KEY, this)
-          .appendTo(container)
+        $(tip).data(this.constructor.DATA_KEY, this)
+
+        if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {
+          $(tip).appendTo(container)
+        }
 
         $(this.element).trigger(this.constructor.Event.INSERTED)
 
@@ -308,8 +306,7 @@ const Tooltip = (($) => {
 
         const complete = () => {
           const prevHoverState = this._hoverState
-          this._hoverState   = null
-          this._isTransitioning = false
+          this._hoverState     = null
 
           $(this.element).trigger(this.constructor.Event.SHOWN)
 
@@ -319,7 +316,6 @@ const Tooltip = (($) => {
         }
 
         if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
-          this._isTransitioning = true
           $(this.tip)
             .one(Util.TRANSITION_END, complete)
             .emulateTransitionEnd(Tooltip._TRANSITION_DURATION)
@@ -333,9 +329,6 @@ const Tooltip = (($) => {
     hide(callback) {
       const tip       = this.getTipElement()
       const hideEvent = $.Event(this.constructor.Event.HIDE)
-      if (this._isTransitioning) {
-        throw new Error('Tooltip is transitioning')
-      }
       const complete  = () => {
         if (this._hoverState !== HoverState.SHOW && tip.parentNode) {
           tip.parentNode.removeChild(tip)
@@ -344,7 +337,6 @@ const Tooltip = (($) => {
         this._cleanTipClass()
         this.element.removeAttribute('aria-describedby')
         $(this.element).trigger(this.constructor.Event.HIDDEN)
-        this._isTransitioning = false
         this.cleanupTether()
 
         if (callback) {
@@ -366,7 +358,7 @@ const Tooltip = (($) => {
 
       if (Util.supportsTransitionEnd() &&
           $(this.tip).hasClass(ClassName.FADE)) {
-        this._isTransitioning = true
+
         $(tip)
           .one(Util.TRANSITION_END, complete)
           .emulateTransitionEnd(TRANSITION_DURATION)
diff --git a/js/tests/visual/carousel.html b/js/tests/visual/carousel.html
index b02d28a05392ea3b89056ad6bd54e9e810b376e9..ad249d874dc27663c6596ebd2471e0c592704813 100644
--- a/js/tests/visual/carousel.html
+++ b/js/tests/visual/carousel.html
@@ -45,31 +45,11 @@
     <script src="../../dist/carousel.js"></script>
 
     <script>
-      // Should throw an error because carousel is in transition
-      function testCarouselTransitionError() {
-        var err = false
-        var $carousel = $('#carousel-example-generic')
-        $carousel.on('slid.bs.carousel', function () {
-          $carousel.off('slid.bs.carousel')
-          if (!err) {
-            alert('No error thrown for : testCarouselTransitionError')
-          }
-        })
-        try {
-          $carousel.carousel('next').carousel('prev')
-        }
-        catch (e) {
-          err = true
-          console.error(e.message)
-        }
-      }
-
-      $(function () {
+      $(function() {
         // Test to show that the carousel doesn't slide when the current tab isn't visible
-        $('#carousel-example-generic').on('slid.bs.carousel', function (event) {
+        $('#carousel-example-generic').on('slid.bs.carousel', function(event) {
           console.log('slid at ', event.timeStamp)
         })
-        testCarouselTransitionError()
       })
     </script>
   </body>
diff --git a/js/tests/visual/collapse.html b/js/tests/visual/collapse.html
index 3eb585b7ba1dfc04a7dc2557c398b2908f69470f..fe45c1804224d0c310be5c4d0baae206bb0fbaf2 100644
--- a/js/tests/visual/collapse.html
+++ b/js/tests/visual/collapse.html
@@ -60,30 +60,5 @@
     <script src="../../../docs/assets/js/vendor/jquery-slim.min.js"></script>
     <script src="../../dist/util.js"></script>
     <script src="../../dist/collapse.js"></script>
-    <script>
-      // JavaScript Test
-      $(function () {
-        testCollapseTransitionError()
-      });
-
-      // Should throw an error because carousel is in transition
-      function testCollapseTransitionError() {
-        var err = false
-        $('#collapseOne').on('hidden.bs.collapse', function (e) {
-          $(this).off('hidden.bs.collapse')
-          if (!err) {
-            alert('No error thrown for : testCollapseTransitionError')
-          }
-        })
-
-        try {
-          $('#collapseOne').collapse('hide').collapse('show')
-        }
-        catch (e) {
-          err = true
-          console.error(e.message)
-        }
-      }
-    </script>
   </body>
 </html>
diff --git a/js/tests/visual/modal.html b/js/tests/visual/modal.html
index d971a45c70e175caffd4bc4ebb52746fc9928e4b..e999514f7b9604338d409fd9101d7dd16d473b00 100644
--- a/js/tests/visual/modal.html
+++ b/js/tests/visual/modal.html
@@ -187,26 +187,6 @@
         }
       }
 
-      // Should throw an error because modal is in transition
-      function testModalTransitionError() {
-        var err = false
-        // Close #myModal
-        $('#myModal').on('shown.bs.modal', function () {
-          $('#myModal').modal('hide').off('shown.bs.modal')
-          if (!err) {
-            alert('No error thrown for : testModalTransitionError')
-          }
-        })
-
-        try {
-          $('#myModal').modal('show').modal('hide')
-        }
-        catch (e) {
-          err = true
-          console.error(e.message)
-        }
-      }
-
       $(function () {
         $('[data-toggle="popover"]').popover()
         $('[data-toggle="tooltip"]').tooltip()
@@ -219,7 +199,6 @@
           $('#firefoxModal').on('focus', reportFirefoxTestResult.bind(false))
           $('#ff-bug-input').on('focus', reportFirefoxTestResult.bind(true))
         })
-        testModalTransitionError()
       })
     </script>
   </body>
diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html
index ada6d8b7929ee17ac5b7f162e93951c63c4627cd..f447a533b65787ab401e832e6f8d4df9d9697338 100644
--- a/js/tests/visual/tooltip.html
+++ b/js/tests/visual/tooltip.html
@@ -41,26 +41,7 @@
     <script>
       $(function () {
         $('[data-toggle="tooltip"]').tooltip()
-        testTooltipTransitionError()
       })
-
-      // Should throw an error because tooltip is in transition
-      function testTooltipTransitionError() {
-        var err = false
-        $('#btnOne').on('shown.bs.tooltip', function () {
-          $('#btnOne').tooltip('hide').off('shown.bs.tooltip')
-          if (!err) {
-            alert('No error thrown for : testTooltipTransitionError')
-          }
-        })
-        try {
-          $('#btnOne').tooltip('show').tooltip('hide')
-        }
-        catch (e) {
-          err = true
-          console.error(e.message)
-        }
-      }
     </script>
   </body>
 </html>