scrollspy.js 9.54 KB
Newer Older
fat's avatar
fat committed
1
2
3
4
5
6
7
8
'use strict';

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; }; })();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

/**
 * --------------------------------------------------------------------------
9
 * Bootstrap (v4.0.0-alpha.2): scrollspy.js
fat's avatar
fat committed
10
11
12
13
14
15
16
17
18
19
20
21
22
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

var ScrollSpy = (function ($) {

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

  var NAME = 'scrollspy';
XhmikosR's avatar
XhmikosR committed
23
  var VERSION = '4.0.0-alpha.2';
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
78
79
80
81
  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */

  var ScrollSpy = (function () {
    function ScrollSpy(element, config) {
      _classCallCheck(this, ScrollSpy);

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

91
      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
fat's avatar
fat committed
92
93
94
95
96

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

Jacob Thornton's avatar
Jacob Thornton committed
97
98
99
100
101
102
103
104
    /**
     * ------------------------------------------------------------------------
     * Data Api implementation
     * ------------------------------------------------------------------------
     */

    // getters

fat's avatar
fat committed
105
106
107
108
109
110
111
112
    _createClass(ScrollSpy, [{
      key: 'refresh',

      // public

      value: function refresh() {
        var _this = this;

113
114
115
        var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;

        var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
fat's avatar
fat committed
116

117
        var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
fat's avatar
fat committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

        this._offsets = [];
        this._targets = [];

        this._scrollHeight = this._getScrollHeight();

        var targets = $.makeArray($(this._selector));

        targets.map(function (element) {
          var target = undefined;
          var targetSelector = Util.getSelectorFromElement(element);

          if (targetSelector) {
            target = $(targetSelector)[0];
          }

          if (target && (target.offsetWidth || target.offsetHeight)) {
            // todo (fat): remove sketch reliance on jQuery position/offset
            return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
          }
Chris Rebert's avatar
grunt    
Chris Rebert committed
138
          return null;
fat's avatar
fat committed
139
140
141
142
143
144
145
146
147
        }).filter(function (item) {
          return item;
        }).sort(function (a, b) {
          return a[0] - b[0];
        }).forEach(function (item) {
          _this._offsets.push(item[0]);
          _this._targets.push(item[1]);
        });
      }
fat's avatar
fat committed
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    }, {
      key: 'dispose',
      value: 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
163
164
165

      // private

Jacob Thornton's avatar
Jacob Thornton committed
166
167
    }, {
      key: '_getConfig',
fat's avatar
fat committed
168
169
170
171
172
173
174
175
176
177
178
179
      value: function _getConfig(config) {
        config = $.extend({}, Default, config);

        if (typeof config.target !== 'string') {
          var id = $(config.target).attr('id');
          if (!id) {
            id = Util.getUID(NAME);
            $(config.target).attr('id', id);
          }
          config.target = '#' + id;
        }

fat's avatar
fat committed
180
181
        Util.typeCheckConfig(NAME, config, DefaultType);

fat's avatar
fat committed
182
183
184
185
        return config;
      }
    }, {
      key: '_getScrollTop',
fat's avatar
fat committed
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
      value: function _getScrollTop() {
        return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
      }
    }, {
      key: '_getScrollHeight',
      value: function _getScrollHeight() {
        return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
      }
    }, {
      key: '_process',
      value: 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();
        }

        if (scrollTop >= maxScroll) {
          var target = this._targets[this._targets.length - 1];

          if (this._activeTarget !== target) {
            this._activate(target);
          }
        }

        if (this._activeTarget && scrollTop < this._offsets[0]) {
          this._activeTarget = null;
          this._clear();
          return;
        }

        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]);

          if (isActiveTarget) {
            this._activate(this._targets[i]);
          }
        }
      }
    }, {
      key: '_activate',
      value: function _activate(target) {
        this._activeTarget = target;

        this._clear();

Jacob Thornton's avatar
Jacob Thornton committed
234
235
236
237
        var queries = this._selector.split(',');
        queries = queries.map(function (selector) {
          return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
        });
fat's avatar
fat committed
238

Jacob Thornton's avatar
Jacob Thornton committed
239
        var $link = $(queries.join(','));
fat's avatar
fat committed
240

Jacob Thornton's avatar
Jacob Thornton committed
241
        if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
242
243
244
          $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
          $link.addClass(ClassName.ACTIVE);
        } else {
245
          // todo (fat) this is kinda sus...
246
247
          // recursively add actives to tested nav-links
          $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
fat's avatar
fat committed
248
249
250
251
252
253
254
255
256
        }

        $(this._scrollElement).trigger(Event.ACTIVATE, {
          relatedTarget: target
        });
      }
    }, {
      key: '_clear',
      value: function _clear() {
257
        $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
fat's avatar
fat committed
258
259
260
261
      }

      // static

Jacob Thornton's avatar
Jacob Thornton committed
262
263
    }], [{
      key: '_jQueryInterface',
fat's avatar
fat committed
264
265
266
267
268
269
270
271
272
273
274
      value: function _jQueryInterface(config) {
        return this.each(function () {
          var data = $(this).data(DATA_KEY);
          var _config = typeof config === 'object' && config || null;

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

          if (typeof config === 'string') {
Chris Rebert's avatar
Chris Rebert committed
275
276
277
            if (data[config] === undefined) {
              throw new Error('No method named "' + config + '"');
            }
fat's avatar
fat committed
278
279
280
281
            data[config]();
          }
        });
      }
Jacob Thornton's avatar
Jacob Thornton committed
282
283
284
285
286
287
288
289
290
291
    }, {
      key: 'VERSION',
      get: function get() {
        return VERSION;
      }
    }, {
      key: 'Default',
      get: function get() {
        return Default;
      }
fat's avatar
fat committed
292
293
294
295
296
    }]);

    return ScrollSpy;
  })();

fat's avatar
fat committed
297
  $(window).on(Event.LOAD_DATA_API, function () {
fat's avatar
fat committed
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
    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;
})(jQuery);
Jacob Thornton's avatar
Jacob Thornton committed
321
//# sourceMappingURL=scrollspy.js.map