PageSourceSearch

https://sion.ed.cr/assets/plugins/smooth-scroll/jquery.smooth-scroll.js

js sion.ed.cr collected 2026-10-03 02:42:15 UTC 8,925 bytes, 299 lines download raw bytes

vendor: 4,965 bytes, lines 1-159
1(function($) {
2  var version = '2.0.1';
3  var optionOverrides = {};
4  var defaults = {
5    exclude: [],
6    excludeWithin: [],
7    offset: 0,
8
9    // one of 'top' or 'left'
10    direction: 'top',
11
12    // if set, bind click events through delegation
13    //  supported since jQuery 1.4.2
14    delegateSelector: null,
15
16    // jQuery set of elements you wish to scroll (for $.smoothScroll).
17    //  if null (default), $('html, body').firstScrollable() is used.
18    scrollElement: null,
19
20    // only use if you want to override default behavior
21    scrollTarget: null,
22
23    // fn(opts) function to be called before scrolling occurs.
24    // `this` is the element(s) being scrolled
25    beforeScroll: function() {},
26
27    // fn(opts) function to be called after scrolling occurs.
28    // `this` is the triggering element
29    afterScroll: function() {},
30
31    // easing name. jQuery comes with "swing" and "linear." For others, you'll need an easing plugin
32    // from jQuery UI or elsewhere
33    easing: 'swing',
34
35    // speed can be a number or 'auto'
36    // if 'auto', the speed will be calculated based on the formula:
37    // (current scroll position - target scroll position) / autoCoeffic
38    speed: 400,
39
40    // coefficient for "auto" speed
41    autoCoefficient: 2,
42
43    // $.fn.smoothScroll only: whether to prevent the default click action
44    preventDefault: true
45  };
46
47  var getScrollable = function(opts) {
48    var scrollable = [];
49    var scrolled = false;
50    var dir = opts.dir && opts.dir === 'left' ? 'scrollLeft' : 'scrollTop';
51
52    this.each(function() {
53      var el = $(this);
54
55      if (this === document || this === window) {
56        return;
57      }
58
59      if (document.scrollingElement && (this === document.documentElement || this === document.body)) {
60        scrollable.push(document.scrollingElement);
61
62        return false;
63      }
64
65      if (el[dir]() > 0) {
66        scrollable.push(this);
67      } else {
68        // if scroll(Top|Left) === 0, nudge the element 1px and see if it moves
69        el[dir](1);
70        scrolled = el[dir]() > 0;
71
72        if (scrolled) {
73          scrollable.push(this);
74        }
75        // then put it back, of course
76        el[dir](0);
77      }
78    });
79
80    if (!scrollable.length) {
81      this.each(function() {
82        // If no scrollable elements and <html> has scroll-behavior:smooth because
83        // "When this property is specified on the root element, it applies to the viewport instead."
84        // and "The scroll-behavior property of the … body element is *not* propagated to the viewport."
85        // → https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior
86        if (this === document.documentElement && $(this).css('scrollBehavior') === 'smooth') {
87          scrollable = [this];
88        }
89
90        // If still no scrollable elements, fall back to <body>,
91        // if it's in the jQuery collection
92        // (doing this because Safari sets scrollTop async,
93        // so can't set it to 1 and immediately get the value.)
94        if (!scrollable.length && this.nodeName === 'BODY') {
95          scrollable = [this];
96        }
97      });
98    }
99
100    // Use the first scrollable element if we're calling firstScrollable()
101    if (opts.el === 'first' && scrollable.length > 1) {
102      scrollable = [scrollable[0]];
103    }
104
105    return scrollable;
106  };
107
108  $.fn.extend({
109    scrollable: function(dir) {
110      var scrl = getScrollable.call(this, {dir: dir});
111
112      return this.pushStack(scrl);
113    },
114    firstScrollable: function(dir) {
115      var scrl = getScrollable.call(this, {el: 'first', dir: dir});
116
117      return this.pushStack(scrl);
118    },
119
120    smoothScroll: function(options, extra) {
121      options = options || {};
122
123      if (options === 'options') {
124        if (!extra) {
125          return this.first().data('ssOpts');
126        }
127
128        return this.each(function() {
129          var $this = $(this);
130          var opts = $.extend($this.data('ssOpts') || {}, extra);
131
132          $(this).data('ssOpts', opts);
133        });
134      }
135
136      var opts = $.extend({}, $.fn.smoothScroll.defaults, options);
137
138      var clickHandler = function(event) {
139        var escapeSelector = function(str) {
140          return str.replace(/(:|\.|\/)/g, '\\$1');
141        };
142
143        var link = this;
144        var $link = $(this);
145        var thisOpts = $.extend({}, opts, $link.data('ssOpts') || {});
146        var exclude = opts.exclude;
147        var excludeWithin = thisOpts.excludeWithin;
148        var elCounter = 0;
149        var ewlCounter = 0;
150        var include = true;
151        var clickOpts = {};
152        var locationPath = $.smoothScroll.filterPath(location.pathname);
153        var linkPath = $.smoothScroll.filterPath(link.pathname);
154        var hostMatch = location.hostname === link.hostname || !link.hostname;
155        var pathMatch = thisOpts.scrollTarget || (linkPath === locationPath);
156        var thisHash = escapeSelector(link.hash);
157
158        if (thisHash && !$(thisHash).length) {
159          include = false;
160        }
161
162        if (!thisOpts.scrollTarget && (!hostMatch || !pathMatch || !thisHash)) {
163          include = false;
164        } else {
165          while (include && elCounter < exclude.length) {
166            if ($link.is(escapeSelector(exclude[elCounter++]))) {
167              include = false;
168            }
169          }
170
171          while (include && ewlCounter < excludeWithin.length) {
172            if ($link.closest(excludeWithin[ewlCounter++]).length) {
173              include = false;
174            }
175          }
176        }
177
178        if (include) {
179          if (thisOpts.preventDefault) {
180            event.preventDefault();
181          }
182
183          $.extend(clickOpts, thisOpts, {
184            scrollTarget: thisOpts.scrollTarget || thisHash,
185            link: link
186          });
187
188          $.smoothScroll(clickOpts);
189        }
190      };
191
192      if (options.delegateSelector !== null) {
193        this
194        .off('click.smoothscroll', options.delegateSelector)
195        .on('click.smoothscroll', options.delegateSelector, clickHandler);
196      } else {
197        this
198        .off('click.smoothscroll')
199        .on('click.smoothscroll', clickHandler);
200      }
201
202      return this;
203    }
204  });
205
206  $.smoothScroll = function(options, px) {
207    if (options === 'options' && typeof px === 'object') {
208      return $.extend(optionOverrides, px);
209    }
210    var opts, $scroller, scrollTargetOffset, speed, delta;
211    var scrollerOffset = 0;
212    var offPos = 'offset';
213    var scrollDir = 'scrollTop';
214    var aniProps = {};
215    var aniOpts = {};
216
217    if (typeof options === 'number') {
218      opts = $.extend({link: null}, $.fn.smoothScroll.defaults, optionOverrides);
219      scrollTargetOffset = options;
220    } else {
221      opts = $.extend({link: null}, $.fn.smoothScroll.defaults, options || {}, optionOverrides);
222
223      if (opts.scrollElement) {
224        offPos = 'position';
225
226        if (opts.scrollElement.css('position') === 'static') {
227          opts.scrollElement.css('position', 'relative');
228        }
229      }
230    }
231
232    scrollDir = opts.direction === 'left' ? 'scrollLeft' : scrollDir;
233
234    if (opts.scrollElement) {
235      $scroller = opts.scrollElement;
236
237      if (!(/^(?:HTML|BODY)$/).test($scroller[0].nodeName)) {
238        scrollerOffset = $scroller[scrollDir]();
239      }
240    } else {
241      $scroller = $('html, body').firstScrollable(opts.direction);
242    }
243
244    // beforeScroll callback function must fire before calculating offset
245    opts.beforeScroll.call($scroller, opts);
246
247    scrollTargetOffset = (typeof options === 'number') ? options :
248                          px ||
249                          ($(opts.scrollTarget)[offPos]() &&
250                          $(opts.scrollTarget)[offPos]()[opts.direction]) ||
251                          0;
252
253    aniProps[scrollDir] = scrollTargetOffset + scrollerOffset + opts.offset;
254    speed = opts.speed;
255
256    // automatically calculate the speed of the scroll based on distance / coefficient
257    if (speed === 'auto') {
258
259      // $scroller[scrollDir]() is position before scroll, aniProps[scrollDir] is position after
260      // When delta is greater, speed will be greater.
261      delta = Math.abs(aniProps[scrollDir] - $scroller[scrollDir]());
262
263      // Divide the delta by the coefficient
264      speed = delta / opts.autoCoefficient;
265    }
266
267    aniOpts = {
268      duration: speed,
269      easing: opts.easing,
270      complete: function() {
271        opts.afterScroll.call(opts.link, opts);
272      }
273    };
274
275    if (opts.step) {
276      aniOpts.step = opts.step;
277    }
278
279    if ($scroller.length) {
280      $scroller.stop().animate(aniProps, aniOpts);
281    } else {
282      opts.afterScroll.call(opts.link, opts);
283    }
284  };
285
286  $.smoothScroll.version = version;
287  $.smoothScroll.filterPath = function(string) {
288    string = string || '';
289
290    return string
291      .replace(/^\//, '')
292      .replace(/(?:index|default).[a-zA-Z]{3,4}$/, '')
293      .replace(/\/$/, '');
294  };
295
296  // default options
297  $.fn.smoothScroll.defaults = defaults;
298
299})(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.