UNPKG

muicss

Version:

Lightweight CSS framework based on Google's Material Design guidelines

205 lines (150 loc) 4.33 kB
/** * MUI CSS/JS overlay module * @module overlay */ 'use strict'; var util = require('./lib/util'), jqLite = require('./lib/jqLite'), overlayId = 'mui-overlay', bodyClass = 'mui--overflow-hidden', iosRegex = /(iPad|iPhone|iPod)/g, activeElement; /** * Turn overlay on/off. * @param {string} action - Turn overlay "on"/"off". * @param {object} [options] * @config {boolean} [keyboard] - If true, close when escape key is pressed. * @config {boolean} [static] - If false, close when backdrop is clicked. * @config {Function} [onclose] - Callback function to execute on close * @param {Element} [childElement] - Child element to add to overlay. */ function overlayFn(action) { var overlayEl; if (action === 'on') { // extract arguments var arg, options, childElement; // pull options and childElement from arguments for (var i=arguments.length - 1; i > 0; i--) { arg = arguments[i]; if (jqLite.type(arg) === 'object') options = arg; if (arg instanceof Element && arg.nodeType === 1) childElement = arg; } // option defaults options = options || {}; if (options.keyboard === undefined) options.keyboard = true; if (options.static === undefined) options.static = false; // execute method overlayEl = overlayOn(options, childElement); } else if (action === 'off') { overlayEl = overlayOff(); } else { // raise error util.raiseError("Expecting 'on' or 'off'"); } return overlayEl; } /** * Turn on overlay. * @param {object} options - Overlay options. * @param {Element} childElement - The child element. */ function overlayOn(options, childElement) { var doc = document, bodyEl = doc.body, overlayEl = doc.getElementById(overlayId); // cache activeElement if (doc.activeElement) activeElement = doc.activeElement; // add overlay util.enableScrollLock(); if (!overlayEl) { // create overlayEl overlayEl = doc.createElement('div'); overlayEl.setAttribute('id', overlayId); overlayEl.setAttribute('tabindex', '-1'); // add child element if (childElement) overlayEl.appendChild(childElement); bodyEl.appendChild(overlayEl); } else { // remove existing children while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild); // add child element if (childElement) overlayEl.appendChild(childElement); } // iOS bugfix if (iosRegex.test(navigator.userAgent)) { jqLite.css(overlayEl, 'cursor', 'pointer'); } // handle options if (options.keyboard) addKeyupHandler(); else removeKeyupHandler(); if (options.static) removeClickHandler(overlayEl); else addClickHandler(overlayEl); // attach options overlayEl.muiOptions = options; // focus overlay element overlayEl.focus(); return overlayEl; } /** * Turn off overlay. */ function overlayOff() { var overlayEl = document.getElementById(overlayId), callbackFn; if (overlayEl) { // remove children while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild); // remove overlay element overlayEl.parentNode.removeChild(overlayEl); // callback reference callbackFn = overlayEl.muiOptions.onclose; // remove click handler removeClickHandler(overlayEl); } util.disableScrollLock(); // remove keyup handler removeKeyupHandler(); // return focus to activeElement if (activeElement) activeElement.focus(); // execute callback if (callbackFn) callbackFn(); return overlayEl; } /** * Add keyup handler. */ function addKeyupHandler() { jqLite.on(document, 'keyup', onKeyup); } /** * Remove keyup handler. */ function removeKeyupHandler() { jqLite.off(document, 'keyup', onKeyup); } /** * Teardown overlay when escape key is pressed. */ function onKeyup(ev) { if (ev.keyCode === 27) overlayOff(); } /** * Add click handler. */ function addClickHandler(overlayEl) { jqLite.on(overlayEl, 'click', onClick); } /** * Remove click handler. */ function removeClickHandler(overlayEl) { jqLite.off(overlayEl, 'click', onClick); } /** * Teardown overlay when backdrop is clicked. */ function onClick(ev) { if (ev.target.id === overlayId) overlayOff(); } /** Define module API */ module.exports = overlayFn;