pure-modal
Version:
A lightweight, accessible, vanilla JavaScript modal component
7 lines (6 loc) • 4.84 kB
JavaScript
/**
* Pure Modal v1.0.3
* (c) 2019 Roman Slonov
* Released under the MIT License.
*/
var t="modal-backdrop",i="is-open",s="in",e="out",o="modal-dialog",n=27,a=9,r={transition:!0},l=function(t){return window.console.error("PureModal: "+t)},c=function t(i,s){this.id=i,this.config=Object.assign({},r,s),this.modal=t.findModal(this.id),this.dialog=this.modal.querySelector("."+o),this.backdrop=null,this.isOpen=!1,this.isInit=!1,this.isTransitioning=!1,this.triggers=t.findTriggers(this.id),this.closeEls=null,this.focusableEls=null,this.focusedElBeforeOpen=null,this.firstFocusableEl=null,this.lastFocusableEl=null,this.open=this.open.bind(this),this.close=this.close.bind(this),this.onDismiss=this.onDismiss.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this)};c.prototype.init=function(){var t=this;this.isInit?l("Event listeners already added."):(this.triggers.forEach(function(i){return i.addEventListener("click",t.open)}),this.isInit=!0)},c.prototype.destroy=function(){var t=this;this.isInit?(this.triggers.forEach(function(i){return i.removeEventListener("click",t.open)}),this.isInit=!1):l("Event listeners already removed.")},c.prototype.open=function(t){var e=this;this.isTransitioning||(t.preventDefault(),"function"==typeof this.config.beforeOpen&&this.config.beforeOpen(),this.focusedElBeforeOpen=document.activeElement,this.focusableEls=Array.from(this.dialog.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]')),this.firstFocusableEl=this.focusableEls[0],this.lastFocusableEl=this.focusableEls[this.focusableEls.length-1],this.showBackdrop(),this.modal.style.display="block",this.config.transition?(this.isTransitioning=!0,this.modal.classList.add(i),this.modal.classList.add(s),this.openWithTransition()):this.firstFocusableEl.focus(),document.addEventListener("mousedown",this.onDismiss),document.addEventListener("keydown",this.handleKeyDown),this.closeEls=Array.from(this.modal.querySelectorAll('[data-dismiss="modal"]')),this.closeEls.forEach(function(t){return t.addEventListener("click",e.close)}),this.isOpen=!0,"function"==typeof this.config.onOpen&&this.config.onOpen())},c.prototype.openWithTransition=function(){var t=this,i=function(){t.dialog.removeEventListener("animationend",i),t.firstFocusableEl.focus(),"function"==typeof t.config.onOpen&&t.config.onOpen(),t.isTransitioning=!1};this.dialog.addEventListener("animationend",i)},c.prototype.close=function(){var t=this;this.isTransitioning||("function"==typeof this.config.beforeClose&&this.config.beforeClose(),this.config.transition?(this.isTransitioning=!0,this.modal.classList.remove(s),this.modal.classList.remove(i),this.modal.classList.add(e),this.closeWithTransition(),this.closeBackdrop()):(this.modal.style.display="none",this.modal.classList.remove(i),this.closeBackdrop(),"function"==typeof this.config.onClose&&this.config.onClose()),document.removeEventListener("mousedown",this.onDismiss),document.removeEventListener("keydown",this.handleKeyDown),this.closeEls.forEach(function(i){return i.removeEventListener("click",t.close)}),this.isOpen=!1,this.focusedElBeforeOpen.focus())},c.prototype.closeWithTransition=function(){var t=this,i=function(){t.dialog.removeEventListener("animationend",i),t.modal.style.display="none",t.modal.classList.remove(e),"function"==typeof t.config.onClose&&t.config.onClose(),t.isTransitioning=!1};this.dialog.addEventListener("animationend",i)},c.prototype.onDismiss=function(t){!this.dialog.contains(t.target)&&this.isOpen&&this.close()},c.prototype.showBackdrop=function(){this.backdrop=document.createElement("div"),this.backdrop.tabIndex=-1,this.backdrop.classList.add(t),this.config.transition&&this.backdrop.classList.add(s),document.body.appendChild(this.backdrop),this.backdrop.offsetHeight,this.backdrop.classList.add(i)},c.prototype.closeBackdrop=function(){this.config.transition?(this.backdrop.classList.remove(s),this.backdrop.classList.remove(i),this.backdrop.classList.add(e),this.closeBackdropWithTransition()):this.backdrop.remove()},c.prototype.closeBackdropWithTransition=function(){var t=this,i=function(){t.backdrop.removeEventListener("transitionend",i),t.backdrop.remove()};this.backdrop.addEventListener("transitionend",i)},c.prototype.handleKeyDown=function(t){var i=this;switch(t.keyCode){case a:if(1===this.focusableEls.length){t.preventDefault();break}t.shiftKey?document.activeElement===i.firstFocusableEl&&(t.preventDefault(),i.lastFocusableEl.focus()):document.activeElement===i.lastFocusableEl&&(t.preventDefault(),i.firstFocusableEl.focus());break;case n:this.close()}},c.findTriggers=function(t){return Array.from(document.querySelectorAll('[data-toggle="modal"][data-target="'+t+'"]'))},c.findModal=function(t){return document.getElementById(t)};export default c;