1/* ======================================================================== 2* Bootstrap: scrollspy.js v3.3.2 3* http://getbootstrap.com/javascript/#scrollspy 4* ======================================================================== 5* Copyright 2011-2015 Twitter, Inc. 6* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 7* ======================================================================== */ 8 9/** 10 * Customized by iissnan & Ivan.Nginx 11 * 12 * - Add a `clear.bs.scrollspy` event. 13 * - Esacpe targets selector. 14 * - Refactored with eslint-config-theme-next style. 15 */ 16 17/* global NexT */ 18 19(function($) { 20 'use strict'; 21 22 // SCROLLSPY CLASS DEFINITION 23 // ========================== 24 function ScrollSpy(element, options) { 25 this.$body = $(document.body); 26 this.$scrollElement = $(element).is(document.body) ? $(window) : $(element); 27 this.options = $.extend({}, ScrollSpy.DEFAULTS, options); 28 this.selector = (this.options.target || '') + ' .nav li > a'; 29 this.offsets = []; 30 this.targets = []; 31 this.activeTarget = null; 32 this.scrollHeight = 0; 33 34 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)); 35 this.refresh(); 36 this.process(); 37 } 38 39 ScrollSpy.VERSION = '3.3.2'; 40 41 ScrollSpy.DEFAULTS = { 42 offset: 10 43 }; 44 45 ScrollSpy.prototype.getScrollHeight = function() { 46 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight); 47 }; 48 49 ScrollSpy.prototype.refresh = function() { 50 var that = this; 51 var offsetMethod = 'offset'; 52 var offsetBase = 0; 53 54 this.offsets = []; 55 this.targets = []; 56 this.scrollHeight = this.getScrollHeight(); 57 58 if (!$.isWindow(this.$scrollElement[0])) { 59 offsetMethod = 'position'; 60 offsetBase = this.$scrollElement.scrollTop(); 61 } 62 63 this.$body 64 .find(this.selector) 65 .map(function() { 66 var $el = $(this); 67 var href = $el.data('target') || $el.attr('href'); 68 var $href = /^#./.test(href) && $(NexT.utils.escapeSelector(href)); // Need to escape selector. 69 70 return ($href 71 && $href.length 72 && $href.is(':visible') 73 && [[$href[offsetMethod]().top + offsetBase, href]]) || null; 74 }) 75 .sort(function(a, b) { 76 return a[0] - b[0]; 77 }) 78 .each(function() { 79 that.offsets.push(this[0]); 80 that.targets.push(this[1]); 81 }); 82 83 84 }; 85 86 ScrollSpy.prototype.process = function() { 87 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset; 88 var scrollHeight = this.getScrollHeight(); 89 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height(); 90 var offsets = this.offsets; 91 var targets = this.targets; 92 var activeTarget = this.activeTarget; 93 var i; 94 95 if (this.scrollHeight !== scrollHeight) { 96 this.refresh(); 97 } 98 99 if (scrollTop >= maxScroll) { 100 return activeTarget !== (i = targets[targets.length - 1]) && this.activate(i); 101 } 102 103 if (activeTarget && scrollTop < offsets[0]) { 104 $(this.selector).trigger('clear.bs.scrollspy'); // Add a custom event. 105 this.activeTarget = null; 106 return this.clear(); 107 } 108 109 for (i = offsets.length; i--;) { 110 activeTarget !== targets[i] 111 && scrollTop >= offsets[i] 112 && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 113 && this.activate(targets[i]); 114 } 115 }; 116 117 ScrollSpy.prototype.activate = function(target) { 118 this.activeTarget = target; 119 120 this.clear(); 121 122 var selector = this.selector 123 + '[data-target="' + target + '"],' 124 + this.selector + '[href="' + target + '"]'; 125 126 var active = $(selector) 127 .parents('li') 128 .addClass('active'); 129 130 if (active.parent('.dropdown-menu').length) { 131 active = active 132 .closest('li.dropdown') 133 .addClass('active'); 134 } 135 136 active.trigger('activate.bs.scrollspy'); 137 }; 138 139 ScrollSpy.prototype.clear = function() { 140 $(this.selector) 141 .parentsUntil(this.options.target, '.active') 142 .removeClass('active'); 143 }; 144 145 // SCROLLSPY PLUGIN DEFINITION 146 // =========================== 147 function Plugin(option) { 148 return this.each(function() { 149 var $this = $(this); 150 var data = $this.data('bs.scrollspy'); 151 var options = typeof option === 'object' && option; 152 153 if (!data) $this.data('bs.scrollspy', data = new ScrollSpy(this, options)); 154 if (typeof option === 'string') data[option](); 155 }); 156 } 157 158 var old = $.fn.scrollspy; 159 160 $.fn.scrollspy = Plugin; 161 $.fn.scrollspy.Constructor = ScrollSpy; 162 163 // SCROLLSPY NO CONFLICT 164 // ===================== 165 $.fn.scrollspy.noConflict = function() { 166 $.fn.scrollspy = old; 167 return this; 168 }; 169 170 // SCROLLSPY DATA-API 171 // ================== 172 $(window).on('load.bs.scrollspy.data-api', function() { 173 $('[data-spy="scroll"]').each(function() { 174 var $spy = $(this); 175 Plugin.call($spy, $spy.data()); 176 }); 177 }); 178 179}(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.