PageSourceSearch

https://windliang.wang/js/src/affix.js?v=6.3.0

js windliang.wang collected 2026-10-04 00:12:31 UTC 5,100 bytes, 168 lines download raw bytes

1/* ========================================================================
2 * Bootstrap: affix.js v3.3.5
3 * http://getbootstrap.com/javascript/#affix
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 Ivan.Nginx
11 *
12 * - Refactored with eslint-config-theme-next style.
13 */
14
15(function($) {
16  'use strict';
17
18  // AFFIX CLASS DEFINITION
19  // ======================
20
21  var Affix = function(element, options) {
22    this.options = $.extend({}, Affix.DEFAULTS, options);
23
24    this.$target = $(this.options.target)
25      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
26      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this));
27
28    this.$element     = $(element);
29    this.affixed      = null;
30    this.unpin        = null;
31    this.pinnedOffset = null;
32
33    this.checkPosition();
34  };
35
36  Affix.VERSION  = '3.3.5';
37
38  Affix.RESET    = 'affix affix-top affix-bottom';
39
40  Affix.DEFAULTS = {
41    offset: 0,
42    target: window
43  };
44
45  Affix.prototype.getState = function(scrollHeight, height, offsetTop, offsetBottom) {
46    var scrollTop    = this.$target.scrollTop();
47    var position     = this.$element.offset();
48    var targetHeight = this.$target.height();
49
50    if (offsetTop != null && this.affixed === 'top') return scrollTop < offsetTop ? 'top' : false;
51
52    if (this.affixed === 'bottom') {
53      if (offsetTop != null) return scrollTop + this.unpin <= position.top ? false : 'bottom';
54      return scrollTop + targetHeight <= scrollHeight - offsetBottom ? false : 'bottom';
55    }
56
57    var initializing   = this.affixed == null;
58    var colliderTop    = initializing ? scrollTop : position.top;
59    var colliderHeight = initializing ? targetHeight : height;
60
61    if (offsetTop != null && scrollTop <= offsetTop) return 'top';
62    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom';
63
64    return false;
65  };
66
67  Affix.prototype.getPinnedOffset = function() {
68    if (this.pinnedOffset) return this.pinnedOffset;
69    this.$element.removeClass(Affix.RESET).addClass('affix');
70    var scrollTop = this.$target.scrollTop();
71    var position  = this.$element.offset();
72    return (this.pinnedOffset = position.top - scrollTop);
73  };
74
75  Affix.prototype.checkPositionWithEventLoop = function() {
76    setTimeout($.proxy(this.checkPosition, this), 1);
77  };
78
79  Affix.prototype.checkPosition = function() {
80    if (!this.$element.is(':visible')) return;
81
82    var height       = this.$element.height();
83    var offset       = this.options.offset;
84    var offsetTop    = offset.top;
85    var offsetBottom = offset.bottom;
86    var scrollHeight = Math.max($(document).height(), $(document.body).height());
87
88    /* eslint-disable */
89    if (typeof offset !== 'object')         offsetBottom = offsetTop = offset;
90    if (typeof offsetTop === 'function')    offsetTop    = offset.top(this.$element);
91    if (typeof offsetBottom === 'function') offsetBottom = offset.bottom(this.$element);
92    /* eslint-enable */
93
94    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom);
95
96    if (this.affixed !== affix) {
97      if (this.unpin != null) this.$element.css('top', '');
98
99      var affixType = 'affix' + (affix ? '-' + affix : '');
100      var e         = new $.Event(affixType + '.bs.affix');
101
102      this.$element.trigger(e);
103
104      if (e.isDefaultPrevented()) return;
105
106      this.affixed = affix;
107      this.unpin = affix === 'bottom' ? this.getPinnedOffset() : null;
108
109      this.$element
110        .removeClass(Affix.RESET)
111        .addClass(affixType)
112        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix');
113    }
114
115    if (affix === 'bottom') {
116      this.$element.offset({
117        top: scrollHeight - height - offsetBottom
118      });
119    }
120  };
121
122  // AFFIX PLUGIN DEFINITION
123  // =======================
124
125  function Plugin(option) {
126    return this.each(function() {
127      var $this   = $(this);
128      var data    = $this.data('bs.affix');
129      var options = typeof option === 'object' && option;
130
131      if (!data) $this.data('bs.affix', data = new Affix(this, options));
132      if (typeof option === 'string') data[option]();
133    });
134  }
135
136  var old = $.fn.affix;
137
138  $.fn.affix             = Plugin;
139  $.fn.affix.Constructor = Affix;
140
141  // AFFIX NO CONFLICT
142  // =================
143
144  $.fn.affix.noConflict = function() {
145    $.fn.affix = old;
146    return this;
147  };
148
149  // AFFIX DATA-API
150  // ==============
151
152  $(window).on('load', function() {
153    $('[data-spy="affix"]').each(function() {
154      var $spy = $(this);
155      var data = $spy.data();
156
157      data.offset = data.offset || {};
158
159      /* eslint-disable */
160      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom;
161      if (data.offsetTop    != null) data.offset.top    = data.offsetTop;
162      /* eslint-enable */
163
164      Plugin.call($spy, data);
165    });
166  });
167
168}(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.