cssAudio - ActiveCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - Activehtmloctocatspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <main id=content>

  <h1><a href="http://websemantics.uk/articles/accessible-modal-dialog-popup-iframe/" target=_blank>Accessible modal dialog pop-up iframe (v3)</a></h1>

  <nav>
    <a href="http://codepen.io/2kool2/pen/KzXYmV" title="[new window]" target=_blank>Version 1</a>
    <a href="http://codepen.io/2kool2/pen/YqePqQ" title="[new window]" target=_blank>Version 2</a>
    <a href="http://codepen.io/2kool2/pen/dXazyK" title="[new window]" target=_blank>Version 3</a>
    <a href="http://codepen.io/2kool2/pen/LkaXay" title="[new window]" target=_blank>Version 4</a>
  </nav>

  <p>Vanilla JavaScript, no dependencies (but see <a href="http://codepen.io/2kool2/pen/LkaXay" title="[new window]" target=_blank>version 4</a>).</p>

  <p>Uses an anchor to launch a modal pop-up which is then populated with an <code>iframe</code> like so:</p>
  <p>
    <a class=lnk_modal-open href="https://www.google.com/maps/place/147+Wardour+St,+Soho,+London+W1F+8WD,+UK/@51.514197,-0.134724,16z/data=!4m5!3m4!1s0x487604d357825039:0xf0c170d8fa918a9b!8m2!3d51.5141967!4d-0.1347244?hl=en-GB" data-modal="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d4175.8218601402605!2d-0.1390235133502716!3d51.51397674271494!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x487604d357825039%3A0xf0c170d8fa918a9b!2s147+Wardour+St%2C+Soho%2C+London+W1F+8WD%2C+UK!5e0!3m2!1sen!2sin!4v1468326690641">
      <img class="img_modal-open" src="https://websemantics.uk/portfolio/modal-test/i/wine-bar-map-location.32.compressed.png" alt="Tesco finest* wine bar location">
    </a>
  </p>


  <h2>In use</h2>
  <ul>
    <li>Add attribute <code>data-modal</code> to any link to indicate "Launch in modal".</li>
    <li>Give <code>data-modal</code> the url of the <code>iframe</code> <code>src</code> if different from the link <code>href</code>.</li>
    <li>The modal title is taken as the image <code>alt</code> (image is a requirement in this version).</li>
  </ul>

  <p>Please note this modal neither raises or lowers accessibility barriers caused by the <code>iframe</code> content.</p>


  <h2>Features</h2>
  <ul>
    <li><abbr title="Web Content Accessibility Guidelines">WCAG</abbr> 2 level AA with <abbr title="Accessible Rich Internet Applications">ARIA</abbr> support</li>
    <li>Fully responsive, mobile-first approach.</li>
    <li>Lightweight, less than 3 kb to the browser including CSS.</li>
    <li>When opening; the focus is moved to modal content.</li>
    <li>When closing; the focus is moved back to the activating link.</li>
    <li>While open; the <kbd>Tab</kbd> scope is limited to the modal content.<br>(Currently double checking this requirement)</li>
    <li>While open; the #content block is frozen (considering removal).</li>
    <li>While open; the <kbd>Esc</kbd> key closes the modal while on any focusable object (but not while inside the <code>iframe</code>).</li>
    <li>All customisations are via inline HTML attributes and CSS.<br>No need to edit JavaScript.</li>
    <li>Just a link is presented when JavaScript is unavailable.</li>
  </ul>


  <h2>Current status</h2>
  <p>14/08/2016 - In cross-browser, cross-platform and cross-device testing.<br>To be followed with full access testing by <a href="http://www.digitalaccessibilitycentre.org/">Digital Accessibility Centre</a>.</p>


  <h2>Based on the workings of:</h2>
  <ul>
    <li>Greg Kraus: <a href="https://accessibility.oit.ncsu.edu/training/aria/modal-window/version-3/">The incredible accessible modal window v3</a></li>
    <li>Marco Zehe: <a href="https://www.marcozehe.de/2015/02/05/advanced-aria-tip-2-accessible-modal-dialogs/">Accessible modal dialogs</a></li>
    <li>Heydonworks: <a href="http://heydonworks.com/practical_aria_examples/#warning-dialog">Warning dialog</a></li>
  </ul>


  <h2>Alternatives</h2>
  <p>Let's mention alternate versions of modal pop-ups out there:</p>
  <ul>
    <li><a href="http://www.humaan.com/modaal/">Modaal</a> - The best I've seen though kicks in at 17 kb. Does it all except allow for different link <code>href</code> to a modal <code>iframe</code> src (as per this example). If you need Accessibility with
      bells & whistles this is <strong>recommended</strong>. [Nicked some of your feature docs, thanks].</li>
    <li><a href="https://robinparisi.github.io/tingle/">Tingle js</a> - Love the UX feel of this one but Accessibility not the strong point. Code weight (3 kb loaded) and a style I'm envious of. Appreciated the prototype technique over my purely functional.
      [Nicked the lightbox <code>cursor</code>, thanks].</li>
    <li><a href="http://thephuse.github.io/vanilla-modal/">Vanilla modal</a> - Loved the lightweight (&lt; 4 kb loaded inc CSS) simplicity, hated the modals loading before interaction, sadly ignores keyboard-only users too.</li>
    <li>This version 3 (&lt; 3 kb inc CSS) - Has a couple of assumptions which I'd like to remove. Has the requirement of using an image in the activation link. Uses <code>classList</code> so limited to IE10+.</li>
  </ul>

  <p>All in all nothing is ever perfect, just avoid using a heavy weight library / framework for something this simple.</p>

