PageSourceSearch

https://northword.github.io/js/src/scrollspy.js?v=6.5.0

js northword.github.io collected 2026-10-03 09:41:54 UTC 5,081 bytes, 179 lines download raw bytes

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.