bootstrap-scrollspy.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* =============================================================
  2. * bootstrap-scrollspy.js v2.3.2
  3. * http://getbootstrap.com/2.3.2/javascript.html#scrollspy
  4. * =============================================================
  5. * Copyright 2013 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. !function ($) {
  20. "use strict"; // jshint ;_;
  21. /* SCROLLSPY CLASS DEFINITION
  22. * ========================== */
  23. function ScrollSpy(element, options) {
  24. var process = $.proxy(this.process, this)
  25. , $element = $(element).is('body') ? $(window) : $(element)
  26. , href
  27. this.options = $.extend({}, $.fn.scrollspy.defaults, options)
  28. this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
  29. this.selector = (this.options.target
  30. || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
  31. || '') + ' .nav li > a'
  32. this.$body = $('body')
  33. this.refresh()
  34. this.process()
  35. }
  36. ScrollSpy.prototype = {
  37. constructor: ScrollSpy
  38. , refresh: function () {
  39. var self = this
  40. , $targets
  41. this.offsets = $([])
  42. this.targets = $([])
  43. $targets = this.$body
  44. .find(this.selector)
  45. .map(function () {
  46. var $el = $(this)
  47. , href = $el.data('target') || $el.attr('href')
  48. , $href = /^#\w/.test(href) && $(href)
  49. return ( $href
  50. && $href.length
  51. && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
  52. })
  53. .sort(function (a, b) { return a[0] - b[0] })
  54. .each(function () {
  55. self.offsets.push(this[0])
  56. self.targets.push(this[1])
  57. })
  58. }
  59. , process: function () {
  60. var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
  61. , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
  62. , maxScroll = scrollHeight - this.$scrollElement.height()
  63. , offsets = this.offsets
  64. , targets = this.targets
  65. , activeTarget = this.activeTarget
  66. , i
  67. if (scrollTop >= maxScroll) {
  68. return activeTarget != (i = targets.last()[0])
  69. && this.activate ( i )
  70. }
  71. for (i = offsets.length; i--;) {
  72. activeTarget != targets[i]
  73. && scrollTop >= offsets[i]
  74. && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
  75. && this.activate( targets[i] )
  76. }
  77. }
  78. , activate: function (target) {
  79. var active
  80. , selector
  81. this.activeTarget = target
  82. $(this.selector)
  83. .parent('.active')
  84. .removeClass('active')
  85. selector = this.selector
  86. + '[data-target="' + target + '"],'
  87. + this.selector + '[href="' + target + '"]'
  88. active = $(selector)
  89. .parent('li')
  90. .addClass('active')
  91. if (active.parent('.dropdown-menu').length) {
  92. active = active.closest('li.dropdown').addClass('active')
  93. }
  94. active.trigger('activate')
  95. }
  96. }
  97. /* SCROLLSPY PLUGIN DEFINITION
  98. * =========================== */
  99. var old = $.fn.scrollspy
  100. $.fn.scrollspy = function (option) {
  101. return this.each(function () {
  102. var $this = $(this)
  103. , data = $this.data('scrollspy')
  104. , options = typeof option == 'object' && option
  105. if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
  106. if (typeof option == 'string') data[option]()
  107. })
  108. }
  109. $.fn.scrollspy.Constructor = ScrollSpy
  110. $.fn.scrollspy.defaults = {
  111. offset: 10
  112. }
  113. /* SCROLLSPY NO CONFLICT
  114. * ===================== */
  115. $.fn.scrollspy.noConflict = function () {
  116. $.fn.scrollspy = old
  117. return this
  118. }
  119. /* SCROLLSPY DATA-API
  120. * ================== */
  121. $(window).on('load', function () {
  122. $('[data-spy="scroll"]').each(function () {
  123. var $spy = $(this)
  124. $spy.scrollspy($spy.data())
  125. })
  126. })
  127. }(window.jQuery);