Skip to content
Snippets Groups Projects
Select Git revision
  • 2d53f54d96ca09e81df3f265da336d4d15a12f49
  • main default protected
  • v0.1.6
  • v0.1.5
  • v0.1.4
  • v0.1.3
  • v0.1.2
  • v0.1.1
  • v0.1.0
9 results

ProxyData.php

Blame
  • micromodal.es.js 15.73 KiB
    // see https://github.com/ghosh/Micromodal/pull/351
    
    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, descriptor.key, descriptor);
      }
    }
    
    function _createClass(Constructor, protoProps, staticProps) {
      if (protoProps) _defineProperties(Constructor.prototype, protoProps);
      if (staticProps) _defineProperties(Constructor, staticProps);
      return Constructor;
    }
    
    function _toConsumableArray(arr) {
      return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
    }
    
    function _arrayWithoutHoles(arr) {
      if (Array.isArray(arr)) return _arrayLikeToArray(arr);
    }
    
    function _iterableToArray(iter) {
      if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
    }
    
    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(n);
      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 _nonIterableSpread() {
      throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
    }
    
    var MicroModal = function () {
    
      var FOCUSABLE_ELEMENTS = ['a[href]', 'area[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];
    
      var Modal = /*#__PURE__*/function () {
        function Modal(_ref) {
          var targetModal = _ref.targetModal,
              _ref$triggers = _ref.triggers,
              triggers = _ref$triggers === void 0 ? [] : _ref$triggers,
              _ref$onShow = _ref.onShow,
              onShow = _ref$onShow === void 0 ? function () {} : _ref$onShow,
              _ref$onClose = _ref.onClose,
              onClose = _ref$onClose === void 0 ? function () {} : _ref$onClose,
              _ref$openTrigger = _ref.openTrigger,
              openTrigger = _ref$openTrigger === void 0 ? 'data-micromodal-trigger' : _ref$openTrigger,
              _ref$closeTrigger = _ref.closeTrigger,
              closeTrigger = _ref$closeTrigger === void 0 ? 'data-micromodal-close' : _ref$closeTrigger,
              _ref$openClass = _ref.openClass,
              openClass = _ref$openClass === void 0 ? 'is-open' : _ref$openClass,
              _ref$disableScroll = _ref.disableScroll,
              disableScroll = _ref$disableScroll === void 0 ? false : _ref$disableScroll,
              _ref$disableFocus = _ref.disableFocus,
              disableFocus = _ref$disableFocus === void 0 ? false : _ref$disableFocus,
              _ref$awaitCloseAnimat = _ref.awaitCloseAnimation,
              awaitCloseAnimation = _ref$awaitCloseAnimat === void 0 ? false : _ref$awaitCloseAnimat,
              _ref$awaitOpenAnimati = _ref.awaitOpenAnimation,
              awaitOpenAnimation = _ref$awaitOpenAnimati === void 0 ? false : _ref$awaitOpenAnimati,
              _ref$debugMode = _ref.debugMode,
              debugMode = _ref$debugMode === void 0 ? false : _ref$debugMode;
    
          _classCallCheck(this, Modal);
    
          // Save a reference of the modal
          this.modal = this.modal = typeof targetModal === "string" ? document.getElementById(targetModal) : targetModal; // Save a reference to the passed config
    
          this.config = {
            debugMode: debugMode,
            disableScroll: disableScroll,
            openTrigger: openTrigger,
            closeTrigger: closeTrigger,
            openClass: openClass,
            onShow: onShow,
            onClose: onClose,
            awaitCloseAnimation: awaitCloseAnimation,
            awaitOpenAnimation: awaitOpenAnimation,
            disableFocus: disableFocus
          }; // Register click events only if pre binding eventListeners
    
          if (triggers.length > 0) this.registerTriggers.apply(this, _toConsumableArray(triggers)); // pre bind functions for event listeners
    
          this.onClick = this.onClick.bind(this);
          this.onKeydown = this.onKeydown.bind(this);
        }
        /**
         * Loops through all openTriggers and binds click event
         * @param  {array} triggers [Array of node elements]
         * @return {void}
         */
    
    
        _createClass(Modal, [{
          key: "registerTriggers",
          value: function registerTriggers() {
            var _this = this;
    
            for (var _len = arguments.length, triggers = new Array(_len), _key = 0; _key < _len; _key++) {
              triggers[_key] = arguments[_key];
            }
    
            triggers.filter(Boolean).forEach(function (trigger) {
              trigger.addEventListener('click', function (event) {
                return _this.showModal(event);
              });
            });
          }
        }, {
          key: "showModal",
          value: function showModal() {
            var _this2 = this;
    
            var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
            this.activeElement = document.activeElement;
            this.modal.setAttribute('aria-hidden', 'false');
            this.modal.classList.add(this.config.openClass);
            this.scrollBehaviour('disable');
            this.addEventListeners();
    
            if (this.config.awaitOpenAnimation) {
              var handler = function handler() {
                _this2.modal.removeEventListener('animationend', handler, false);
    
                _this2.setFocusToFirstNode();
              };
    
              this.modal.addEventListener('animationend', handler, false);
            } else {
              this.setFocusToFirstNode();
            }
    
            this.config.onShow(this.modal, this.activeElement, event);
          }
        }, {
          key: "closeModal",
          value: function closeModal() {
            var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
            var modal = this.modal;
            this.modal.setAttribute('aria-hidden', 'true');
            this.removeEventListeners();
            this.scrollBehaviour('enable');
    
            if (this.activeElement && this.activeElement.focus) {
              this.activeElement.focus();
            }
    
            this.config.onClose(this.modal, this.activeElement, event);
    
            if (this.config.awaitCloseAnimation) {
              var openClass = this.config.openClass; // <- old school ftw
    
              this.modal.addEventListener('animationend', function handler() {
                modal.classList.remove(openClass);
                modal.removeEventListener('animationend', handler, false);
              }, false);
            } else {
              modal.classList.remove(this.config.openClass);
            }
          }
        }, {
          key: "closeModalById",
          value: function closeModalById(targetModal) {
            // added support to pass on an element or an id -> for webcomponents
            if (targetModal instanceof HTMLElement) {
              this.modal = targetModal;
            }
            else {
              this.model = document.getElementById(targetModal);
            }
            if (this.modal) this.closeModal();
          }
        }, {
          key: "scrollBehaviour",
          value: function scrollBehaviour(toggle) {
            if (!this.config.disableScroll) return;
            var body = document.querySelector('body');
    
            switch (toggle) {
              case 'enable':
                Object.assign(body.style, {
                  overflow: ''
                });
                break;
    
              case 'disable':
                Object.assign(body.style, {
                  overflow: 'hidden'
                });
                break;
            }
          }
        }, {
          key: "addEventListeners",
          value: function addEventListeners() {
            this.modal.addEventListener('touchstart', this.onClick);
            this.modal.addEventListener('click', this.onClick);
            document.addEventListener('keydown', this.onKeydown);
          }
        }, {
          key: "removeEventListeners",
          value: function removeEventListeners() {
            this.modal.removeEventListener('touchstart', this.onClick);
            this.modal.removeEventListener('click', this.onClick);
            document.removeEventListener('keydown', this.onKeydown);
          }
        }, {
          key: "onClick",
          value: function onClick(event) {
            if (event.target.hasAttribute(this.config.closeTrigger)) {
              this.closeModal(event);
            }
          }
        }, {
          key: "onKeydown",
          value: function onKeydown(event) {
            if (event.keyCode === 27) this.closeModal(event); // esc
    
            if (event.keyCode === 9) this.retainFocus(event); // tab
          }
        }, {
          key: "getFocusableNodes",
          value: function getFocusableNodes() {
            var nodes = this.modal.querySelectorAll(FOCUSABLE_ELEMENTS);
            return Array.apply(void 0, _toConsumableArray(nodes));
          }
          /**
           * Tries to set focus on a node which is not a close trigger
           * if no other nodes exist then focuses on first close trigger
           */
    
        }, {
          key: "setFocusToFirstNode",
          value: function setFocusToFirstNode() {
            var _this3 = this;
    
            if (this.config.disableFocus) return;
            var focusableNodes = this.getFocusableNodes(); // no focusable nodes
    
            if (focusableNodes.length === 0) return; // remove nodes on whose click, the modal closes
            // could not think of a better name :(
    
            var nodesWhichAreNotCloseTargets = focusableNodes.filter(function (node) {
              return !node.hasAttribute(_this3.config.closeTrigger);
            });
            if (nodesWhichAreNotCloseTargets.length > 0) nodesWhichAreNotCloseTargets[0].focus();
            if (nodesWhichAreNotCloseTargets.length === 0) focusableNodes[0].focus();
          }
        }, {
          key: "retainFocus",
          value: function retainFocus(event) {
            var focusableNodes = this.getFocusableNodes(); // no focusable nodes
    
            if (focusableNodes.length === 0) return;
            /**
             * Filters nodes which are hidden to prevent
             * focus leak outside modal
             */
    
            focusableNodes = focusableNodes.filter(function (node) {
              return node.offsetParent !== null;
            }); // if disableFocus is true
    
            if (!this.modal.contains(document.activeElement)) {
              focusableNodes[0].focus();
            } else {
              var focusedItemIndex = focusableNodes.indexOf(document.activeElement);
    
              if (event.shiftKey && focusedItemIndex === 0) {
                focusableNodes[focusableNodes.length - 1].focus();
                event.preventDefault();
              }
    
              if (!event.shiftKey && focusableNodes.length > 0 && focusedItemIndex === focusableNodes.length - 1) {
                focusableNodes[0].focus();
                event.preventDefault();
              }
            }
          }
        }]);
    
        return Modal;
      }();
      /**
       * Modal prototype ends.
       * Here on code is responsible for detecting and
       * auto binding event handlers on modal triggers
       */
      // Keep a reference to the opened modal
    
    
      var activeModal = null;
      /**
       * Generates an associative array of modals and it's
       * respective triggers
       * @param  {array} triggers     An array of all triggers
       * @param  {string} triggerAttr The data-attribute which triggers the module
       * @return {array}
       */
    
      var generateTriggerMap = function generateTriggerMap(triggers, triggerAttr) {
        var triggerMap = [];
        triggers.forEach(function (trigger) {
          var targetModal = trigger.attributes[triggerAttr].value;
          if (triggerMap[targetModal] === undefined) triggerMap[targetModal] = [];
          triggerMap[targetModal].push(trigger);
        });
        return triggerMap;
      };
      /**
       * Validates whether a modal of the given id exists
       * in the DOM
       * @param  {number} id  The id of the modal
       * @return {boolean}
       */
    
    
      var validateModalPresence = function validateModalPresence(id) {
        if (!document.getElementById(id)) {
          console.warn("MicroModal: \u2757Seems like you have missed %c'".concat(id, "'"), 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'ID somewhere in your code. Refer example below to resolve it.');
          console.warn("%cExample:", 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', "<div class=\"modal\" id=\"".concat(id, "\"></div>"));
          return false;
        }
      };
      /**
       * Validates if there are modal triggers present
       * in the DOM
       * @param  {array} triggers An array of data-triggers
       * @return {boolean}
       */
    
    
      var validateTriggerPresence = function validateTriggerPresence(triggers) {
        if (triggers.length <= 0) {
          console.warn("MicroModal: \u2757Please specify at least one %c'micromodal-trigger'", 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'data attribute.');
          console.warn("%cExample:", 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', "<a href=\"#\" data-micromodal-trigger=\"my-modal\"></a>");
          return false;
        }
      };
      /**
       * Checks if triggers and their corresponding modals
       * are present in the DOM
       * @param  {array} triggers   Array of DOM nodes which have data-triggers
       * @param  {array} triggerMap Associative array of modals and their triggers
       * @return {boolean}
       */
    
    
      var validateArgs = function validateArgs(triggers, triggerMap) {
        validateTriggerPresence(triggers);
        if (!triggerMap) return true;
    
        for (var id in triggerMap) {
          validateModalPresence(id);
        }
    
        return true;
      };
      /**
       * Binds click handlers to all modal triggers
       * @param  {object} config [description]
       * @return void
       */
    
    
      var init = function init(config) {
        // Create an config object with default openTrigger
        var options = Object.assign({}, {
          openTrigger: 'data-micromodal-trigger'
        }, config); // Collects all the nodes with the trigger
    
        var triggers = _toConsumableArray(document.querySelectorAll("[".concat(options.openTrigger, "]"))); // Makes a mappings of modals with their trigger nodes
    
    
        var triggerMap = generateTriggerMap(triggers, options.openTrigger); // Checks if modals and triggers exist in dom
    
        if (options.debugMode === true && validateArgs(triggers, triggerMap) === false) return; // For every target modal creates a new instance
    
        for (var key in triggerMap) {
          var value = triggerMap[key];
          options.targetModal = key;
          options.triggers = _toConsumableArray(value);
          activeModal = new Modal(options); // eslint-disable-line no-new
        }
      };
      /**
       * Shows a particular modal
       * @param  {string} targetModal [The id of the modal to display]
       * @param  {object} config [The configuration object to pass]
       * @return {void}
       */
    
    
      var show = function show(targetModal, config) {
        var options = config || {};
        options.targetModal = targetModal; // Checks if modals and triggers exist in dom
    
        if (options.debugMode === true && validateModalPresence(targetModal) === false) return; // clear events in case previous modal wasn't close
    
        if (activeModal) activeModal.removeEventListeners(); // stores reference to active modal
    
        activeModal = new Modal(options); // eslint-disable-line no-new
    
        activeModal.showModal();
      };
      /**
       * Closes the active modal
       * @param  {string} targetModal [The id of the modal to close]
       * @return {void}
       */
    
    
      var close = function close(targetModal) {
        targetModal ? activeModal.closeModalById(targetModal) : activeModal.closeModal();
      };
    
      return {
        init: init,
        show: show,
        close: close
      };
    }();
    window.MicroModal = MicroModal;
    
    export default MicroModal;