scrollspy.js 9.57 KB
Newer Older
Mark Otto's avatar
grunt    
Mark Otto committed
1
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
fat's avatar
fat committed
2

Mark Otto's avatar
grunt    
Mark Otto committed
3
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
fat's avatar
fat committed
4

Mark Otto's avatar
grunt    
Mark Otto committed
5
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
fat's avatar
fat committed
6
7
8

/**
 * --------------------------------------------------------------------------
Mark Otto's avatar
Mark Otto committed
9
 * Bootstrap (v4.0.0-alpha.5): scrollspy.js
fat's avatar
fat committed
10
11
12
13
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

Mark Otto's avatar
grunt    
Mark Otto committed
14
var ScrollSpy = function ($) {
fat's avatar
fat committed
15
16
17
18
19
20
21
22

  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */

  var NAME = 'scrollspy';
Mark Otto's avatar
Mark Otto committed
23
  var VERSION = '4.0.0-alpha.5';
fat's avatar
fat committed
24
  var DATA_KEY = 'bs.scrollspy';
fat's avatar
fat committed
25
26
  var EVENT_KEY = '.' + DATA_KEY;
  var DATA_API_KEY = '.data-api';
fat's avatar
fat committed
27
28
  var JQUERY_NO_CONFLICT = $.fn[NAME];

29
  var Default = {
30
    offset: 10,
fat's avatar
fat committed
31
32
    method: 'auto',
    target: ''
fat's avatar
fat committed
33
34
  };

fat's avatar
fat committed
35
36
37
38
39
40
  var DefaultType = {
    offset: 'number',
    method: 'string',
    target: '(string|element)'
  };

fat's avatar
fat committed
41
  var Event = {
fat's avatar
fat committed
42
43
    ACTIVATE: 'activate' + EVENT_KEY,
    SCROLL: 'scroll' + EVENT_KEY,
Jacob Thornton's avatar
Jacob Thornton committed
44
    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
fat's avatar
fat committed
45
46
47
  };

  var ClassName = {
Jacob Thornton's avatar
Jacob Thornton committed
48
    DROPDOWN_ITEM: 'dropdown-item',
fat's avatar
fat committed
49
    DROPDOWN_MENU: 'dropdown-menu',
50
51
    NAV_LINK: 'nav-link',
    NAV: 'nav',
fat's avatar
fat committed
52
53
54
55
56
57
    ACTIVE: 'active'
  };

  var Selector = {
    DATA_SPY: '[data-spy="scroll"]',
    ACTIVE: '.active',
58
    LIST_ITEM: '.list-item',
fat's avatar
fat committed
59
    LI: 'li',
fat's avatar
fat committed
60
    LI_DROPDOWN: 'li.dropdown',
Jacob Thornton's avatar
Jacob Thornton committed
61
    NAV_LINKS: '.nav-link',
62
63
64
    DROPDOWN: '.dropdown',
    DROPDOWN_ITEMS: '.dropdown-item',
    DROPDOWN_TOGGLE: '.dropdown-toggle'
fat's avatar
fat committed
65
66
  };

67
68
69
70
71
  var OffsetMethod = {
    OFFSET: 'offset',
    POSITION: 'position'
  };

fat's avatar
fat committed
72
73
74
75
76
77
  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */

