@odopod/odo-dialog
Version:
Responsive window dialog component focused on a11y and extendibility
3 lines (2 loc) • 12.1 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@odopod/odo-helpers"),require("@odopod/odo-device"),require("tiny-emitter")):"function"==typeof define&&define.amd?define(["@odopod/odo-helpers","@odopod/odo-device","tiny-emitter"],t):e.OdoDialog=t(e.OdoHelpers,e.OdoDevice,e.TinyEmitter)}(this,function(e,t,n){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t,n=n&&n.hasOwnProperty("default")?n.default:n;var i=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},o=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},s=!!t.HAS_PASSIVE_LISTENERS&&{passive:!1},l=function(){function e(t,n){i(this,e),this.element=t,this.id=n,this.startY=null,this.scrollY=null,this._createBoundEvents(),this._registerEvents()}return e.prototype._createBoundEvents=function(){this._touchStartBound=this._onTouchStart.bind(this),this._touchMoveBound=this._onTouchMove.bind(this),this._preventDefaultBound=this._preventDefault.bind(this)},e.prototype._registerEvents=function(){document.body.addEventListener("touchstart",this._touchStartBound,s),document.body.addEventListener("touchmove",this._touchMoveBound,s),document.addEventListener("touchmove",this._preventDefaultBound,s)},e.prototype._onTouchStart=function(e){this.startY=e.changedTouches[0].pageY,this.scrollY=this.element.scrollTop},e.prototype._onTouchMove=function(e){var t=this.startY-e.changedTouches[0].pageY,n=this.scrollY+t;n<0||n+this.element.offsetHeight>this.element.scrollHeight?e.preventDefault():e.stopPropagation()},e.prototype._preventDefault=function(e){e.preventDefault()},e.prototype.dispose=function(){document.body.removeEventListener("touchstart",this._touchStartBound,s),document.body.removeEventListener("touchmove",this._touchMoveBound,s),document.removeEventListener("touchmove",this._preventDefaultBound,s),this.element=null,this.id=null},e}(),r={_fixes:new Map,add:function(n){if(t.HAS_TOUCH_EVENTS){var i=e.randomString();return this._fixes.set(i,new l(n,i)),i}return""},remove:function(e){this._fixes.has(e)&&(this._fixes.get(e).dispose(),this._fixes.delete(e))}},a=["a[href]","area[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","button:not([disabled])","iframe","object","embed","[contenteditable]",'[tabindex]:not([tabindex^="-"])'].join(","),d=function(t){function n(e,s){i(this,n);var l=o(this,t.call(this));if(!(e instanceof HTMLElement))throw new TypeError('OdoDialog requires an element. Got: "'+e+'"');return l.element=e,l.options=Object.assign({},n.Defaults,s),l.id=e.getAttribute("id"),l.backdrop=document.createElement("div"),l.backdrop.className=n.Classes.BACKDROP,l.content=l.getByClass(n.Classes.CONTENT),l._closers=Array.from(l.element.querySelectorAll("[data-odo-dialog-close]")),l._resizeId=null,l._scrollFixId=null,l.isOpen=!1,l.isAnimating=!1,l._hasBodyScrollbar=null,l._originalBodyPadding=-1,l._isFullscreen=null,l.z=n.Z_BASE,n.Instances.push(l),1===n.Instances.length&&document.body.addEventListener("click",n._handleTriggerClick),l.element.classList.toggle(n.Classes.NO_AUTO_MARGIN,!n.SUPPORTS_AUTO_MARGINS),l._bindContexts(),l.onResize(),l._addA11yAttributes(),l._ensureBodyChild(),l}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(n,t),n.prototype.getByClass=function(e){return this.element.getElementsByClassName(e)[0]},n.prototype._bindContexts=function(){this.onKeyPress=this.onKeyPress.bind(this),this.onClick=this.onClick.bind(this),this.close=this.close.bind(this),this.closeWithAnimation=this.close.bind(this,!1),this.onWindowResize=this.onResize.bind(this,void 0)},n.prototype._addA11yAttributes=function(){this.element.tabIndex=-1,this.element.setAttribute("aria-hidden",!0),this.element.setAttribute("role","dialog"),this.content.setAttribute("role","document")},n.prototype._ensureBodyChild=function(){this.element.parentNode!==document.body&&document.body.appendChild(this.element)},n.prototype._applyScrollFix=function(){if(this.options.scrollableElement){var e=this.element.matches(this.options.scrollableElement)?this.element:this.element.querySelector(this.options.scrollableElement);this._scrollFixId=r.add(e)}},n.prototype._getScrollbarOffset=function(){var e=this.element.scrollHeight>document.documentElement.clientHeight;return this._hasBodyScrollbar&&!e?n.SCROLLBAR_WIDTH:0},n.prototype.onClick=function(e){this.options.dismissable&&e.target===this.element&&this.close()},n.prototype.onKeyPress=function(e){this.z===n.getTopLayer()&&(this.options.dismissable&&e.which===n.Keys.ESC&&this.close(),e.which===n.Keys.TAB&&n._trapTabKey(this.element,e))},n.prototype.onResize=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.innerHeight;this.element.style.height=e+"px"},n.prototype.open=function(){var t=this,i=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!this.isAnimating&&!this.isOpen){var o=window.innerHeight;n.focusedBeforeDialog=document.activeElement,this._hasBodyScrollbar=document.body.clientWidth<window.innerWidth,this._isFullscreen=this.element.classList.contains(n.Classes.FULLSCREEN);var s=n._getSiblings(this.element),l=s.map(function(e){return e.getAttribute("aria-hidden")});s.forEach(function(e,t){l[t]&&e.setAttribute("data-odo-dialog-original",l[t]),e.setAttribute("aria-hidden",!0)}),n.getOpenDialogCount()>0&&this.handleOtherOpenDialogs(),this.isOpen=!0,this.onResize(o),this.element.removeAttribute("aria-hidden"),this.element.classList.add(n.Classes.OPEN),this.element.classList.add(n.Classes.ENTER),n.SCROLLBAR_WIDTH&&(document.body.style.paddingRight=n.SCROLLBAR_WIDTH+"px"),document.body.classList.add(n.Classes.BODY_OPEN),document.body.insertBefore(this.backdrop,this.element.nextSibling),this.element.scrollTop=0,this._applyScrollFix(),this.element.focus(),document.addEventListener("keydown",this.onKeyPress),window.addEventListener("resize",this.onWindowResize),this.element.addEventListener("click",this.onClick),this._closers.forEach(function(e){e.addEventListener("click",t.closeWithAnimation)}),!0===i?(this._openNext(),this._opened()):n._nextFrame(function(){t._openNext(),e.onTransitionEnd(t.element,t._opened,t,null,1e3)})}},n.prototype._openNext=function(){this.isAnimating=!0;var e=this._getScrollbarOffset();!this._isFullscreen&&e>0&&(this.element.style.paddingRight=e+"px"),this.element.classList.remove(n.Classes.ENTER),this.element.classList.add(n.Classes.ENTERING)},n.prototype._opened=function(){this.element.classList.remove(n.Classes.ENTERING),this.element.classList.add(n.Classes.VISIBLE),this.isAnimating=!1,this.emit(n.EventType.OPENED)},n.prototype.close=function(){var t=this,i=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!this.isAnimating&&this.isOpen){var o=n._getSiblings(this.element),s=o.map(function(e){return e.getAttribute("data-odo-dialog-original")});o.forEach(function(e,t){s[t]?(e.setAttribute("aria-hidden",s[t]),e.removeAttribute("data-odo-dialog-original")):e.removeAttribute("aria-hidden")}),this.isOpen=!1,this.element.classList.add(n.Classes.LEAVE),this.element.classList.remove(n.Classes.VISIBLE),r.remove(this._scrollFixId),n.focusedBeforeDialog&&"function"==typeof n.focusedBeforeDialog.focus&&n.focusedBeforeDialog.focus(),document.removeEventListener("keydown",this.onKeyPress),window.removeEventListener("resize",this.onWindowResize),this.element.removeEventListener("click",this.onClick),this._closers.forEach(function(e){e.removeEventListener("click",t.closeWithAnimation)}),!0===i?(this._closeNext(),this._closed()):n._nextFrame(function(){t._closeNext(),e.onTransitionEnd(t.element,t._closed,t,null,1e3)})}},n.prototype._closeNext=function(){this.isAnimating=!0,this.element.classList.remove(n.Classes.LEAVE),this.element.classList.add(n.Classes.LEAVING)},n.prototype._closed=function(){this.isAnimating=!1,this.element.style.paddingRight="",this.element.setAttribute("aria-hidden",!0),this.element.classList.remove(n.Classes.OPEN),this.element.classList.remove(n.Classes.LEAVING),0===n.getOpenDialogCount()&&(document.body.style.paddingRight="",document.body.classList.remove(n.Classes.BODY_OPEN)),document.body.removeChild(this.backdrop),this.emit(n.EventType.CLOSED)},n.prototype.handleOtherOpenDialogs=function(){var e=this;this.z=n.getTopLayer()+20,this.element.style.zIndex=this.z,this.backdrop.style.zIndex=this.z-5,this.once(n.EventType.CLOSED,function(){e.z=n.Z_BASE,e.element.style.zIndex="",e.backdrop.style.zIndex="";var t=n.getTopLayer();n.Instances.forEach(function(e){e.isOpen&&e.z===t&&e.didEnterForeground()})}),n.Instances.forEach(function(t){t.isOpen&&t.id!==e.id&&t.didEnterBackground()})},n.prototype.didEnterBackground=function(){r.remove(this._scrollFixId)},n.prototype.didEnterForeground=function(){this._applyScrollFix()},n.prototype.dispose=function(){this.isOpen&&this.close(!0),this.element=null,this.content=null,this.backdrop=null,this._closers.length=0,e.pull(n.Instances,this),0===n.Instances.length&&document.body.removeEventListener("click",n._handleTriggerClick)},n._nextFrame=function(e){window.requestAnimationFrame(window.requestAnimationFrame.bind(null,e))},n._handleTriggerClick=function(e){var t=e.target.closest("[data-odo-dialog-open]");if(null!==t){e.preventDefault();var i=t.getAttribute("data-odo-dialog-open"),o=n.getDialogById(i);o.emit(n.EventType.TRIGGER_CLICKED,t),o.open()}},n._trapTabKey=function(e,t){var i=n._getFocusableChildren(e),o=i.indexOf(document.activeElement);t.shiftKey&&0===o?(i[i.length-1].focus(),t.preventDefault()):t.shiftKey||o!==i.length-1||(i[0].focus(),t.preventDefault())},n._getFocusableChildren=function(e){return Array.from(e.querySelectorAll(a)).filter(n._isVisibleElement)},n._isVisibleElement=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},n._getSiblings=function(e){var t=Array.from(e.parentElement.children),n=["script","link","meta"];return t.filter(function(t){return t!==e&&!n.includes(t.nodeName.toLowerCase())})},n._getScrollbarWidth=function(){var e=document.createElement("div");e.style.cssText="width:50px;height:50px;overflow:scroll;position:absolute;top:-9999px;",document.body.appendChild(e);var t=e.offsetWidth-e.clientWidth;return document.body.removeChild(e),t},n._autoMarginTest=function(){var e=document.createElement("div"),t=document.createElement("div");e.style.cssText="display:flex;height:50px;width:50px;position:absolute;",t.style.cssText="margin:auto;",t.innerHTML="a",e.appendChild(t),document.body.appendChild(e);var n=t.offsetTop>0;return document.body.removeChild(e),n},n.initializeAll=function(e){return n.disposeAll(),Array.from(document.querySelectorAll("."+n.Classes.BASE),function(t){return new n(t,e)})},n.disposeAll=function(){n.Instances.slice().forEach(function(e){e.dispose()})},n.getDialogById=function(e){return n.Instances.find(function(t){return t.id===e})},n.getOpenDialogCount=function(){return n.Instances.filter(function(e){return e.isOpen}).length},n.getTopLayer=function(){return Math.max.apply(Math,n.Instances.map(function(e){return e.z}))},n}(n);return d.Classes={BODY_OPEN:"odo-dialog-open",BASE:"odo-dialog",OPEN:"odo-dialog--open",ENTER:"odo-dialog--enter",ENTERING:"odo-dialog--enter-active",LEAVE:"odo-dialog--leave",LEAVING:"odo-dialog--leave-active",VISIBLE:"odo-dialog--visible",FULLSCREEN:"odo-dialog--full",NO_AUTO_MARGIN:"odo-dialog--no-auto-margin",BACKDROP:"odo-dialog-backdrop",CONTENT:"odo-dialog__content"},d.EventType={OPENED:"ododialog:open",CLOSED:"ododialog:closed",TRIGGER_CLICKED:"ododialog:triggerclicked"},d.Keys={ESC:27,TAB:9},d.Defaults={dismissable:!0,scrollableElement:".odo-dialog"},d.Instances=[],d.Z_BASE=1050,d.ScrollFix=r,d.focusedBeforeDialog=null,d.SUPPORTS_AUTO_MARGINS=d._autoMarginTest(),d.SCROLLBAR_WIDTH=d._getScrollbarWidth(),d});
//# sourceMappingURL=odo-dialog.min.js.map