|
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); |