UNPKG

baseframe-js

Version:

A suite of useful Javascript plugins and functions to help with Front-end Development on websites

308 lines (307 loc) 15 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _helpers = require("./util/helpers"); var _cashDom = _interopRequireDefault(require("cash-dom")); var _Store = _interopRequireDefault(require("./core/Store")); var _UrlState = _interopRequireDefault(require("./core/UrlState")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); } function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } } function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); } function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; } function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); } var VERSION = "1.0.1"; var DATA_NAME = 'ScrollSpy'; var EVENT_NAME = 'scrollSpy'; var DEFAULTS = { observerOptions: { rootMargin: "0px", threshold: 1 }, cssPrefix: 'scroll-spy', spyNavElems: 'a', spyBody: '.scroll-spy-body', spyElems: 'h2', setActiveCssToLi: true, locationFilter: null, urlFilterType: 'hash', historyType: 'push', loadLocation: true }; var _pairedElems = /*#__PURE__*/new WeakMap(); var _lastSpyElem = /*#__PURE__*/new WeakMap(); var _observer = /*#__PURE__*/new WeakMap(); var _ScrollSpy_brand = /*#__PURE__*/new WeakSet(); var ScrollSpy = exports["default"] = /*#__PURE__*/function () { function ScrollSpy(element, options) { _classCallCheck(this, ScrollSpy); _classPrivateMethodInitSpec(this, _ScrollSpy_brand); _classPrivateFieldInitSpec(this, _pairedElems, new Map()); _defineProperty(this, "inViewEntries", new Set()); _defineProperty(this, "backUpInViewEntry", void 0); _classPrivateFieldInitSpec(this, _lastSpyElem, null); _classPrivateFieldInitSpec(this, _observer, null); _defineProperty(this, "params", void 0); _defineProperty(this, "element", void 0); _defineProperty(this, "$spyBody", void 0); _defineProperty(this, "spyContents", void 0); var _s = this; var dataOptions = (0, _helpers.getDataOptions)(element, EVENT_NAME); _s.element = element; _s.params = _cashDom["default"].extend({}, ScrollSpy.defaults, options, dataOptions); _s.$spyBody = (0, _cashDom["default"])(_s.params.spyBody); _s.spyContents = Array.from(_s.$spyBody.find(_s.params.spyElems)).filter(function (el) { return (0, _helpers.isVisible)(el) && el.id; }); if (_s.spyContents.length > 0) { (0, _cashDom["default"])(element).addClass("".concat(_s.params.cssPrefix, "-nav")); _s.$spyBody.addClass("".concat(_s.params.cssPrefix, "-body")); _classPrivateFieldSet(_lastSpyElem, _s, _s.spyContents[_s.spyContents.length - 1]); _s.backUpInViewEntry = _assertClassBrand(_ScrollSpy_brand, _s, _getInitialBackUpInViewEntry).call(_s); _assertClassBrand(_ScrollSpy_brand, _s, _pairElementsToNavEls).call(_s); _s.handleEvents(); } else { console.warn("there is nothing to spy, check your 'spyBody' for those elements", _s.params.spyBody); } return _s; } return _createClass(ScrollSpy, [{ key: "handleEvents", value: function handleEvents() { var s = this; var p = s.params; var observerProcess = function observerProcess(entries) { _assertClassBrand(_ScrollSpy_brand, s, _setInViewEntries).call(s, entries); _assertClassBrand(_ScrollSpy_brand, s, _spyElements).call(s); }; s.loadFromUrl(); _classPrivateFieldSet(_observer, s, new IntersectionObserver(observerProcess, p.observerOptions)); var _iterator = _createForOfIteratorHelper(s.spyContents), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var elem = _step.value; _classPrivateFieldGet(_observer, s).observe(elem); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } (0, _cashDom["default"])(s.element).on("click.".concat(EVENT_NAME), p.spyNavElems, function (e) { var clickElem = this; var paramVal = (this.nodeName === 'A' ? this.hash : clickElem.dataset.hash).replace(/^\#/, ''); var $bodyElem = s.scrollToElement(paramVal, 'smooth'); if ($bodyElem.length) { if (typeof p.urlFilterType === 'string') { if (p.locationFilter) { if (p.urlFilterType === 'hashVal') { _UrlState["default"].setHashVal(paramVal, p.historyType); } else if (p.urlFilterType === 'hash' || p.urlFilterType === 'search') { _UrlState["default"].set(p.urlFilterType, p.locationFilter, paramVal, p.historyType); } } } e.preventDefault(); } }); } }, { key: "scrollToElement", value: function scrollToElement(elemId, behavior) { var s = this; var p = s.params; var scrollRoot = p.observerOptions.root || window; var observerOffsetTop = parseFloat(p.observerOptions.rootMargin.split(' ')[0]) || 0; var $bodyElem = (0, _cashDom["default"])(elemId ? '#' + elemId : document.body); if ($bodyElem.length) { scrollRoot.scrollTo({ top: $bodyElem.offset().top - observerOffsetTop, behavior: behavior }); } return $bodyElem; } }, { key: "loadFromUrl", value: function loadFromUrl() { var s = this; var p = s.params; if (p.locationFilter !== null && p.loadLocation && p.urlFilterType !== 'none') { var spyId = _UrlState["default"].get(p.urlFilterType, p.locationFilter); if (spyId) { s.scrollToElement(spyId, 'instant'); } } } }], [{ key: "remove", value: function remove(element, plugin) { (0, _cashDom["default"])(element).each(function () { var s = plugin || (0, _Store["default"])(this, DATA_NAME); var _iterator2 = _createForOfIteratorHelper(s.spyContents), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var elem = _step2.value; _assertClassBrand(_ScrollSpy_brand, s, _toggleActiveCss).call(s, elem, 'remove'); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } (0, _cashDom["default"])(s.element).off("click.".concat(EVENT_NAME)).removeClass("".concat(s.params.cssPrefix, "-nav")); s.$spyBody.removeClass("".concat(s.params.cssPrefix, "-body")); _classPrivateFieldGet(_observer, s).disconnect(); (0, _Store["default"])(this, DATA_NAME, null); }); } }]); }(); function _getInitialBackUpInViewEntry() { var s = this; var sortedByTop = s.spyContents.map(function (el) { return { el: el, top: el.getBoundingClientRect().top }; }).sort(function (a, b) { return a.top < b.top ? -1 : 1; }); for (var i = 0, l = sortedByTop.length; i < l; i++) { var curr = sortedByTop[i]; var prev = sortedByTop[i - 1]; if (curr.top >= 0) { if (prev) { return prev.el; } return curr.el; } } } function _pairElementsToNavEls() { var s = this; var _s$params = s.params, spyNavElems = _s$params.spyNavElems, setActiveCssToLi = _s$params.setActiveCssToLi; (0, _cashDom["default"])(s.element).find(spyNavElems).each(function () { var clickEl = this; var hash = this.nodeName === 'A' ? clickEl.hash : clickEl.dataset.hash; if (hash) { var foundElem = s.spyContents.find(function (el) { return el.id && el.id === hash.replace('#', ''); }); if (foundElem) { var pairedElem = setActiveCssToLi ? clickEl.closest('li') || clickEl : clickEl; _classPrivateFieldGet(_pairedElems, s).set(foundElem, pairedElem); _classPrivateFieldGet(_pairedElems, s).set(clickEl, foundElem); } } }); } function _setInViewEntries(entries) { var s = this; var _iterator3 = _createForOfIteratorHelper(entries), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var entry = _step3.value; var target = entry.target; if (entry.isIntersecting) { s.inViewEntries.add(target); } else { if (s.inViewEntries.has(target)) { s.backUpInViewEntry = target; s.inViewEntries["delete"](target); _assertClassBrand(_ScrollSpy_brand, s, _toggleActiveCss).call(s, target, 'remove'); } } } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } function _toggleActiveCss(target, type) { var s = this; var cssPrefix = s.params.cssPrefix; var clickElem = _classPrivateFieldGet(_pairedElems, s).get(target); if (clickElem) { clickElem.classList[type]("".concat(cssPrefix, "-nav__active")); target.classList[type]("".concat(cssPrefix, "-body__active")); } } function _spyElements() { var s = this; var hasInViewEntries = s.inViewEntries.size > 0; var topMostEntries = hasInViewEntries ? [] : [s.backUpInViewEntry]; var _iterator4 = _createForOfIteratorHelper(s.inViewEntries), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var entry = _step4.value; if (topMostEntries.length) { var elTop = entry.getBoundingClientRect().top; for (var i = 0, l = topMostEntries.length; i < l; i++) { var tmEntry = topMostEntries[i]; var tmElTop = tmEntry.getBoundingClientRect().top; if (elTop < tmElTop && elTop >= 0) { topMostEntries.splice(i, 1, entry); _assertClassBrand(_ScrollSpy_brand, s, _toggleActiveCss).call(s, tmEntry, 'remove'); } var isLastEntry = _classPrivateFieldGet(_lastSpyElem, s).isSameNode(entry); if (isLastEntry) { var remainingBodyScroll = document.body.scrollHeight - window.scrollY; var canScrollAmount = window.innerHeight; if (canScrollAmount > remainingBodyScroll) { // if we can't get to the last scroll element // then highlight once in the screen topMostEntries.push(entry); } } if (elTop === tmElTop) { topMostEntries.push(entry); } } } else { topMostEntries.push(entry); } } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } if (hasInViewEntries) { _assertClassBrand(_ScrollSpy_brand, s, _toggleActiveCss).call(s, s.backUpInViewEntry, 'remove'); } for (var _i = 0, _topMostEntries = topMostEntries; _i < _topMostEntries.length; _i++) { var elem = _topMostEntries[_i]; _assertClassBrand(_ScrollSpy_brand, s, _toggleActiveCss).call(s, elem, 'add'); } if (s.params.callback) { var navEntries = topMostEntries.map(function (el) { return _classPrivateFieldGet(_pairedElems, s).get(el); }); s.params.callback(topMostEntries, navEntries); } } _defineProperty(ScrollSpy, "defaults", DEFAULTS); _defineProperty(ScrollSpy, "version", VERSION); _defineProperty(ScrollSpy, "pluginName", DATA_NAME);