1 2+function ($) { 3 'use strict'; 4 5 function ScrollSpy(element, options) { 6 var process = $.proxy(this.process, this); 7 8 this.$body = $('body'); 9 this.$scrollElement = $(element).is('body') ? $(window) : $(element); 10 this.options = $.extend({}, ScrollSpy.DEFAULTS, options); 11 this.selector = (this.options.target || '') + ' li > a'; 12 this.offsets = []; 13 this.targets = []; 14 this.activeTarget = null; 15 this.scrollHeight = 0; 16 17 this.$scrollElement.on('scroll.bs.scrollspy', process); 18 this.refresh(); 19 this.process(); 20 } 21 22 ScrollSpy.VERSION = '3.3.2'; 23 24 ScrollSpy.DEFAULTS = { 25 offset: 10 26 }; 27 28 ScrollSpy.prototype.getScrollHeight = function () { 29 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight); 30 }; 31 32 ScrollSpy.prototype.refresh = function () { 33 var offsetMethod = 'offset'; 34 var offsetBase = 0; 35 36 if (!$.isWindow(this.$scrollElement[0])) { 37 offsetMethod = 'position'; 38 offsetBase = this.$scrollElement.scrollTop(); 39 }; 40 41 this.offsets = []; 42 this.targets = []; 43 this.scrollHeight = this.getScrollHeight(); 44 45 var self = this; 46 47 this.$body 48 .find(this.selector) 49 .map(function () { 50 var $el = $(this); 51 var href = $el.data('target') || $el.attr('href'); 52 var $href = /^#./.test(href) && $(href); 53 54 return ($href 55 && $href.length 56 && $href.is(':visible') 57 && [[$href[offsetMethod]().top + offsetBase, href]]) || null; 58 }) 59 .sort(function (a, b) { return a[0] - b[0]; }) 60 .each(function () { 61 self.offsets.push(this[0]); 62 self.targets.push(this[1]); 63 }); 64 }; 65 66 ScrollSpy.prototype.process = function () { 67 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset; 68 var scrollHeight = this.getScrollHeight(); 69 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height(); 70 var offsets = this.offsets; 71 var targets = this.targets; 72 var activeTarget = this.activeTarget; 73 var i; 74 75 if (this.scrollHeight != scrollHeight) { 76 this.refresh(); 77 }; 78 79 if (scrollTop >= maxScroll) { 80 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i); 81 }; 82 83 if (activeTarget && scrollTop < offsets[0]) { 84 this.activeTarget = null; 85 return this.clear(); 86 }; 87 88 for (i = offsets.length; i--;) { 89 activeTarget != targets[i] 90 && scrollTop >= offsets[i] 91 && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 92 && this.activate(targets[i]); 93 }; 94 }; 95 96 ScrollSpy.prototype.activate = function (target) { 97 this.activeTarget = target; 98 99 this.clear(); 100 var $current_href = window.location.href.split( '#' ), 101 $current_path = ( $current_href[0].charAt( $current_href[0].length - 1 ) == '/' ) ? $current_href[0] : $current_href[0] + '/'; 102 103 var selector = this.selector + 104 '[data-target="' + target + '"],' + 105 this.selector + '[href="' + target + '"],' + 106 this.selector + '[href="' + $current_path + target + '"]'; 107 108 var active = $(selector) 109 .parents('li') 110 .addClass('current-menu-item'); 111 112 if (active.parent('.sub-menu').length) { 113 active = active 114 .closest('li.fusion-dropdown-menu') 115 .addClass('current-menu-item'); 116 }; 117 118 active.trigger('activate.bs.scrollspy'); 119 }; 120 121 ScrollSpy.prototype.clear = function () { 122 $(this.selector) 123 .parentsUntil(this.options.target, '.current-menu-item') 124 .removeClass('current-menu-item'); 125 126 $(this.selector).parentsUntil(this.options.target, '.current-menu-parent').removeClass( 'current-menu-parent' ); 127 128 }; 129 130 function Plugin(option) { 131 return this.each(function () { 132 var $this = $(this); 133 var data = $this.data('bs.scrollspy'); 134 var options = typeof option == 'object' && option; 135 136 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))); 137 if (typeof option == 'string') data[option](); 138 }); 139 }; 140 141 var old = $.fn.scrollspy; 142 143 $.fn.scrollspy = Plugin; 144 $.fn.scrollspy.Constructor = ScrollSpy; 145 146 $.fn.scrollspy.noConflict = function () { 147 $.fn.scrollspy = old; 148 return this; 149 }; 150 151}(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.