UNPKG

baseframe-js

Version:

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

283 lines (282 loc) 13.1 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 _cashDom = _interopRequireDefault(require("cash-dom")); var _helpers = require("./util/helpers"); var _trapFocus = _interopRequireDefault(require("./fn/trapFocus")); var _transition2 = _interopRequireDefault(require("./fn/transition")); var _constants = require("./core/constants"); var _Store = _interopRequireDefault(require("./core/Store")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 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 _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 _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 _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); } 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 = "3.0.0"; var DATA_NAME = 'NavMobile'; var EVENT_NAME = 'navMobile'; var DEFAULTS = { enableBtn: '#mobile-nav-btn', ariaLabel: 'Toggle site navigation', subMenuText: 'toggle menu for', insertToggleBtnAfter: 'a', slideDuration: 400, outerElement: document.body, outsideClickClose: true, animateHeight: true, cssPrefix: 'menu', menuBtnCss: 'i i-arrow-b', menuBtnSkip: false, afterNavItemOpen: _helpers.noop, afterNavItemClose: _helpers.noop, afterOpen: _helpers.noop, afterClose: _helpers.noop, doTrapFocus: true, trapFocusElem: null, stopPropagation: true, bkptEnable: null }; var _transition = /*#__PURE__*/new WeakMap(); var _NavMobile_brand = /*#__PURE__*/new WeakSet(); var NavMobile = exports["default"] = /*#__PURE__*/function () { function NavMobile(element, options) { _classCallCheck(this, NavMobile); _classPrivateMethodInitSpec(this, _NavMobile_brand); _defineProperty(this, "$element", void 0); _defineProperty(this, "params", void 0); _defineProperty(this, "menuOpened", void 0); _defineProperty(this, "allowClick", void 0); _defineProperty(this, "cssList", void 0); _classPrivateFieldInitSpec(this, _transition, (0, _transition2["default"])()); var _s = this; var dataOptions = (0, _helpers.getDataOptions)(element, EVENT_NAME); _s.$element = (0, _cashDom["default"])(element); _s.params = _cashDom["default"].extend({}, NavMobile.defaults, options, dataOptions); var _s$params = _s.params, cssPrefix = _s$params.cssPrefix, menuBtnCss = _s$params.menuBtnCss; _s.cssList = { menuOuterOpen: "".concat(cssPrefix, "--outer-open"), menuHasUL: "".concat(cssPrefix, "__has-ul"), menuOpen: "".concat(cssPrefix, "--open"), menuOpening: "".concat(cssPrefix, "--is-opening"), menuClosing: "".concat(cssPrefix, "--is-closing"), menuToggling: "".concat(cssPrefix, "--toggling"), menuBtnCss: "".concat(cssPrefix, "__btn-nav ").concat(menuBtnCss) }; //run the methods _s.addChildNavCss(); _s.handleEvents(); _s.checkIfEnabled(); var elemID = element.id || element.className; (0, _cashDom["default"])(_s.params.enableBtn).attr({ 'aria-controls': elemID, 'aria-label': _s.params.ariaLabel }); return _s; } return _createClass(NavMobile, [{ key: "handleEvents", value: function handleEvents() { var s = this; var css = s.cssList; var $enableBtn = (0, _cashDom["default"])(s.params.enableBtn); $enableBtn.attr({ 'aria-expanded': 'false' }).on("click.".concat(EVENT_NAME, " ").concat(EVENT_NAME), function (e) { if (!s.allowClick) return; _assertClassBrand(_NavMobile_brand, s, _menuToggle).call(s); e.stopPropagation(); e.preventDefault(); }); (0, _cashDom["default"])(document).on("keydown.".concat(EVENT_NAME), function (e) { if (e.code === _constants.KEYS.esc && s.$element.hasClass(css.menuOpen) && s.allowClick) { _assertClassBrand(_NavMobile_brand, s, _menuToggle).call(s); if ($enableBtn.length) { $enableBtn[0].focus(); } } }); _assertClassBrand(_NavMobile_brand, s, _navToggle).call(s); _assertClassBrand(_NavMobile_brand, s, _outsideClickClose).call(s); } }, { key: "addChildNavCss", value: function addChildNavCss() { var s = this; var p = s.params; var css = s.cssList; (0, _cashDom["default"])('li', s.$element).has('ul').each(function () { var $this = (0, _cashDom["default"])(this); var skipUl = false; if (typeof p.menuBtnSkip === 'function' && // condition in function must return false p.menuBtnSkip(this)) { skipUl = true; } if (!$this.next('button').length && !skipUl) { var $el = $this.find(p.insertToggleBtnAfter).first(); $el.addClass(css.menuHasUL); if ($el.length) { if ($el[0].parentNode.isSameNode(this)) { // make sure the <el> is a direct child of <li> $el.after((0, _cashDom["default"])('<button>').attr({ "class": css.menuBtnCss, type: 'button', 'aria-label': p.subMenuText + ' ' + $el.text().trim() })); } } } }); } }, { key: "checkIfEnabled", value: function checkIfEnabled() { var s = this; var resizeTimer; //basically if the navigational button is visible then //we can allow the click to open the navigation //this is so it doesn't clash with any other plugins //and allows for the control of this click via CSS (0, _cashDom["default"])(window).on("resize.".concat(EVENT_NAME, " ").concat(EVENT_NAME), function (e) { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { var $enableBtn = (0, _cashDom["default"])(s.params.enableBtn); s.allowClick = typeof s.params.bkptEnable === 'number' ? (0, _cashDom["default"])(window).width() <= s.params.bkptEnable : $enableBtn.length ? (0, _helpers.isVisible)($enableBtn[0]) : false; }, e.type === EVENT_NAME ? 0 : 200); }).trigger(EVENT_NAME); } }], [{ key: "remove", value: function remove(element, plugin) { (0, _cashDom["default"])(element).each(function () { var s = plugin || (0, _Store["default"])(this, DATA_NAME); (0, _cashDom["default"])(s.params.enableBtn).off("click.".concat(EVENT_NAME, " ").concat(EVENT_NAME)); (0, _cashDom["default"])(document).off("keydown.".concat(EVENT_NAME)); s.$element.off("click.".concat(EVENT_NAME, " ").concat(EVENT_NAME)).off("click.".concat(EVENT_NAME, " ").concat(EVENT_NAME)); (0, _cashDom["default"])(document.body).off("click.".concat(EVENT_NAME)); (0, _cashDom["default"])(window).off("resize.".concat(EVENT_NAME, " ").concat(EVENT_NAME)); (0, _Store["default"])(this, DATA_NAME, null); }); } }]); }(); function _menuToggle() { var s = this; var p = s.params; var css = s.cssList; var trappedFocus = null; var $enableBtn = (0, _cashDom["default"])(p.enableBtn); var $elemParent = s.$element.parent(); var doClose = s.menuOpened; var cssMenuState = "".concat(doClose ? css.menuClosing : css.menuOpening, " ").concat(css.menuToggling); _classPrivateFieldGet(_transition, s).call(s, function () { s.menuOpened = !doClose; s.$element.addClass(cssMenuState); (0, _cashDom["default"])(p.enableBtn).attr({ 'aria-expanded': !doClose + '' }); (0, _cashDom["default"])(p.outerElement).toggleClass(css.menuOuterOpen, !doClose).addClass(cssMenuState); if (doClose) { $elemParent.find(".".concat(css.menuOpen)).removeClass(css.menuOpen).find("[style]").css({ 'display': null }); trappedFocus && trappedFocus.remove(); } else { if (p.doTrapFocus) { trappedFocus = (0, _trapFocus["default"])(p.trapFocusElem || s.$element, { nameSpace: EVENT_NAME }); } } }, function () { (0, _cashDom["default"])(p.outerElement).removeClass(cssMenuState); s.$element.removeClass(cssMenuState); if (!doClose) { s.$element.addClass(css.menuOpen); } s.params[doClose ? 'afterClose' : 'afterOpen'](s.$element, (0, _cashDom["default"])(p.outerElement), $enableBtn); }, p.slideDuration); } function _navToggle() { var s = this; var css = s.cssList; s.$element.on("click.".concat(EVENT_NAME, " ").concat(EVENT_NAME), ".".concat(css.menuBtnCss.replace(/\s/g, '.')), function (e) { var p = s.params; var css = s.cssList; var $li = (0, _cashDom["default"])(this).closest(".".concat(css.menuHasUL)); var doClose = $li.hasClass(css.menuOpen); var $ul = $li.find('ul').first(); //exit because were in desktop view if (!s.allowClick) { return; } var cssMenuState = "".concat(css.menuToggling, " ").concat(doClose ? css.menuClosing : css.menuOpening); s.allowClick = doClose; _classPrivateFieldGet(_transition, s).call(s, function () { $li.addClass(cssMenuState).toggleClass(css.menuOpen, !doClose); $ul.addClass(cssMenuState).toggleClass(css.menuOpen, !doClose); if (p.animateHeight) { var openHeight = $ul.length ? $ul[0].scrollHeight : 0; var height = doClose ? 0 : openHeight; $ul.css({ height: doClose ? openHeight : 0 }); setTimeout(function () { $ul.css({ height: height }); }, 0); } }, function () { $li.removeClass(cssMenuState).toggleClass(css.menuOpen, !doClose); $ul.removeClass(cssMenuState).toggleClass(css.menuOpen, !doClose); $ul.css({ height: null }); if (doClose) { s.params.afterNavItemClose($li); } else { s.params.afterNavItemOpen($li); } s.allowClick = true; }, p.slideDuration); e.stopPropagation(); }); s.$element.on("click.".concat(EVENT_NAME, " ").concat(EVENT_NAME), 'a', function (e) { //prohibit closing if an anchor is clicked if (s.params.stopPropagation) { e.stopPropagation(); } }); } function _outsideClickClose() { var s = this; (0, _cashDom["default"])(document.body).on("click.".concat(EVENT_NAME), function (e) { if (s.params.outsideClickClose) { if (!s.menuOpened) { return; } //lets just exit then.. var menuClicked = e.target ? s.$element.has(e.target).length > 0 : false; //if the menu item is not clicked and its opened //the menu button shouldn't register because propogation is prevented to the body if (!menuClicked && s.menuOpened) { _assertClassBrand(_NavMobile_brand, s, _menuToggle).call(s); } } }); } _defineProperty(NavMobile, "defaults", DEFAULTS); _defineProperty(NavMobile, "version", VERSION); _defineProperty(NavMobile, "pluginName", DATA_NAME);