</main>

<svg style="display:none">
  <defs>
    <symbol viewBox="0 0 38 38" id="icon-cross">
      <path d="M19 17.6l5.3-5.4 1.4 1.4-5.3 5.4 5.3 5.3-1.4 1.4-5.3-5.3-5.3 5.3-1.4-1.4 5.2-5.3-5.2-5.3 1.4-1.4 5.3 5.3z"/>
    </symbol>
    <symbol viewBox='0 0 150 130' id="icon-loading">
      <title>Loading</title>
      <path d='M81.5 33l30.8-32.8c0.3-0.3 0.5-0.2 0.3 0.3 -1.8 5.2-1.7 15.3-1.7 15.3 -0.1 6.8-0.8 11.7-6.6 17.9L74.8 65.1c-0.2 0.2-0.4 0-0.3-0.2 1.5-5.1 1.2-15.1 1.2-15.1C75.4 45.6 76.4 38.4 81.5 33M105.9 54.8l43.8 10.3c0.4 0.1 0.4 0.4-0.2 0.4 -5.4 1-14.1 6.1-14.1 6.1 -6 3.3-10.5 5.2-18.8 3.2l-41.9-9.9c-0.3-0.1-0.2-0.3 0-0.4 5.2-1.3 13.7-6.5 13.7-6.5C92 55.9 98.7 53.1 105.9 54.8M99.4 86.3l13 43.2c0.1 0.4-0.1 0.5-0.4 0.1 -3.6-4.2-12.4-9.2-12.4-9.2 -5.8-3.5-9.7-6.5-12.2-14.6L75 64.5c-0.1-0.3 0.2-0.4 0.3-0.2 3.7 3.9 12.5 8.6 12.5 8.6C91.5 74.8 97.3 79.2 99.4 86.3M68.7 97l-30.8 32.8c-0.3 0.3-0.5 0.2-0.3-0.3 1.8-5.2 1.7-15.3 1.7-15.3 0.1-6.8 0.8-11.7 6.6-17.9l29.5-31.4c0.2-0.2 0.4 0 0.3 0.2 -1.5 5.1-1.2 15.1-1.2 15.1C74.8 84.4 73.8 91.6 68.7 97M44.1 75.8L0.3 65.4C-0.1 65.3-0.1 65 0.5 65c5.4-1 14.1-6.1 14.1-6.1 6-3.3 10.5-5.2 18.8-3.2l41.9 9.9c0.3 0.1 0.2 0.3 0 0.4 -5.2 1.3-13.7 6.5-13.7 6.5C58.1 74.7 51.3 77.5 44.1 75.8M50.2 43.8l-13-43.2c-0.1-0.4 0.1-0.5 0.4-0.1C41.2 4.7 50 9.7 50 9.7c5.8 3.5 9.7 6.5 12.2 14.6l12.4 41.3c0.1 0.3-0.2 0.4-0.3 0.2 -3.7-3.9-12.5-8.6-12.5-8.6C58.1 55.4 52.4 50.9 50.2 43.8'/>
    </symbol>
  </defs>