Mark Otto's avatar
grunt    
Mark Otto committed
78
  var ScrollSpy = function () {
fat's avatar
fat committed
79
    function ScrollSpy(element, config) {
Mark Otto's avatar
grunt    
Mark Otto committed
80
81
      var _this = this;

fat's avatar
fat committed
82
83
      _classCallCheck(this, ScrollSpy);

fat's avatar
fat committed
84
      this._element = element;
fat's avatar
fat committed
85
      this._scrollElement = element.tagName === 'BODY' ? window : element;
fat's avatar
fat committed
86
      this._config = this._getConfig(config);
Jacob Thornton's avatar
Jacob Thornton committed
87
      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
fat's avatar
fat committed
88
89
90
91
92
      this._offsets = [];
      this._targets = [];
      this._activeTarget = null;
      this._scrollHeight = 0;

Mark Otto's avatar
grunt    
Mark Otto committed
93
94
95
      $(this._scrollElement).on(Event.SCROLL, function (event) {
        return _this._process(event);
      });
fat's avatar
fat committed
96
97
98
99
100

      this.refresh();
      this._process();
    }

Jacob Thornton's avatar
Jacob Thornton committed
101
102
    // getters

Mark Otto's avatar
grunt    
Mark Otto committed
103
    // public
fat's avatar
fat committed
104

Mark Otto's avatar
grunt    
Mark Otto committed
105
    ScrollSpy.prototype.refresh = function refresh() {
Mark Otto's avatar
grunt    
Mark Otto committed
106
      var _this2 = this;
fat's avatar
fat committed
107

Mark Otto's avatar
grunt    
Mark Otto committed
108
      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
fat's avatar
fat committed
109

Mark Otto's avatar
grunt    
Mark Otto committed
110
      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
111

Mark Otto's avatar
grunt    
Mark Otto committed
112
      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
fat's avatar
fat committed
113

Mark Otto's avatar
grunt    
Mark Otto committed
114
115
      this._offsets = [];
      this._targets = [];
fat's avatar
fat committed
116

Mark Otto's avatar
grunt    
Mark Otto committed
117
      this._scrollHeight = this._getScrollHeight();
fat's avatar
fat committed
118

Mark Otto's avatar
grunt    
Mark Otto committed
119
      var targets = $.makeArray($(this._selector));
fat's avatar
fat committed
120

Mark Otto's avatar
grunt    
Mark Otto committed
121
122
123
      targets.map(function (element) {
        var target = void 0;
        var targetSelector = Util.getSelectorFromElement(element);
fat's avatar
fat committed
124

Mark Otto's avatar
grunt    
Mark Otto committed
125
126
127
        if (targetSelector) {
          target = $(targetSelector)[0];
        }
fat's avatar
fat committed
128

Mark Otto's avatar
grunt    
Mark Otto committed
129
130
131
132
133
134
135
136
137
138
        if (target && (target.offsetWidth || target.offsetHeight)) {
          // todo (fat): remove sketch reliance on jQuery position/offset
          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
        }
        return null;
      }).filter(function (item) {
        return item;
      }).sort(function (a, b) {
        return a[0] - b[0];
      }).forEach(function (item) {
Mark Otto's avatar
grunt    
Mark Otto committed
139
140
        _this2._offsets.push(item[0]);
        _this2._targets.push(item[1]);
Mark Otto's avatar
grunt    
Mark Otto committed
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
      });
    };

    ScrollSpy.prototype.dispose = function dispose() {
      $.removeData(this._element, DATA_KEY);
      $(this._scrollElement).off(EVENT_KEY);

      this._element = null;
      this._scrollElement = null;
      this._config = null;
      this._selector = null;
      this._offsets = null;
      this._targets = null;
      this._activeTarget = null;
      this._scrollHeight = null;
    };
fat's avatar
fat committed
157

Mark Otto's avatar
grunt    
Mark Otto committed
158
    // private
fat's avatar
fat committed
159

Mark Otto's avatar
grunt    
Mark Otto committed
160
161
    ScrollSpy.prototype._getConfig = function _getConfig(config) {
      config = $.extend({}, Default, config);
fat's avatar
fat committed
162

Mark Otto's avatar
grunt    
Mark Otto committed
163
164
165
166
167
      if (typeof config.target !== 'string') {
        var id = $(config.target).attr('id');
        if (!id) {
          id = Util.getUID(NAME);
          $(config.target).attr('id', id);
fat's avatar
fat committed
168
        }
Mark Otto's avatar
grunt    
Mark Otto committed
169
170
        config.target = '#' + id;
      }
fat's avatar
fat committed
171

Mark Otto's avatar
grunt    
Mark Otto committed
172
      Util.typeCheckConfig(NAME, config, DefaultType);
fat's avatar
fat committed
173

Mark Otto's avatar
grunt    
Mark Otto committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
      return config;
    };

    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
    };

    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
    };

    ScrollSpy.prototype._process = function _process() {
      var scrollTop = this._getScrollTop() + this._config.offset;
      var scrollHeight = this._getScrollHeight();
      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;

      if (this._scrollHeight !== scrollHeight) {
        this.refresh();
fat's avatar
fat committed
192
193
      }

Mark Otto's avatar
grunt    
Mark Otto committed
194
195
      if (scrollTop >= maxScroll) {
        var target = this._targets[this._targets.length - 1];
fat's avatar
fat committed
196

Mark Otto's avatar
grunt    
Mark Otto committed
197
198
        if (this._activeTarget !== target) {
          this._activate(target);
fat's avatar
fat committed
199
        }
Mark Otto's avatar
grunt    
Mark Otto committed
200
      }
fat's avatar
fat committed
201

Mark Otto's avatar
grunt    
Mark Otto committed
202
203
204
205
206
      if (this._activeTarget && scrollTop < this._offsets[0]) {
        this._activeTarget = null;
        this._clear();
        return;
      }
fat's avatar
fat committed
207

Mark Otto's avatar
grunt    
Mark Otto committed
208
209
      for (var i = this._offsets.length; i--;) {
        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
fat's avatar
fat committed
210

Mark Otto's avatar
grunt    
Mark Otto committed
211
212
        if (isActiveTarget) {
          this._activate(this._targets[i]);
fat's avatar
fat committed
213
214
        }
      }
Mark Otto's avatar
grunt    
Mark Otto committed
215
    };
