@r00t80y/primary-navigation
Version:
An overlay Menu with a collection of effects and styles using CSS transitions.
326 lines (259 loc) • 9.41 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('custom-event-polyfill'), require('element-closest-polyfill'), require('throttle-debounce')) :
typeof define === 'function' && define.amd ? define(['exports', 'custom-event-polyfill', 'element-closest-polyfill', 'throttle-debounce'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.PrimaryNavigation = {}, null, null, global.throttleDebounce));
})(this, (function (exports, customEventPolyfill, elementClosestPolyfill, throttleDebounce) { 'use strict';
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
enumerableOnly && (symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
})), keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = null != arguments[i] ? arguments[i] : {};
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
_defineProperty(target, key, source[key]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* @author r00t80y<https://github.com/R00T80Y>
* @file Utils used in plugin
* @since 09-02-2022
* @updated 10-04-2022
*/
var Utils = {
// Data Type
type: function type(data) {
return Object.prototype.toString.call(data).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
},
isFunction: function isFunction(func) {
return Utils.type(func) === 'function';
},
uniqId: function uniqId() {
var date = Date.now().toString(36);
var number = Math.random().toString(36).substring(2);
return date + number;
}
};
var defaultOptions = {
breakpointClose: 756,
overflowHidden: true,
stateControlSelector: '.navigation__state-control',
panelSelector: '.navigation__panel',
buttonSelector: '.navigation__button.navigation__button--burger',
focus: false,
init: false,
open: false,
close: false
};
function Plugin($rootElement, pluginOptions) {
var $checkbox = $rootElement.querySelector(pluginOptions.stateControlSelector);
var $button = $rootElement.querySelector(pluginOptions.buttonSelector);
var $labelsList = $rootElement.querySelectorAll("label[for=\"".concat($checkbox.id, "\"]"));
var $panel = $rootElement.querySelector(pluginOptions.panelSelector);
var uniqName = function () {
var name;
do {
name = "primary-navigation-".concat(Utils.uniqId());
} while (document.getElementById(name));
return name;
}();
$rootElement.setAttribute('data-plugin-name-uniq', uniqName);
$rootElement.setAttribute('data-plugin-name', 'primary-navigation'); // Menu opened or not
function isOpen() {
return !!$checkbox.checked;
} // Open menu
function _open() {
if (!isOpen()) {
$checkbox.checked = true;
$checkbox.dispatchEvent(new CustomEvent('change'));
}
} // Close menu
function _close() {
if (isOpen()) {
$checkbox.checked = false;
$checkbox.dispatchEvent(new CustomEvent('change'));
}
} // Close All opened menus
function closeAll() {
var $menuList = document.querySelectorAll('[data-plugin-name="primary-navigation"]');
if ($menuList) {
for (var i = 0, l = $menuList.length; i < l; i += 1) {
var $menuCheckbox = $menuList[i].querySelector(pluginOptions.stateControlSelector);
if ($menuCheckbox) {
var isChecked = !!$menuCheckbox.checked;
if (isChecked === true) {
$menuCheckbox.checked = false;
$menuCheckbox.dispatchEvent(new CustomEvent('change'));
}
}
}
}
}
function onKeydown(e) {
e.stopPropagation(); // Enter, Space
if (e.keyCode === 32 || e.keyCode === 13) {
e.preventDefault();
if (isOpen()) {
_close();
} else {
closeAll();
_open();
} // Esc
} else if (e.keyCode === 27) {
e.preventDefault();
closeAll();
}
}
function onKeydownEsc(e) {
// Esc
if (e.keyCode === 27) {
closeAll();
}
} // Close the menu by clicking on the page
function onClickDocument(event) {
// If the menu is closed, then exit the function
if (!isOpen()) return; // Ignore click inside the menu
if (event.target.closest("[data-plugin-name-uniq=\"".concat(uniqName, "\"]"))) {
return;
} // Close menu
closeAll();
}
function onStateModify(event) {
// Is the menu open or not?
if (event.target.checked) {
if (pluginOptions.overflowHidden) {
document.querySelector('html').style.overflow = 'hidden';
}
for (var i = 0, l = $labelsList.length; i < l; i += 1) {
$labelsList[i].setAttribute('aria-expanded', 'true');
}
$panel.setAttribute('data-visible', 'true');
if (pluginOptions.focus) {
setTimeout(function () {
$panel.querySelector('a').focus();
}, 400);
}
if (Utils.isFunction(pluginOptions.open)) {
pluginOptions.open();
}
} else {
if (pluginOptions.overflowHidden) {
document.querySelector('html').style.overflow = 'auto';
}
for (var _i = 0, _l = $labelsList.length; _i < _l; _i += 1) {
$labelsList[_i].setAttribute('aria-expanded', 'false');
}
$panel.setAttribute('data-visible', 'false');
if (pluginOptions.focus) {
$button.focus();
}
if (Utils.isFunction(pluginOptions.close)) {
pluginOptions.close();
}
}
}
var onResizeWindow = throttleDebounce.throttle(200, function () {
// Close the menu if the window is resized
if (isOpen()) {
if (document.body.clientWidth >= pluginOptions.breakpointClose) {
_close();
}
}
});
function createEvents() {
if (pluginOptions.breakpointClose !== false) {
window.addEventListener('resize', onResizeWindow);
}
$checkbox.addEventListener('change', onStateModify);
for (var i = 0, l = $labelsList.length; i < l; i += 1) {
$labelsList[i].addEventListener('keydown', onKeydown);
}
document.addEventListener('keydown', onKeydownEsc);
document.addEventListener('click', onClickDocument, true);
}
function removeEvents() {
window.removeEventListener('resize', onResizeWindow);
$checkbox.removeEventListener('change', onStateModify);
for (var i = 0, l = $labelsList.length; i < l; i += 1) {
$labelsList[i].removeEventListener('keydown', onKeydown);
}
document.removeEventListener('keydown', onKeydownEsc);
document.removeEventListener('click', onClickDocument);
}
function destroy() {
removeEvents();
} // When the page loads, close the menu
_close();
createEvents();
if (Utils.isFunction(pluginOptions.init)) {
pluginOptions.init();
}
return {
get options() {
return pluginOptions;
},
isOpen: isOpen,
open: function open() {
_open();
},
close: function close() {
_close();
},
destroy: destroy
};
}
function createPrimaryNavigation(element, customOptions) {
var nodeList = [];
var instances = [];
return function init() {
if (element && element instanceof HTMLElement) {
nodeList.push(element);
} else if (element && typeof element === 'string') {
var elementsList = document.querySelectorAll(element);
for (var i = 0, l = elementsList.length; i < l; i += 1) {
if (elementsList[i] instanceof HTMLElement) {
nodeList.push(elementsList[i]);
}
}
} else if (element && element.length) {
for (var _i2 = 0, _l2 = element.length; _i2 < _l2; _i2 += 1) {
if (element[_i2] instanceof HTMLElement) {
nodeList.push(element[_i2]);
}
}
}
for (var _i3 = 0, _l3 = nodeList.length; _i3 < _l3; _i3 += 1) {
instances.push(new Plugin(nodeList[_i3], _objectSpread2(_objectSpread2(_objectSpread2({}, defaultOptions), customOptions), {}, {
name: 'ToggleButton'
})));
}
return instances;
}();
}
exports.createPrimaryNavigation = createPrimaryNavigation;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=index.js.map