diff --git a/Gruntfile.js b/Gruntfile.js index e945b9d4805b7e8eb3a72f3fc9229f643bea9061..09e71c4a2512cb8c63ae7b144a513ee4ce5b7444 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -140,6 +140,7 @@ module.exports = function (grunt) { src: [ 'docs/assets/js/vendor/holder.js', 'docs/assets/js/vendor/ZeroClipboard.min.js', + 'docs/assets/js/vendor/smartscroll.js', 'docs/assets/js/src/application.js' ], dest: 'docs/assets/js/docs.min.js' diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html index ef68da3ebab3e6d310c40160cfb6a55eb554e011..aeb1f6183b352a5debfc37c4af2511ff68157cb7 100644 --- a/docs/_includes/footer.html +++ b/docs/_includes/footer.html @@ -43,6 +43,7 @@ {% else %} <script src="../assets/js/vendor/holder.js"></script> <script src="../assets/js/vendor/ZeroClipboard.min.js"></script> +<script src="../assets/js/vendor/smartscroll.js"></script> <script src="../assets/js/src/application.js"></script> {% endif %} {% if page.slug == "customize" %} diff --git a/docs/assets/css/src/docs.css b/docs/assets/css/src/docs.css index 0e43d1f55ca661513f402a983510ccbf2f64a9c7..0490b5d92bf95db1087d1b7da0447c31d5b87473 100644 --- a/docs/assets/css/src/docs.css +++ b/docs/assets/css/src/docs.css @@ -1537,3 +1537,11 @@ h1[id] { -webkit-box-shadow: 0 0 8px rgba(82,168,236,.6); box-shadow: 0 0 8px rgba(82,168,236,.6); } + +/* Utility class to pause infinite animation loops (#14409) */ +.js-pause { + -webkit-animation-play-state: paused; + -ms-animation-play-state: paused; + -o-animation-play-state: paused; + animation-play-state: paused; +} diff --git a/docs/assets/js/src/application.js b/docs/assets/js/src/application.js index cfcfa2b503dccd1f7943c610c35ab276bfe72543..e4a2c868df7ccfcdc2968559165d881055d6753e 100644 --- a/docs/assets/js/src/application.js +++ b/docs/assets/js/src/application.js @@ -109,6 +109,47 @@ }, 3000) }) + // Pause infinite animations until they are within the viewport + // @see: https://github.com/twbs/bootstrap/issues/14409 + var isInViewport = function (elem) { + // Get the scroll position of the page. + var viewportTop = $(window).scrollTop() + var viewportBottom = viewportTop + $(window).height() + + // Get the position of the element on the page. + var elemTop = Math.round($(elem).offset().top) + var elemBottom = elemTop + $(elem).height() + + return ((elemTop < viewportBottom) && (elemBottom > viewportTop)) + } + + // Check if it's time to start the animation. + var checkAnimatedElems = function () { + return $infinitelyAnimatedElems.each(function () { + var $this = $(this) + + if (isInViewport(this)) { + // Start the animation + $this.removeClass('js-pause') + } else { + // Pause the animation + $this.addClass('js-pause') + } + }) + } + + // Define what elems have infinite animations + var $infinitelyAnimatedElems = $('.progress-bar.active') + + if ($infinitelyAnimatedElems.length > 0) { + // Check for infinitely animated elems in viewport on scroll (debounced) + $(window).smartscroll(function () { + checkAnimatedElems() + }) + // Check for infinitely animated elems in viewport on load + checkAnimatedElems() + } + // Config ZeroClipboard ZeroClipboard.config({ diff --git a/docs/assets/js/vendor/smartscroll.js b/docs/assets/js/vendor/smartscroll.js new file mode 100644 index 0000000000000000000000000000000000000000..f1fa39e41d069a7ed297128c716a14bd7bfc88ed --- /dev/null +++ b/docs/assets/js/vendor/smartscroll.js @@ -0,0 +1,38 @@ +/*! +* Debounced scroll event library for jQuery based on Paul Irish's smartresize +* http://paulirish.com/2009/throttled-smartresize-jquery-event-handler/ +* https://github.com/peschee/jquery-smartscroll +*/ + +(function($, sscr){ + 'use strict'; + + var debounce = function (func, threshold, execAsap) { + var timeout; + + return function debounced () { + var obj = this, + args = arguments + + function delayed () { + if (!execAsap) + func.apply(obj, args) + + timeout = null + } + + if (timeout) + clearTimeout(timeout) + else if (execAsap) + func.apply(obj, args) + + timeout = setTimeout(delayed, threshold || 100) + } + + } + + jQuery.fn[sscr] = function (fn) { + return fn ? this.bind('scroll', debounce(fn)) : this.trigger(sscr) + } + +})(jQuery, 'smartscroll');