</svg>
            
          
!
            
              .modal {
  max-width: 80vw;
  max-height: 90vh;
  background-color: #F7F0E8;
  margin: 0 auto;
  position: absolute;
  left: 10%;
  right: 10%;
  top: 5%;
  bottom: 5%;
  z-index: 10;
  border: 1px solid #3a3a3a;
  border-radius: .25em;
  box-shadow: 0 .25em .5em rgba(0, 0, 0, .25);
  transition: opacity .5s ease-out, visibility 0s ease-out 1s, transform .5s ease-out .5s;
  backface-visibility: hidden;
  opacity: 0;
  visibility: hidden;
  transform: scale(.8) translate3d(0,0,0);
  pointer-events: none;
}

.modal[aria-hidden="false"] {
  position: fixed;
  transition: opacity .5s ease-out, visibility 0s ease-out 0s, transform .5s ease-out 0s;
  opacity: 1;
  visibility: visible;
  transform: scale(1) translate3d(0,0,0);
  pointer-events: auto;
}


/* Class added to body tag and id="content" tag when modal is open */

.-modal-open {
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}


/* Light box properties */

.lightbox {
  text-indent: -200em;
  background-color: rgba(0, 0, 0, 0.8);
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  /* places the modal overlay between the main page (0) and the modal dialog (10) */
  z-index: 5;
  cursor: pointer;
  transition: opacity .5s ease-out, visibility 0s ease-out .5s;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.lightbox-on {
  transition: opacity .5s ease-out, visibility 0s ease-out 0s;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.lightbox-on:hover {
  /* Stolen from trickle.js. Under consideration. SVGs will not work here */
  cursor: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAANpJREFUOBGNkz0KAjEQhYPYWXgCKws7LcXWyt7WG4i9jegBvIJ4AvEyXsRCsBDiN0sGkiE/O/A2O9n3viS7rPPeb9ETrVzPwrtHDzR1XF5I6oPWLQaeq5hDXQRw0I6xCuF5HH7Tz7oFuTkhrSyEhza8THaLoQhphpWUg/QOFyA/AFpy5nTbGrIjxvg4AiiGBzYc+rGZH9KPzFy+ZbX4bX9l+VDZr5NQMMbhbtvMxccpQ3JhpTchtXATQviItIpvW0CY7HHm8c9UDRd2chbABt3RQk2tEe8O3dDkD4JQ4iOR7BMpAAAAAElFTkSuQmCC"), pointer;
}


/* Modal title and description */

.modal_title,
.modal_desc {
  position: absolute;
  top: 5px;
  left: -200em;
  background-color: #fff;
  color: #000;
  text-shadow: 0 0 0 #fff;
  font-size: 20px;
  padding: 0.125em .25em;
  font-family: Tesco_W_Rg, sans-serif;
  margin: 0;
}

.modal_title:focus,
.modal_desc:focus {
  left: 5px;
}

[aria-hidden="false"] .modal_title {
  transition: opacity .5s ease-out 3s;
  opacity: 0;
}

.modal_title,
.modal_title:focus {
  opacity: 1;
  transition: opacity .5s ease-out;
}


/* The iframe */

.modal_iframe {
  transition: opacity .5s ease-out, visibility 0s ease-out 1s;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.modal_iframe-on {
  transition: opacity .8s ease-out, visibility 0s ease-out 0s;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}


/* The modal pop-ups close button, appears last in the modal but is moved visually to the top right of the pop-up */

.modal_lnk-close {
  cursor: pointer;
  position: absolute;
  top: -20px;
  right: -20px;
  border: 0 solid;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  background-color: #000;
  box-shadow: 0 .25em .5em rgba(0, 0, 0, .25);
  overflow: hidden;
  transition: background-color .3s ease-out;
}

.modal_lnk-close:hover,
.modal_lnk-close:active,
.modal_lnk-close:focus {
  background-color: #c00;
  outline: 0 solid;
}

.modal_lnk-close span {
  position: absolute;
  top: 0;
  left: -200em;
  display: block;
}

.svg-close {
  pointer-events: none;
  width: 40px;
  height: 40px;
  stroke: #fff;
  stroke-width: 2;
}


/* Modal opening link */

.lnk_modal-open {
  display: inline-block;
  text-decoration: none;
  border: 0 solid;
  margin: 0 auto;
  transition: box-shadow .3s ease-out, filter .3s ease-out;
}

.lnk_modal-open:hover {
  -webkit-filter: contrast(120%);
  filter: contrast(120%);
}

.lnk_modal-open:hover,
.lnk_modal-open:focus {
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .6);
}

.lnk_modal-open:focus {
  outline: none;
}

.lnk_modal-open:active {
  -webkit-filter: brightness(85%);
  filter: brightness(85%);
}

[role="dialog"][aria-hidden="true"] .modal_iframe {
  display: none;
}

[role="dialog"][aria-hidden="false"] .modal_iframe {
  display: block;
}

.img_modal-open {
  display: block
}


/* Modal SVG (Tesco) loading animation version 2 (overlaid on itself and out of phase) */

[class*="svg-loading"] {
  position: absolute;
  width: 80px;
  height: 80px;
  top: calc(50% - 40px);
  left: calc(50% - 40px);
  z-index: -1;
  transition: opacity .3s ease-out;
  backface-visibility: hidden;
}

.svg-loading {
  fill: #00539f;
  -webkit-animation: rotate 4s linear 0s infinite;
  animation: rotate 4s linear 0s infinite;
}

.svg-loading2 {
  /* Match to .modal background colour for full effect */
  fill: #F7F0E8;
  -webkit-animation: rotate 5s linear 1s infinite;
  animation: rotate 5s linear 1s infinite;
}

.svg-loading.OFF {
  opacity: 0;
}

@-webkit-keyframes rotate {
  to {
    -webkit-transform: rotate(360deg) translate3d(0,0,0);
    transform: rotate(360deg) translate3d(0,0,0);
  }
}

@keyframes rotate {
  to {
    -webkit-transform: rotate(360deg) translate3d(0,0,0);
    transform: rotate(360deg) translate3d(0,0,0);
  }
}

xa {
  background-color: #1a1a1a;
  box-shadow: 0 0 0 2px #1a1a1a
}
            
          
!
            
              
// https://john-dugan.com/javascript-debounce/
// Example: window.addEventListener("resize",debounce(funcToCall, timeToWaitBetweenRefreshes, booleanRunAtStart [false = RunAtEnd]));
var debounce=function(e,t,n){var a;return function(){var r=this,i=arguments,o=function(){a=null,n||e.apply(r,i)},s=n&&!a;clearTimeout(a),a=setTimeout(o,t||200),s&&e.apply(r,i)}};


(function () {

  "use strict";

  // Modal pop-up window iframe version 3.0 13-08-2016

  // v3.0 - Revamped to launch from an anchor link

  // Requires:
  //    SVG definitions for: #icon-cross, #icon-loading
  //    External functions: debounce()

  // Assumptions:
  //    First object in modal is the modal title
  //    Last object is the modal close link
  //    Activating Link contains an image with alt text

  // To do:
  //    Remove reliance on image as activation Link content. Version 4?

  var d = document;
  var modalName;
  var contentObj = d.getElementById("content"); // This object is removed from keyboard actions
  var lightboxClass = "lightbox";


  var _closeModal = function (e) {
    var count = e.target.count; // lightbox, modal (ESC key), close btn
    var modal = d.getElementById(modalName + "_" + count);
    var lightbox = d.getElementById(lightboxClass + "_" + count);
    var modalLink;
    if (modal) {
      modal.setAttribute("aria-hidden", "true");
      lightbox.className = lightbox.className.replace(lightboxClass + "-on", "");
      contentObj.setAttribute("aria-hidden", "false");
      modalLink = d.getElementById(modal.returnId);
      setTimeout(function () {
        // move focus back to initialising button
        modalLink.focus();
      }, 300);
      d.body.classList.remove("-" + modalName + "-open");
    }
  };


  var _getModalSize = function (modalSection) {
    var clone = modalSection.cloneNode(true);
    var size = {};
    clone.className = modalName;
    clone.setAttribute("style", "position:fixed;visibility:hidden;transform: none");
    modalSection.parentElement.appendChild(clone);
    size.width = clone.clientWidth; // faster than getBoundingClientRect
    size.height = clone.clientHeight; // faster than getBoundingClientRect
    modalSection.parentElement.removeChild(clone);
    return size;
  };


  var _resizeIframes = function () {

    var size;
    var iframes;
    var ii;

    var modals = d.getElementsByClassName(modalName);
    var i = modals.length;

    while (i--) {

      size = _getModalSize(modals[i]);

      iframes = modals[i].getElementsByClassName(modalName + "_iframe");
      ii = iframes.length;

      while (ii--) {
        iframes[ii].width = size.width;
        iframes[ii].height = size.height;
      }
    }
  };


  var _addIframe = function (modalSection) {

    var size;
    var close_lnk;
    var frames = modalSection.getElementsByClassName(modalName + "_iframe");
    var iframe;
    if (!frames[0]) {

      iframe = d.createElement("iframe");

      iframe.addEventListener("load", function () {
        iframe.classList.add(modalName + "_iframe-on");
      }, false);

      iframe.src = modalSection.modalSrc;
      iframe.className = modalName + "_iframe";

      size = _getModalSize(modalSection);
      iframe.width = size.width;
      iframe.height = size.height;

      iframe.setAttribute("frameborder", 0);
      iframe.setAttribute("allowfullscreen", true);

      // Add iframe before the close button
      close_lnk = d.getElementById(modalName + "_lnk_close_" + modalSection.count);
      modalSection.insertBefore(iframe, close_lnk);

    }
  };


  var _openModal = function (e) {

    e.preventDefault();

    var target = e.target;
    if (!target.modalSrc) {
      target = target.parentElement; // Assumption!!!
    }

    var count = target.count;
    var modalSection = d.getElementById(modalName + "_" + count);
    var lightbox = d.getElementById(lightboxClass + "_" + count);

    if (modalSection && lightbox) {
      if (!lightbox.className.match(lightboxClass + "-on")) {
        lightbox.className += " " + lightboxClass + "-on";
      }
      modalSection.setAttribute("aria-hidden", "false");
      _addIframe(modalSection);
      contentObj.setAttribute("aria-hidden", "true");

      d.getElementById(modalName + "_title_" + count).focus();
      d.body.classList.add("-" + modalName + "-open");
    }
  };


  var _addOpenModalLinkAttr = function (modalLink) {
    modalLink.id = modalLink.id || "modal_lnk_" + modalLink.count;
    modalLink.setAttribute("aria-controls", modalName + "_" + modalLink.count);
    modalLink.setAttribute("aria-role", "button");
    modalLink.addEventListener("click", _openModal, false);
  };


  var _getImgAlt = function (modalLink) {
    var alt = "";
    var imgs = modalLink.getElementsByTagName("img");
    if (imgs && imgs[0]) {
      alt = imgs[0].alt;
    }
    return alt;
  };


  var _keydown = function (e) {

    var target = e.target;

    // ESC key on anything actionable
    if (e.which === 27) {
      _closeModal(e);
    }

    // tab key and shift on the h1
    if (e.which === 9 && e.shiftKey) {
      if (target.classList.contains(modalName + "_title")) {
        e.preventDefault();
        //focus on last object in modal (close btn)
        d.getElementById(modalName + "_lnk_close_" + e.target.count).focus();
      }
    }

    // tab key and not shift on the close link.
    if (e.which === 9 && !e.shiftKey) {
      if (target.classList.contains(modalName + "_lnk-close")) {
        e.preventDefault();
        //focus on first object in modal - or should it be the modal? Requires testing
        d.getElementById(modalName + "_title_" + e.target.count).focus();
      }
    }

    // enter or space on the close link
    if (e.which === 13 || e.which === 32) {
      if (target.classList.contains(modalName + "_lnk-close")) {
        _closeModal(e);
      }
    }
  };


  var _getModalTitle = function (modalLink) {
    var title = d.createElement("h1");
    title.id = modalName + "_title_" + modalLink.count;
    title.className = modalName + "_title";
    title.tabIndex = 0;
    title.textContent = _getImgAlt(modalLink);
    title.count = modalLink.count;
    title.addEventListener("keydown", _keydown, false);
    return title;
  };


  var _getModalSVG = function (icon, clss, title) {
    var svg = d.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.classList.add(clss);
    if (title) {
      var t = d.createElementNS("http://www.w3.org/2000/svg", "title");
      t.textContent = title;
      svg.appendChild(t);
    }
    var use = d.createElementNS("http://www.w3.org/2000/svg", "use");
    use.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#" + icon);
    svg.appendChild(use);
    return svg;
  };


  var _getModalDesc = function (modalLink) {
    var desc = d.createElement("p");
    desc.id = modalName + "_desc_" + modalLink.count;
    desc.className = modalName + "_desc";
    desc.tabIndex = 0;
    desc.innerHTML = "<kbd>tab</kbd> &amp; <kbd>shift-tab</kbd> to move focus.";
    desc.count = modalLink.count;
    desc.addEventListener("keydown", _keydown, false);
    return desc;
  };


  var _getModalCloseLink = function (modalLink) {
    var link = d.createElement("a");
    link.id = modalName + "_lnk_close_" + modalLink.count;
    link.className = modalName + "_lnk-close";
    link.tabIndex = 0;
    link.appendChild(_getModalSVG("icon-cross", "svg-close", "Close modal"));
    link.count = modalLink.count;
    link.addEventListener("click", _closeModal, false);
    link.addEventListener("keydown", _keydown, false);
    return link;
  };


  var _addModalSection = function(modalLink) {
    var section = d.createElement("section");
    section.id = modalName + "_" + modalLink.count;
    section.count = modalLink.count;
    section.returnId = modalLink.id;
    section.className = modalName;
    section.setAttribute("aria-hidden", "true");

    // should be on the activating link?
    section.setAttribute("aria-labelledby", modalName + "_title_" + modalLink.count);
    section.setAttribute("aria-describedby", modalName + "_desc_" + modalLink.count);

    section.setAttribute("role", "dialog");
    section.modalSrc = modalLink.modalSrc;

    section.appendChild(_getModalTitle(modalLink));
    section.appendChild(_getModalSVG("icon-loading", "svg-loading"));
    section.appendChild(_getModalSVG("icon-loading", "svg-loading2"));
    section.appendChild(_getModalDesc(modalLink));
    section.appendChild(_getModalCloseLink(modalLink));

    d.body.appendChild(section);
  };


  var _addLightbox = function (modalLink) {

    var count = modalLink.count;
    var lightboxDiv = d.createElement("div");

    lightboxDiv.id = lightboxClass + "_" + count;
    lightboxDiv.className = lightboxClass;
    lightboxDiv.count = count;
    lightboxDiv.returnId = modalLink.id;

    // mouse / touch only
    lightboxDiv.addEventListener("click", _closeModal, false);

    // belt & braces - should not be able to reach this via keyboard
    lightboxDiv.setAttribute("tabindex", "0");
    lightboxDiv.addEventListener("keydown", _keydown, false);

    d.body.appendChild(lightboxDiv);
  };


  var configuration = function (cfg) {
    modalName = cfg.modalName || "modal";
    lightboxClass = cfg.lightboxClass || "lightbox";
    contentObj = d.getElementById(cfg.contentId || "content"); // This object is removed from keyboard actions - currently under consideration
  };


  var initialise = function (cfg) {

    configuration(cfg);

    var modalSrc;
    var dataModals = d.querySelectorAll("[data-" + modalName + "]");

    if (contentObj && dataModals) {
      var i = dataModals.length;
      while (i--) {

        // Link href and iframe src are not always the same!
        modalSrc = false;

        // use the href if available
        if (dataModals[i].hasAttribute("href")) {
          modalSrc = dataModals[i].href;
        }

        // overwrite src with data-modal content
        if (dataModals[i].getAttribute("data-modal").length) {
          modalSrc = dataModals[i].getAttribute("data-modal");
        }

        if (modalSrc) {
          dataModals[i].modalSrc = modalSrc;
          dataModals[i].count = i;
          _addOpenModalLinkAttr(dataModals[i]);
          _addModalSection(dataModals[i]);
          _addLightbox(dataModals[i]);
        }

      }

      window.addEventListener("resize", debounce(_resizeIframes, 250, false));

    }

  };

  initialise({
    modalName : "modal",  // class name of modal, also used as the base for all classes used except SVGs.
    contentId : "content", // This object is removed from keyboard actions - currently under consideration
    lightboxClass : "lightbox"
  });

}(window, document, debounce));
            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console