UNPKG

modal-vanilla

Version:

Vanilla JS Modal compatible with Bootstrap

738 lines (636 loc) 23.7 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1).default; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = 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, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /** * Vanilla JS Modal compatible with Bootstrap * modal-vanilla 0.13.0 <https://github.com/KaneCohen/modal-vanilla> * Copyright 2020 Kane Cohen <https://github.com/KaneCohen> * Available under BSD-3-Clause license */ var _events = __webpack_require__(2); var _events2 = _interopRequireDefault(_events); 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 _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _factory = null; var _defaults = Object.freeze({ el: null, // Existing DOM element that will be 'Modal-ized'. animate: true, // Show Modal using animation. animateClass: 'fade', // animateInClass: 'show', // appendTo: 'body', // DOM element to which constructed Modal will be appended. backdrop: true, // Boolean or 'static', Show Modal backdrop blocking content. keyboard: true, // Close modal on esc key. title: false, // Content of the title in the constructed dialog. header: true, // Show header content. content: false, // Either string or an HTML element. footer: true, // Footer content. By default will use buttons. buttons: null, // headerClose: true, // Show close button in the header. construct: false, // Creates new HTML with a given content. transition: 300, // backdropTransition: 150 // }); var _buttons = deepFreeze({ dialog: [{ text: 'Cancel', value: false, attr: { 'class': 'btn btn-default', 'data-dismiss': 'modal' } }, { text: 'OK', value: true, attr: { 'class': 'btn btn-primary', 'data-dismiss': 'modal' } }], alert: [{ text: 'OK', attr: { 'class': 'btn btn-primary', 'data-dismiss': 'modal' } }], confirm: [{ text: 'Cancel', value: false, attr: { 'class': 'btn btn-default', 'data-dismiss': 'modal' } }, { text: 'OK', value: true, attr: { 'class': 'btn btn-primary', 'data-dismiss': 'modal' } }] }); var _templates = { container: '<div class="modal"></div>', dialog: '<div class="modal-dialog"></div>', content: '<div class="modal-content"></div>', header: '<div class="modal-header"></div>', headerClose: '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>', body: '<div class="modal-body"></div>', footer: '<div class="modal-footer"></div>', backdrop: '<div class="modal-backdrop"></div>' }; function deepFreeze(obj) { for (var k in obj) { if (Array.isArray(obj[k])) { obj[k].forEach(function (v) { deepFreeze(v); }); } else if (obj[k] !== null && _typeof(obj[k]) === 'object') { Object.freeze(obj[k]); } } return Object.freeze(obj); } function guid() { return ((1 + Math.random()) * 0x10000 | 0).toString(16) + ((1 + Math.random()) * 0x10000 | 0).toString(16); } function data(el, prop, value) { var prefix = 'data'; var elData = el[prefix] || {}; if (typeof value === 'undefined') { if (el[prefix] && el[prefix][prop]) { return el[prefix][prop]; } else { var dataAttr = el.getAttribute(prefix + '-' + prop); if (typeof dataAttr !== 'undefined') { return dataAttr; } return null; } } else { elData[prop] = value; el[prefix] = elData; return el; } } function build(html, all) { if (html.nodeName) return html; html = html.replace(/(\t|\n$)/g, ''); if (!_factory) { _factory = document.createElement('div'); } _factory.innerHTML = ''; _factory.innerHTML = html; if (all === true) { return _factory.childNodes; } else { return _factory.childNodes[0]; } } function calcScrollbarWidth() { var inner = void 0; var width = void 0; var outerWidth = void 0; var outer = document.createElement('div'); _extends(outer.style, { visibility: 'hidden', width: '100px' }); document.body.appendChild(outer); outerWidth = outer.offsetWidth; outer.style.overflow = 'scroll'; inner = document.createElement('div'); inner.style.width = '100%'; outer.appendChild(inner); width = outerWidth - inner.offsetWidth; document.body.removeChild(outer); return width; } function getPath(node) { var nodes = [node]; while (node.parentNode) { node = node.parentNode; nodes.push(node); } return nodes; } var Modal = function (_EventEmitter) { _inherits(Modal, _EventEmitter); _createClass(Modal, null, [{ key: 'alert', value: function alert(message) { var _options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var options = _extends({}, _defaults, { title: message, content: false, construct: true, headerClose: false, buttons: Modal.buttons.alert }, _options); return new Modal(options); } }, { key: 'confirm', value: function confirm(question) { var _options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var options = _extends({}, _defaults, { title: question, content: false, construct: true, headerClose: false, buttons: Modal.buttons.confirm }, _options); return new Modal(options); } }, { key: 'templates', set: function set(templates) { this._baseTemplates = templates; }, get: function get() { return _extends({}, _templates, Modal._baseTemplates || {}); } }, { key: 'buttons', set: function set(buttons) { this._baseButtons = buttons; }, get: function get() { return _extends({}, _buttons, Modal._baseButtons || {}); } }, { key: 'options', set: function set(options) { this._baseOptions = options; }, get: function get() { return _extends({}, _defaults, Modal._baseOptions || {}); } }, { key: 'version', get: function get() { return '0.13.0'; } }]); function Modal() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, Modal); var _this = _possibleConstructorReturn(this, (Modal.__proto__ || Object.getPrototypeOf(Modal)).call(this)); _this.id = guid(); _this.el = null; _this._html = {}; _this._events = {}; _this._visible = false; _this._pointerInContent = false; _this._options = _extends({}, Modal.options, options); _this._templates = _extends({}, Modal.templates, options.templates || {}); _this._html.appendTo = document.querySelector(_this._options.appendTo); _this._scrollbarWidth = calcScrollbarWidth(); if (_this._options.buttons === null) { _this._options.buttons = Modal.buttons.dialog; } if (_this._options.el) { var el = _this._options.el; if (typeof _this._options.el == 'string') { el = document.querySelector(_this._options.el); if (!el) { throw new Error('Selector: DOM Element ' + _this._options.el + ' not found.'); } } data(el, 'modal', _this); _this.el = el; } else { _this._options.construct = true; } if (_this._options.construct) { _this._render(); } else { _this._mapDom(); } return _this; } _createClass(Modal, [{ key: '_render', value: function _render() { var html = this._html; var o = this._options; var t = this._templates; var animate = o.animate ? o.animateClass : false; html.container = build(t.container); html.dialog = build(t.dialog); html.content = build(t.content); html.header = build(t.header); html.headerClose = build(t.headerClose); html.body = build(t.body); html.footer = build(t.footer); if (animate) html.container.classList.add(animate); this._setHeader(); this._setContent(); this._setFooter(); this.el = html.container; html.dialog.appendChild(html.content); html.container.appendChild(html.dialog); return this; } }, { key: '_mapDom', value: function _mapDom() { var html = this._html; var o = this._options; if (this.el.classList.contains(o.animateClass)) { o.animate = true; } html.container = this.el; html.dialog = this.el.querySelector('.modal-dialog'); html.content = this.el.querySelector('.modal-content'); html.header = this.el.querySelector('.modal-header'); html.headerClose = this.el.querySelector('.modal-header .close'); html.body = this.el.querySelector('.modal-body'); html.footer = this.el.querySelector('.modal-footer'); this._setHeader(); this._setContent(); this._setFooter(); return this; } }, { key: '_setHeader', value: function _setHeader() { var html = this._html; var o = this._options; if (o.header && html.header) { if (o.title.nodeName) { html.header.innerHTML = o.title.outerHTML; } else if (typeof o.title === 'string') { html.header.innerHTML = '<h4 class="modal-title">' + o.title + '</h4>'; } // Add header close button only to constructed modals. if (this.el === null && html.headerClose && o.headerClose) { html.header.appendChild(html.headerClose); } if (o.construct) { html.content.appendChild(html.header); } } } }, { key: '_setContent', value: function _setContent() { var html = this._html; var o = this._options; if (o.content && html.body) { if (typeof o.content === 'string') { html.body.innerHTML = o.content; } else { html.body.innerHTML = o.content.outerHTML; } if (o.construct) { html.content.appendChild(html.body); } } } }, { key: '_setFooter', value: function _setFooter() { var html = this._html; var o = this._options; if (o.footer && html.footer) { if (o.footer.nodeName) { html.footer.innerHTML = o.footer.outerHTML; } else if (typeof o.footer === 'string') { html.footer.innerHTML = o.footer; } else if (!html.footer.children.length) { o.buttons.forEach(function (button) { var el = document.createElement('button'); data(el, 'button', button); el.innerHTML = button.text; el.setAttribute('type', 'button'); for (var j in button.attr) { el.setAttribute(j, button.attr[j]); } html.footer.appendChild(el); }); } if (o.construct) { html.content.appendChild(html.footer); } } } }, { key: '_setEvents', value: function _setEvents() { var o = this._options; var html = this._html; this._events.keydownHandler = this._handleKeydownEvent.bind(this); document.body.addEventListener('keydown', this._events.keydownHandler); this._events.mousedownHandler = this._handleMousedownEvent.bind(this); html.container.addEventListener('mousedown', this._events.mousedownHandler); this._events.clickHandler = this._handleClickEvent.bind(this); html.container.addEventListener('click', this._events.clickHandler); this._events.resizeHandler = this._handleResizeEvent.bind(this); window.addEventListener('resize', this._events.resizeHandler); } }, { key: '_handleMousedownEvent', value: function _handleMousedownEvent(e) { var _this2 = this; this._pointerInContent = false; var path = getPath(e.target); path.every(function (node) { if (node.classList && node.classList.contains('modal-content')) { _this2._pointerInContent = true; return false; } return true; }); } }, { key: '_handleClickEvent', value: function _handleClickEvent(e) { var _this3 = this; var path = getPath(e.target); path.every(function (node) { if (node.tagName === 'HTML') { return false; } if (_this3._options.backdrop !== true && node.classList.contains('modal')) { return false; } if (node.classList.contains('modal-content')) { return false; } if (node.getAttribute('data-dismiss') === 'modal') { _this3.emit('dismiss', _this3, e, data(e.target, 'button')); _this3.hide(); return false; } if (!_this3._pointerInContent && node.classList.contains('modal')) { _this3.emit('dismiss', _this3, e, null); _this3.hide(); return false; } return true; }); this._pointerInContent = false; } }, { key: '_handleKeydownEvent', value: function _handleKeydownEvent(e) { if (e.which === 27 && this._options.keyboard) { this.emit('dismiss', this, e, null); this.hide(); } } }, { key: '_handleResizeEvent', value: function _handleResizeEvent(e) { this._resize(); } }, { key: 'show', value: function show() { var _this4 = this; var o = this._options; var html = this._html; this.emit('show', this); this._checkScrollbar(); this._setScrollbar(); document.body.classList.add('modal-open'); if (o.construct) { html.appendTo.appendChild(html.container); } html.container.style.display = 'block'; html.container.scrollTop = 0; if (o.backdrop !== false) { this.once('showBackdrop', function () { _this4._setEvents(); if (o.animate) html.container.offsetWidth; // Force reflow html.container.classList.add(o.animateInClass); setTimeout(function () { _this4._visible = true; _this4.emit('shown', _this4); }, o.transition); }); this._backdrop(); } else { this._setEvents(); if (o.animate) html.container.offsetWidth; // Force reflow html.container.classList.add(o.animateInClass); setTimeout(function () { _this4._visible = true; _this4.emit('shown', _this4); }, o.transition); } this._resize(); return this; } }, { key: 'toggle', value: function toggle() { if (this._visible) { this.hide(); } else { this.show(); } } }, { key: '_resize', value: function _resize() { var modalIsOverflowing = this._html.container.scrollHeight > document.documentElement.clientHeight; this._html.container.style.paddingLeft = !this.bodyIsOverflowing && modalIsOverflowing ? this._scrollbarWidth + 'px' : ''; this._html.container.style.paddingRight = this.bodyIsOverflowing && !modalIsOverflowing ? this._scrollbarWidth + 'px' : ''; } }, { key: '_backdrop', value: function _backdrop() { var _this5 = this; var html = this._html; var t = this._templates; var o = this._options; var animate = o.animate ? o.animateClass : false; html.backdrop = build(t.backdrop); if (animate) html.backdrop.classList.add(animate); html.appendTo.appendChild(html.backdrop); if (animate) html.backdrop.offsetWidth; html.backdrop.classList.add(o.animateInClass); setTimeout(function () { _this5.emit('showBackdrop', _this5); }, this._options.backdropTransition); } }, { key: 'hide', value: function hide() { var _this6 = this; var html = this._html; var o = this._options; var contCList = html.container.classList; this.emit('hide', this); contCList.remove(o.animateInClass); if (o.backdrop) { var backCList = html.backdrop.classList; backCList.remove(o.animateInClass); } this._removeEvents(); setTimeout(function () { document.body.classList.remove('modal-open'); document.body.style.paddingRight = _this6.originalBodyPad; }, o.backdropTransition); setTimeout(function () { if (o.backdrop) { html.backdrop.parentNode.removeChild(html.backdrop); } html.container.style.display = 'none'; if (o.construct) { html.container.parentNode.removeChild(html.container); } _this6._visible = false; _this6.emit('hidden', _this6); }, o.transition); return this; } }, { key: '_removeEvents', value: function _removeEvents() { if (this._events.keydownHandler) { document.body.removeEventListener('keydown', this._events.keydownHandler); } this._html.container.removeEventListener('mousedown', this._events.mousedownHandler); this._html.container.removeEventListener('click', this._events.clickHandler); window.removeEventListener('resize', this._events.resizeHandler); } }, { key: '_checkScrollbar', value: function _checkScrollbar() { this.bodyIsOverflowing = document.body.clientWidth < window.innerWidth; } }, { key: '_setScrollbar', value: function _setScrollbar() { this.originalBodyPad = document.body.style.paddingRight || ''; if (this.bodyIsOverflowing) { var basePadding = parseInt(this.originalBodyPad || 0, 10); document.body.style.paddingRight = basePadding + this._scrollbarWidth + 'px'; } } }]); return Modal; }(_events2.default); exports.default = Modal; /***/ }), /* 2 */ /***/ (function(module, exports) { module.exports = require("events"); /***/ }) /******/ ]);