scrollspy.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
  3. typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
  4. (global.ScrollSpy = factory(global.jQuery,global.Util));
  5. }(this, (function ($,Util) { 'use strict';
  6. $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
  7. Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
  8. function _defineProperties(target, props) {
  9. for (var i = 0; i < props.length; i++) {
  10. var descriptor = props[i];
  11. descriptor.enumerable = descriptor.enumerable || false;
  12. descriptor.configurable = true;
  13. if ("value" in descriptor) descriptor.writable = true;
  14. Object.defineProperty(target, descriptor.key, descriptor);
  15. }
  16. }
  17. function _createClass(Constructor, protoProps, staticProps) {
  18. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  19. if (staticProps) _defineProperties(Constructor, staticProps);
  20. return Constructor;
  21. }
  22. function _defineProperty(obj, key, value) {
  23. if (key in obj) {
  24. Object.defineProperty(obj, key, {
  25. value: value,
  26. enumerable: true,
  27. configurable: true,
  28. writable: true
  29. });
  30. } else {
  31. obj[key] = value;
  32. }
  33. return obj;
  34. }
  35. function _objectSpread(target) {
  36. for (var i = 1; i < arguments.length; i++) {
  37. var source = arguments[i] != null ? arguments[i] : {};
  38. var ownKeys = Object.keys(source);
  39. if (typeof Object.getOwnPropertySymbols === 'function') {
  40. ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
  41. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  42. }));
  43. }
  44. ownKeys.forEach(function (key) {
  45. _defineProperty(target, key, source[key]);
  46. });
  47. }
  48. return target;
  49. }
  50. /**
  51. * --------------------------------------------------------------------------
  52. * Bootstrap (v4.1.3): scrollspy.js
  53. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  54. * --------------------------------------------------------------------------
  55. */
  56. var ScrollSpy = function ($$$1) {
  57. /**
  58. * ------------------------------------------------------------------------
  59. * Constants
  60. * ------------------------------------------------------------------------
  61. */
  62. var NAME = 'scrollspy';
  63. var VERSION = '4.1.3';
  64. var DATA_KEY = 'bs.scrollspy';
  65. var EVENT_KEY = "." + DATA_KEY;
  66. var DATA_API_KEY = '.data-api';
  67. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  68. var Default = {
  69. offset: 10,
  70. method: 'auto',
  71. target: ''
  72. };
  73. var DefaultType = {
  74. offset: 'number',
  75. method: 'string',
  76. target: '(string|element)'
  77. };
  78. var Event = {
  79. ACTIVATE: "activate" + EVENT_KEY,
  80. SCROLL: "scroll" + EVENT_KEY,
  81. LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY
  82. };
  83. var ClassName = {
  84. DROPDOWN_ITEM: 'dropdown-item',
  85. DROPDOWN_MENU: 'dropdown-menu',
  86. ACTIVE: 'active'
  87. };
  88. var Selector = {
  89. DATA_SPY: '[data-spy="scroll"]',
  90. ACTIVE: '.active',
  91. NAV_LIST_GROUP: '.nav, .list-group',
  92. NAV_LINKS: '.nav-link',
  93. NAV_ITEMS: '.nav-item',
  94. LIST_ITEMS: '.list-group-item',
  95. DROPDOWN: '.dropdown',
  96. DROPDOWN_ITEMS: '.dropdown-item',
  97. DROPDOWN_TOGGLE: '.dropdown-toggle'
  98. };
  99. var OffsetMethod = {
  100. OFFSET: 'offset',
  101. POSITION: 'position'
  102. /**
  103. * ------------------------------------------------------------------------
  104. * Class Definition
  105. * ------------------------------------------------------------------------
  106. */
  107. };
  108. var ScrollSpy =
  109. /*#__PURE__*/
  110. function () {
  111. function ScrollSpy(element, config) {
  112. var _this = this;
  113. this._element = element;
  114. this._scrollElement = element.tagName === 'BODY' ? window : element;
  115. this._config = this._getConfig(config);
  116. this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS);
  117. this._offsets = [];
  118. this._targets = [];
  119. this._activeTarget = null;
  120. this._scrollHeight = 0;
  121. $$$1(this._scrollElement).on(Event.SCROLL, function (event) {
  122. return _this._process(event);
  123. });
  124. this.refresh();
  125. this._process();
  126. } // Getters
  127. var _proto = ScrollSpy.prototype;
  128. // Public
  129. _proto.refresh = function refresh() {
  130. var _this2 = this;
  131. var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION;
  132. var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
  133. var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
  134. this._offsets = [];
  135. this._targets = [];
  136. this._scrollHeight = this._getScrollHeight();
  137. var targets = [].slice.call(document.querySelectorAll(this._selector));
  138. targets.map(function (element) {
  139. var target;
  140. var targetSelector = Util.getSelectorFromElement(element);
  141. if (targetSelector) {
  142. target = document.querySelector(targetSelector);
  143. }
  144. if (target) {
  145. var targetBCR = target.getBoundingClientRect();
  146. if (targetBCR.width || targetBCR.height) {
  147. // TODO (fat): remove sketch reliance on jQuery position/offset
  148. return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector];
  149. }
  150. }
  151. return null;
  152. }).filter(function (item) {
  153. return item;
  154. }).sort(function (a, b) {
  155. return a[0] - b[0];
  156. }).forEach(function (item) {
  157. _this2._offsets.push(item[0]);
  158. _this2._targets.push(item[1]);
  159. });
  160. };
  161. _proto.dispose = function dispose() {
  162. $$$1.removeData(this._element, DATA_KEY);
  163. $$$1(this._scrollElement).off(EVENT_KEY);
  164. this._element = null;
  165. this._scrollElement = null;
  166. this._config = null;
  167. this._selector = null;
  168. this._offsets = null;
  169. this._targets = null;
  170. this._activeTarget = null;
  171. this._scrollHeight = null;
  172. }; // Private
  173. _proto._getConfig = function _getConfig(config) {
  174. config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {});
  175. if (typeof config.target !== 'string') {
  176. var id = $$$1(config.target).attr('id');
  177. if (!id) {
  178. id = Util.getUID(NAME);
  179. $$$1(config.target).attr('id', id);
  180. }
  181. config.target = "#" + id;
  182. }
  183. Util.typeCheckConfig(NAME, config, DefaultType);
  184. return config;
  185. };
  186. _proto._getScrollTop = function _getScrollTop() {
  187. return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
  188. };
  189. _proto._getScrollHeight = function _getScrollHeight() {
  190. return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
  191. };
  192. _proto._getOffsetHeight = function _getOffsetHeight() {
  193. return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
  194. };
  195. _proto._process = function _process() {
  196. var scrollTop = this._getScrollTop() + this._config.offset;
  197. var scrollHeight = this._getScrollHeight();
  198. var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
  199. if (this._scrollHeight !== scrollHeight) {
  200. this.refresh();
  201. }
  202. if (scrollTop >= maxScroll) {
  203. var target = this._targets[this._targets.length - 1];
  204. if (this._activeTarget !== target) {
  205. this._activate(target);
  206. }
  207. return;
  208. }
  209. if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
  210. this._activeTarget = null;
  211. this._clear();
  212. return;
  213. }
  214. var offsetLength = this._offsets.length;
  215. for (var i = offsetLength; i--;) {
  216. var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
  217. if (isActiveTarget) {
  218. this._activate(this._targets[i]);
  219. }
  220. }
  221. };
  222. _proto._activate = function _activate(target) {
  223. this._activeTarget = target;
  224. this._clear();
  225. var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style
  226. queries = queries.map(function (selector) {
  227. return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]");
  228. });
  229. var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(','))));
  230. if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
  231. $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
  232. $link.addClass(ClassName.ACTIVE);
  233. } else {
  234. // Set triggered link as active
  235. $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active
  236. // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
  237. $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ", " + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item
  238. $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
  239. }
  240. $$$1(this._scrollElement).trigger(Event.ACTIVATE, {
  241. relatedTarget: target
  242. });
  243. };
  244. _proto._clear = function _clear() {
  245. var nodes = [].slice.call(document.querySelectorAll(this._selector));
  246. $$$1(nodes).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
  247. }; // Static
  248. ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
  249. return this.each(function () {
  250. var data = $$$1(this).data(DATA_KEY);
  251. var _config = typeof config === 'object' && config;
  252. if (!data) {
  253. data = new ScrollSpy(this, _config);
  254. $$$1(this).data(DATA_KEY, data);
  255. }
  256. if (typeof config === 'string') {
  257. if (typeof data[config] === 'undefined') {
  258. throw new TypeError("No method named \"" + config + "\"");
  259. }
  260. data[config]();
  261. }
  262. });
  263. };
  264. _createClass(ScrollSpy, null, [{
  265. key: "VERSION",
  266. get: function get() {
  267. return VERSION;
  268. }
  269. }, {
  270. key: "Default",
  271. get: function get() {
  272. return Default;
  273. }
  274. }]);
  275. return ScrollSpy;
  276. }();
  277. /**
  278. * ------------------------------------------------------------------------
  279. * Data Api implementation
  280. * ------------------------------------------------------------------------
  281. */
  282. $$$1(window).on(Event.LOAD_DATA_API, function () {
  283. var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY));
  284. var scrollSpysLength = scrollSpys.length;
  285. for (var i = scrollSpysLength; i--;) {
  286. var $spy = $$$1(scrollSpys[i]);
  287. ScrollSpy._jQueryInterface.call($spy, $spy.data());
  288. }
  289. });
  290. /**
  291. * ------------------------------------------------------------------------
  292. * jQuery
  293. * ------------------------------------------------------------------------
  294. */
  295. $$$1.fn[NAME] = ScrollSpy._jQueryInterface;
  296. $$$1.fn[NAME].Constructor = ScrollSpy;
  297. $$$1.fn[NAME].noConflict = function () {
  298. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  299. return ScrollSpy._jQueryInterface;
  300. };
  301. return ScrollSpy;
  302. }($);
  303. return ScrollSpy;
  304. })));
  305. //# sourceMappingURL=scrollspy.js.map