fat's avatar
fat committed
216

Mark Otto's avatar
grunt    
Mark Otto committed
217
218
    ScrollSpy.prototype._activate = function _activate(target) {
      this._activeTarget = target;
fat's avatar
fat committed
219

Mark Otto's avatar
grunt    
Mark Otto committed
220
      this._clear();
fat's avatar
fat committed
221

Mark Otto's avatar
grunt    
Mark Otto committed
222
223
224
225
      var queries = this._selector.split(',');
      queries = queries.map(function (selector) {
        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
      });
fat's avatar
fat committed
226

Mark Otto's avatar
grunt    
Mark Otto committed
227
      var $link = $(queries.join(','));
fat's avatar
fat committed
228

Mark Otto's avatar
grunt    
Mark Otto committed
229
230
231
232
233
234
235
      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
        $link.addClass(ClassName.ACTIVE);
      } else {
        // todo (fat) this is kinda sus...
        // recursively add actives to tested nav-links
        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
fat's avatar
fat committed
236
237
      }

Mark Otto's avatar
grunt    
Mark Otto committed
238
239
240
241
      $(this._scrollElement).trigger(Event.ACTIVATE, {
        relatedTarget: target
      });
    };
fat's avatar
fat committed
242

Mark Otto's avatar
grunt    
Mark Otto committed
243
244
245
    ScrollSpy.prototype._clear = function _clear() {
      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
    };
fat's avatar
fat committed
246

Mark Otto's avatar
grunt    
Mark Otto committed
247
    // static
fat's avatar
fat committed
248

Mark Otto's avatar
grunt    
Mark Otto committed
249
250
251
252
253
254
255
256
257
258
259
260
261
    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
      return this.each(function () {
        var data = $(this).data(DATA_KEY);
        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;

        if (!data) {
          data = new ScrollSpy(this, _config);
          $(this).data(DATA_KEY, data);
        }

        if (typeof config === 'string') {
          if (data[config] === undefined) {
            throw new Error('No method named "' + config + '"');
fat's avatar
fat committed
262
          }
Mark Otto's avatar
grunt    
Mark Otto committed
263
264
265
266
267
268
          data[config]();
        }
      });
    };

    _createClass(ScrollSpy, null, [{
Jacob Thornton's avatar
Jacob Thornton committed
269
270
271
272
273
274
275
276
277
      key: 'VERSION',
      get: function get() {
        return VERSION;
      }
    }, {
      key: 'Default',
      get: function get() {
        return Default;
      }
fat's avatar
fat committed
278
279
280
    }]);

    return ScrollSpy;
Mark Otto's avatar
grunt    
Mark Otto committed
281
282
283
284
285
286
287
  }();

  /**
   * ------------------------------------------------------------------------
   * Data Api implementation
   * ------------------------------------------------------------------------
   */
fat's avatar
fat committed
288

fat's avatar
fat committed
289
  $(window).on(Event.LOAD_DATA_API, function () {
fat's avatar
fat committed
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    var scrollSpys = $.makeArray($(Selector.DATA_SPY));

    for (var i = scrollSpys.length; i--;) {
      var $spy = $(scrollSpys[i]);
      ScrollSpy._jQueryInterface.call($spy, $spy.data());
    }
  });

  /**
   * ------------------------------------------------------------------------
   * jQuery
   * ------------------------------------------------------------------------
   */

  $.fn[NAME] = ScrollSpy._jQueryInterface;
  $.fn[NAME].Constructor = ScrollSpy;
  $.fn[NAME].noConflict = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT;
    return ScrollSpy._jQueryInterface;
  };

  return ScrollSpy;
Mark Otto's avatar
grunt    
Mark Otto committed
312
}(jQuery);
Jacob Thornton's avatar
Jacob Thornton committed
313
//# sourceMappingURL=scrollspy.js.map