js/bootstrap-scrollspy.js
author indvd00m (gotoindvdum[at]gmail[dot]com)
Fri, 04 Jul 2014 16:42:41 +0400
changeset 0 ba8ab09f730e
permissions -rw-r--r--
First home page
     1 /* =============================================================
     2  * bootstrap-scrollspy.js v2.3.1
     3  * http://twitter.github.com/bootstrap/javascript.html#scrollspy
     4  * =============================================================
     5  * Copyright 2012 Twitter, Inc.
     6  *
     7  * Licensed under the Apache License, Version 2.0 (the "License");
     8  * you may not use this file except in compliance with the License.
     9  * You may obtain a copy of the License at
    10  *
    11  * http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  * Unless required by applicable law or agreed to in writing, software
    14  * distributed under the License is distributed on an "AS IS" BASIS,
    15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  * See the License for the specific language governing permissions and
    17  * limitations under the License.
    18  * ============================================================== */
    19 
    20 
    21 !function ($) {
    22 
    23   "use strict"; // jshint ;_;
    24 
    25 
    26  /* SCROLLSPY CLASS DEFINITION
    27   * ========================== */
    28 
    29   function ScrollSpy(element, options) {
    30     var process = $.proxy(this.process, this)
    31       , $element = $(element).is('body') ? $(window) : $(element)
    32       , href
    33     this.options = $.extend({}, $.fn.scrollspy.defaults, options)
    34     this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
    35     this.selector = (this.options.target
    36       || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
    37       || '') + ' .nav li > a'
    38     this.$body = $('body')
    39     this.refresh()
    40     this.process()
    41   }
    42 
    43   ScrollSpy.prototype = {
    44 
    45       constructor: ScrollSpy
    46 
    47     , refresh: function () {
    48         var self = this
    49           , $targets
    50 
    51         this.offsets = $([])
    52         this.targets = $([])
    53 
    54         $targets = this.$body
    55           .find(this.selector)
    56           .map(function () {
    57             var $el = $(this)
    58               , href = $el.data('target') || $el.attr('href')
    59               , $href = /^#\w/.test(href) && $(href)
    60             return ( $href
    61               && $href.length
    62               && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
    63           })
    64           .sort(function (a, b) { return a[0] - b[0] })
    65           .each(function () {
    66             self.offsets.push(this[0])
    67             self.targets.push(this[1])
    68           })
    69       }
    70 
    71     , process: function () {
    72         var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
    73           , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
    74           , maxScroll = scrollHeight - this.$scrollElement.height()
    75           , offsets = this.offsets
    76           , targets = this.targets
    77           , activeTarget = this.activeTarget
    78           , i
    79 
    80         if (scrollTop >= maxScroll) {
    81           return activeTarget != (i = targets.last()[0])
    82             && this.activate ( i )
    83         }
    84 
    85         for (i = offsets.length; i--;) {
    86           activeTarget != targets[i]
    87             && scrollTop >= offsets[i]
    88             && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
    89             && this.activate( targets[i] )
    90         }
    91       }
    92 
    93     , activate: function (target) {
    94         var active
    95           , selector
    96 
    97         this.activeTarget = target
    98 
    99         $(this.selector)
   100           .parent('.active')
   101           .removeClass('active')
   102 
   103         selector = this.selector
   104           + '[data-target="' + target + '"],'
   105           + this.selector + '[href="' + target + '"]'
   106 
   107         active = $(selector)
   108           .parent('li')
   109           .addClass('active')
   110 
   111         if (active.parent('.dropdown-menu').length)  {
   112           active = active.closest('li.dropdown').addClass('active')
   113         }
   114 
   115         active.trigger('activate')
   116       }
   117 
   118   }
   119 
   120 
   121  /* SCROLLSPY PLUGIN DEFINITION
   122   * =========================== */
   123 
   124   var old = $.fn.scrollspy
   125 
   126   $.fn.scrollspy = function (option) {
   127     return this.each(function () {
   128       var $this = $(this)
   129         , data = $this.data('scrollspy')
   130         , options = typeof option == 'object' && option
   131       if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
   132       if (typeof option == 'string') data[option]()
   133     })
   134   }
   135 
   136   $.fn.scrollspy.Constructor = ScrollSpy
   137 
   138   $.fn.scrollspy.defaults = {
   139     offset: 10
   140   }
   141 
   142 
   143  /* SCROLLSPY NO CONFLICT
   144   * ===================== */
   145 
   146   $.fn.scrollspy.noConflict = function () {
   147     $.fn.scrollspy = old
   148     return this
   149   }
   150 
   151 
   152  /* SCROLLSPY DATA-API
   153   * ================== */
   154 
   155   $(window).on('load', function () {
   156     $('[data-spy="scroll"]').each(function () {
   157       var $spy = $(this)
   158       $spy.scrollspy($spy.data())
   159     })
   160   })
   161 
   162 }(window.jQuery);