@odopod/odo-dialog
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -5,3 +5,3 @@ (function (global, factory) { | ||
(global.OdoDialog = factory(global.TinyEmitter,global.OdoHelpers,global.OdoDevice)); | ||
}(this, (function (TinyEmitter,_odopod_odoHelpers,OdoDevice) { 'use strict'; | ||
}(this, (function (TinyEmitter,odoHelpers,OdoDevice) { 'use strict'; | ||
@@ -11,2 +11,4 @@ TinyEmitter = TinyEmitter && TinyEmitter.hasOwnProperty('default') ? TinyEmitter['default'] : TinyEmitter; | ||
var babelHelpers = {}; | ||
var classCallCheck = function (instance, Constructor) { | ||
@@ -20,10 +22,2 @@ if (!(instance instanceof Constructor)) { | ||
var inherits = function (subClass, superClass) { | ||
@@ -45,12 +39,2 @@ if (typeof superClass !== "function" && superClass !== null) { | ||
var possibleConstructorReturn = function (self, call) { | ||
@@ -64,2 +48,6 @@ if (!self) { | ||
babelHelpers; | ||
/** | ||
@@ -192,3 +180,3 @@ * @fileoverview Makes an overflowing element scrollable and handles preventing | ||
if (OdoDevice.HAS_TOUCH_EVENTS) { | ||
var id = _odopod_odoHelpers.string.random(); | ||
var id = odoHelpers.string.random(); | ||
this._fixes.set(id, new ScrollFix(element, id)); | ||
@@ -230,12 +218,11 @@ return id; | ||
/** | ||
* Dialog that can contain static images, carousels, or videos | ||
* @param {Element} element Main element. | ||
* | ||
* @constructor | ||
*/ | ||
var Dialog = function (_TinyEmitter) { | ||
inherits(Dialog, _TinyEmitter); | ||
/** | ||
* Dialog that can contain static images, carousels, or videos | ||
* @param {Element} element Main element. | ||
* @param {object} [opts] Instance options. | ||
* @constructor | ||
*/ | ||
function Dialog(element, opts) { | ||
@@ -256,2 +243,6 @@ classCallCheck(this, Dialog); | ||
/** | ||
* Options object. | ||
* @type {object} | ||
*/ | ||
_this.options = Object.assign({}, Dialog.Defaults, opts); | ||
@@ -347,2 +338,3 @@ | ||
_this._bindContexts(); | ||
_this.onResize(); | ||
_this._addA11yAttributes(); | ||
@@ -373,2 +365,5 @@ _this._ensureBodyChild(); | ||
this.close = this.close.bind(this); | ||
// Bind undefined as the first parameter so that the event object will be | ||
// the second parameter and the optional viewportHeight parameter will work. | ||
this.onWindowResize = this.onResize.bind(this, undefined); | ||
}; | ||
@@ -462,2 +457,19 @@ | ||
/** | ||
* The dialog has a height of 100vh, which, in mobile safari, is incorrect | ||
* when the toolbars are visible, not allowing the user to scroll the full | ||
* height of the content within it. | ||
* The viewportHeight parameter is optional so that it can be read in the open() | ||
* method with all the other DOM reads. This avoids read->write->read #perfmatters. | ||
* @param {number} [viewportHeight=window.innerHeight] Height of the viewport. | ||
* @protected | ||
*/ | ||
Dialog.prototype.onResize = function onResize() { | ||
var viewportHeight = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.innerHeight; | ||
this.element.style.height = viewportHeight + 'px'; | ||
}; | ||
/** | ||
* Checks to see if a dialog is already open or animating If not, opens dialog. | ||
@@ -477,2 +489,3 @@ * @param {boolean} [sync=false] Whether to open with transitions or not. | ||
var viewportHeight = window.innerHeight; | ||
Dialog.focusedBeforeDialog = document.activeElement; | ||
@@ -495,2 +508,3 @@ this._hasBodyScrollbar = document.body.clientWidth < window.innerWidth; | ||
this.isOpen = true; | ||
this.onResize(viewportHeight); | ||
this.element.removeAttribute('aria-hidden'); | ||
@@ -511,2 +525,3 @@ this.element.classList.add(Dialog.Classes.OPEN); | ||
document.addEventListener('keydown', this.onKeyPress); | ||
window.addEventListener('resize', this.onWindowResize); | ||
this.element.addEventListener('click', this.onClick); | ||
@@ -523,3 +538,3 @@ this._closers.forEach(function (element) { | ||
_this2._openNext(); | ||
_odopod_odoHelpers.animation.onTransitionEnd(_this2.element, _this2._opened, _this2, null, 1000); | ||
odoHelpers.animation.onTransitionEnd(_this2.element, _this2._opened, _this2, null, 1000); | ||
}); | ||
@@ -593,3 +608,6 @@ } | ||
if (Dialog.focusedBeforeDialog) { | ||
// Support: IE11 | ||
// Clicking on an SVG element inside an <a> will set the `focusedBeforeDialog` | ||
// to the SVG, but SVG doesn't have a `focus()` method in IE. | ||
if (Dialog.focusedBeforeDialog && typeof Dialog.focusedBeforeDialog.focus === 'function') { | ||
Dialog.focusedBeforeDialog.focus(); | ||
@@ -599,2 +617,3 @@ } | ||
document.removeEventListener('keydown', this.onKeyPress); | ||
window.removeEventListener('resize', this.onWindowResize); | ||
this.element.removeEventListener('click', this.onClick); | ||
@@ -611,3 +630,3 @@ this._closers.forEach(function (element) { | ||
_this3._closeNext(); | ||
_odopod_odoHelpers.animation.onTransitionEnd(_this3.element, _this3._closed, _this3, null, 1000); | ||
odoHelpers.animation.onTransitionEnd(_this3.element, _this3._closed, _this3, null, 1000); | ||
}); | ||
@@ -646,4 +665,3 @@ } | ||
/** | ||
* Disposes of global Dialog variables | ||
* @public | ||
* Close the dialog, remove event listeners and element references. | ||
*/ | ||
@@ -662,3 +680,3 @@ | ||
_odopod_odoHelpers.array.remove(Dialog.Instances, this); | ||
odoHelpers.array.remove(Dialog.Instances, this); | ||
@@ -691,8 +709,10 @@ // If this is the last dialog (being disposed), remove the body listener. | ||
Dialog._handleTriggerClick = function _handleTriggerClick(evt) { | ||
var elem = evt.target.closest('[data-odo-dialog-open]'); | ||
var trigger = evt.target.closest('[data-odo-dialog-open]'); | ||
if (elem !== null) { | ||
if (trigger !== null) { | ||
evt.preventDefault(); | ||
var id = elem.getAttribute('data-odo-dialog-open'); | ||
Dialog.getDialogById(id).open(); | ||
var id = trigger.getAttribute('data-odo-dialog-open'); | ||
var instance = Dialog.getDialogById(id); | ||
instance.emit(Dialog.EventType.TRIGGER_CLICKED, trigger); | ||
instance.open(); | ||
} | ||
@@ -815,4 +835,3 @@ }; | ||
* @param {Object} options Object of all dialog options. Is optional. | ||
* @return {Array.<Dialog>} | ||
* @public | ||
* @return {Dialog[]} | ||
*/ | ||
@@ -830,5 +849,3 @@ | ||
/** | ||
* Clear all references to dialogs so there are no duplicates | ||
* @param {Object} options Object of all dialog options. Is optional. | ||
* @public | ||
* Clear all references to dialogs so there are no duplicates. | ||
*/ | ||
@@ -881,3 +898,4 @@ | ||
OPENED: 'ododialog:open', | ||
CLOSED: 'ododialog:closed' | ||
CLOSED: 'ododialog:closed', | ||
TRIGGER_CLICKED: 'ododialog:triggerclicked' | ||
}; | ||
@@ -897,3 +915,3 @@ | ||
/** @enum {Array} */ | ||
/** @enum {Dialog[]} */ | ||
Dialog.Instances = []; | ||
@@ -900,0 +918,0 @@ |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("tiny-emitter"),require("@odopod/odo-helpers"),require("@odopod/odo-device")):"function"==typeof define&&define.amd?define(["tiny-emitter","@odopod/odo-helpers","@odopod/odo-device"],t):e.OdoDialog=t(e.TinyEmitter,e.OdoHelpers,e.OdoDevice)}(this,function(e,t,i){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e,i=i&&i.hasOwnProperty("default")?i.default:i;var o=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=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)},s=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},l=document.body,r=function(){function e(t,i){o(this,e),this.element=t,this.id=i,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(){l.addEventListener("touchstart",this._touchStartBound),l.addEventListener("touchmove",this._touchMoveBound),document.addEventListener("touchmove",this._preventDefaultBound)},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,i=this.scrollY+t;i<0||i+this.element.offsetHeight>this.element.scrollHeight?e.preventDefault():e.stopPropagation()},e.prototype._preventDefault=function(e){e.preventDefault()},e.prototype.dispose=function(){l.removeEventListener("touchstart",this._touchStartBound),l.removeEventListener("touchmove",this._touchMoveBound),document.removeEventListener("touchmove",this._preventDefaultBound),this.element=null,this.id=null},e}(),a={_fixes:new Map,add:function(e){if(i.HAS_TOUCH_EVENTS){var o=t.string.random();return this._fixes.set(o,new r(e,o)),o}return""},remove:function(e){this._fixes.has(e)&&(this._fixes.get(e).dispose(),this._fixes.delete(e))}},d=["a[href]","area[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","button:not([disabled])","iframe","object","embed","[contenteditable]",'[tabindex]:not([tabindex^="-"])'].join(","),c=function(e){function i(t,n){o(this,i);var l=s(this,e.call(this));if(!(t instanceof Element))throw new TypeError('OdoDialog requires an element. Got: "'+t+'"');return l.element=t,l.options=Object.assign({},i.Defaults,n),l.id=t.getAttribute("id"),l.backdrop=document.createElement("div"),l.backdrop.className=i.Classes.BACKDROP,l.content=l.getByClass(i.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,i.Instances.push(l),1===i.Instances.length&&document.body.addEventListener("click",i._handleTriggerClick),l.element.classList.toggle(i.Classes.NO_AUTO_MARGIN,!i.SUPPORTS_AUTO_MARGINS),l._bindContexts(),l._addA11yAttributes(),l._ensureBodyChild(),l}return n(i,e),i.prototype.getByClass=function(e){return this.element.getElementsByClassName(e)[0]},i.prototype._bindContexts=function(){this.onKeyPress=this.onKeyPress.bind(this),this.onClick=this.onClick.bind(this),this.close=this.close.bind(this)},i.prototype._addA11yAttributes=function(){this.element.tabIndex=-1,this.element.setAttribute("aria-hidden",!0),this.element.setAttribute("role","dialog"),this.content.setAttribute("role","document")},i.prototype._ensureBodyChild=function(){this.element.parentNode!==document.body&&document.body.appendChild(this.element)},i.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=a.add(e)}},i.prototype._getScrollbarOffset=function(){var e=this.element.scrollHeight>document.documentElement.clientHeight;return this._hasBodyScrollbar&&!e?i.SCROLLBAR_WIDTH:0},i.prototype.onClick=function(e){this.options.dismissable&&e.target===this.element&&this.close()},i.prototype.onKeyPress=function(e){this.options.dismissable&&e.which===i.Keys.ESC&&this.close(),e.which===i.Keys.TAB&&i._trapTabKey(this.element,e)},i.prototype.open=function(){var e=this,o=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!this.isAnimating&&!this.isOpen){i.focusedBeforeDialog=document.activeElement,this._hasBodyScrollbar=document.body.clientWidth<window.innerWidth,this._isFullscreen=this.element.classList.contains(i.Classes.FULLSCREEN);var n=i._getSiblings(this.element),s=n.map(function(e){return e.getAttribute("aria-hidden")});n.forEach(function(e,t){s[t]&&e.setAttribute("data-odo-dialog-original",s[t]),e.setAttribute("aria-hidden",!0)}),this.isOpen=!0,this.element.removeAttribute("aria-hidden"),this.element.classList.add(i.Classes.OPEN),this.element.classList.add(i.Classes.ENTER),i.SCROLLBAR_WIDTH&&(document.body.style.paddingRight=i.SCROLLBAR_WIDTH+"px"),document.body.classList.add(i.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),this.element.addEventListener("click",this.onClick),this._closers.forEach(function(t){t.addEventListener("click",e.close)}),!0===o?(this._openNext(),this._opened()):i._nextFrame(function(){e._openNext(),t.animation.onTransitionEnd(e.element,e._opened,e,null,1e3)})}},i.prototype._openNext=function(){this.isAnimating=!0;var e=this._getScrollbarOffset();!this._isFullscreen&&e>0&&(this.element.style.paddingRight=e+"px"),this.element.classList.remove(i.Classes.ENTER),this.element.classList.add(i.Classes.ENTERING)},i.prototype._opened=function(){this.element.classList.remove(i.Classes.ENTERING),this.element.classList.add(i.Classes.VISIBLE),this.isAnimating=!1,this.emit(i.EventType.OPENED)},i.prototype.close=function(){var e=this,o=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!this.isAnimating&&this.isOpen){var n=i._getSiblings(this.element),s=n.map(function(e){return e.getAttribute("data-odo-dialog-original")});n.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(i.Classes.LEAVE),this.element.classList.remove(i.Classes.VISIBLE),a.remove(this._scrollFixId),i.focusedBeforeDialog&&i.focusedBeforeDialog.focus(),document.removeEventListener("keydown",this.onKeyPress),this.element.removeEventListener("click",this.onClick),this._closers.forEach(function(t){t.removeEventListener("click",e.close)}),!0===o?(this._closeNext(),this._closed()):i._nextFrame(function(){e._closeNext(),t.animation.onTransitionEnd(e.element,e._closed,e,null,1e3)})}},i.prototype._closeNext=function(){this.isAnimating=!0,this.element.classList.remove(i.Classes.LEAVE),this.element.classList.add(i.Classes.LEAVING)},i.prototype._closed=function(){this.isAnimating=!1,this.element.style.paddingRight="",this.element.setAttribute("aria-hidden",!0),this.element.classList.remove(i.Classes.OPEN),this.element.classList.remove(i.Classes.LEAVING),document.body.style.paddingRight="",document.body.classList.remove(i.Classes.BODY_OPEN),document.body.removeChild(this.backdrop),this.emit(i.EventType.CLOSED)},i.prototype.dispose=function(){this.isOpen&&this.close(!0),this.element=null,this.content=null,this.backdrop=null,this._closers.length=0,t.array.remove(i.Instances,this),0===i.Instances.length&&document.body.removeEventListener("click",i._handleTriggerClick)},i._nextFrame=function(e){window.requestAnimationFrame(window.requestAnimationFrame.bind(null,e))},i._handleTriggerClick=function(e){var t=e.target.closest("[data-odo-dialog-open]");if(null!==t){e.preventDefault();var o=t.getAttribute("data-odo-dialog-open");i.getDialogById(o).open()}},i._trapTabKey=function(e,t){var o=i._getFocusableChildren(e),n=o.indexOf(document.activeElement);t.shiftKey&&0===n?(o[o.length-1].focus(),t.preventDefault()):t.shiftKey||n!==o.length-1||(o[0].focus(),t.preventDefault())},i._getFocusableChildren=function(e){return Array.from(e.querySelectorAll(d)).filter(i._isVisibleElement)},i._isVisibleElement=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},i._getSiblings=function(e){var t=["script","link","meta"];return Array.from(e.parentNode.children).filter(function(i){return i!==e&&!t.includes(i.nodeName.toLowerCase())})},i._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},i._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 i=t.offsetTop>0;return document.body.removeChild(e),i},i.initializeAll=function(e){return i.disposeAll(),Array.from(document.querySelectorAll("."+i.Classes.BASE)).map(function(t){return new i(t,e)})},i.disposeAll=function(){i.Instances.slice().forEach(function(e){e.dispose()})},i.getDialogById=function(e){return i.Instances.find(function(t){return t.id===e})},i}(e);return c.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"},c.EventType={OPENED:"ododialog:open",CLOSED:"ododialog:closed"},c.Keys={ESC:27,TAB:9},c.Defaults={dismissable:!0,scrollableElement:".odo-dialog"},c.Instances=[],c.ScrollFix=a,c.focusedBeforeDialog=null,c.SUPPORTS_AUTO_MARGINS=c._autoMarginTest(),c.SCROLLBAR_WIDTH=c._getScrollbarWidth(),c}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("tiny-emitter"),require("@odopod/odo-helpers"),require("@odopod/odo-device")):"function"==typeof define&&define.amd?define(["tiny-emitter","@odopod/odo-helpers","@odopod/odo-device"],t):e.OdoDialog=t(e.TinyEmitter,e.OdoHelpers,e.OdoDevice)}(this,function(e,t,i){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e,i=i&&i.hasOwnProperty("default")?i.default:i;var o=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=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)},s=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},l=document.body,r=function(){function e(t,i){o(this,e),this.element=t,this.id=i,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(){l.addEventListener("touchstart",this._touchStartBound),l.addEventListener("touchmove",this._touchMoveBound),document.addEventListener("touchmove",this._preventDefaultBound)},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,i=this.scrollY+t;i<0||i+this.element.offsetHeight>this.element.scrollHeight?e.preventDefault():e.stopPropagation()},e.prototype._preventDefault=function(e){e.preventDefault()},e.prototype.dispose=function(){l.removeEventListener("touchstart",this._touchStartBound),l.removeEventListener("touchmove",this._touchMoveBound),document.removeEventListener("touchmove",this._preventDefaultBound),this.element=null,this.id=null},e}(),a={_fixes:new Map,add:function(e){if(i.HAS_TOUCH_EVENTS){var o=t.string.random();return this._fixes.set(o,new r(e,o)),o}return""},remove:function(e){this._fixes.has(e)&&(this._fixes.get(e).dispose(),this._fixes.delete(e))}},d=["a[href]","area[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","button:not([disabled])","iframe","object","embed","[contenteditable]",'[tabindex]:not([tabindex^="-"])'].join(","),c=function(e){function i(t,n){o(this,i);var l=s(this,e.call(this));if(!(t instanceof Element))throw new TypeError('OdoDialog requires an element. Got: "'+t+'"');return l.element=t,l.options=Object.assign({},i.Defaults,n),l.id=t.getAttribute("id"),l.backdrop=document.createElement("div"),l.backdrop.className=i.Classes.BACKDROP,l.content=l.getByClass(i.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,i.Instances.push(l),1===i.Instances.length&&document.body.addEventListener("click",i._handleTriggerClick),l.element.classList.toggle(i.Classes.NO_AUTO_MARGIN,!i.SUPPORTS_AUTO_MARGINS),l._bindContexts(),l.onResize(),l._addA11yAttributes(),l._ensureBodyChild(),l}return n(i,e),i.prototype.getByClass=function(e){return this.element.getElementsByClassName(e)[0]},i.prototype._bindContexts=function(){this.onKeyPress=this.onKeyPress.bind(this),this.onClick=this.onClick.bind(this),this.close=this.close.bind(this),this.onWindowResize=this.onResize.bind(this,void 0)},i.prototype._addA11yAttributes=function(){this.element.tabIndex=-1,this.element.setAttribute("aria-hidden",!0),this.element.setAttribute("role","dialog"),this.content.setAttribute("role","document")},i.prototype._ensureBodyChild=function(){this.element.parentNode!==document.body&&document.body.appendChild(this.element)},i.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=a.add(e)}},i.prototype._getScrollbarOffset=function(){var e=this.element.scrollHeight>document.documentElement.clientHeight;return this._hasBodyScrollbar&&!e?i.SCROLLBAR_WIDTH:0},i.prototype.onClick=function(e){this.options.dismissable&&e.target===this.element&&this.close()},i.prototype.onKeyPress=function(e){this.options.dismissable&&e.which===i.Keys.ESC&&this.close(),e.which===i.Keys.TAB&&i._trapTabKey(this.element,e)},i.prototype.onResize=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.innerHeight;this.element.style.height=e+"px"},i.prototype.open=function(){var e=this,o=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!this.isAnimating&&!this.isOpen){var n=window.innerHeight;i.focusedBeforeDialog=document.activeElement,this._hasBodyScrollbar=document.body.clientWidth<window.innerWidth,this._isFullscreen=this.element.classList.contains(i.Classes.FULLSCREEN);var s=i._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)}),this.isOpen=!0,this.onResize(n),this.element.removeAttribute("aria-hidden"),this.element.classList.add(i.Classes.OPEN),this.element.classList.add(i.Classes.ENTER),i.SCROLLBAR_WIDTH&&(document.body.style.paddingRight=i.SCROLLBAR_WIDTH+"px"),document.body.classList.add(i.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(t){t.addEventListener("click",e.close)}),!0===o?(this._openNext(),this._opened()):i._nextFrame(function(){e._openNext(),t.animation.onTransitionEnd(e.element,e._opened,e,null,1e3)})}},i.prototype._openNext=function(){this.isAnimating=!0;var e=this._getScrollbarOffset();!this._isFullscreen&&e>0&&(this.element.style.paddingRight=e+"px"),this.element.classList.remove(i.Classes.ENTER),this.element.classList.add(i.Classes.ENTERING)},i.prototype._opened=function(){this.element.classList.remove(i.Classes.ENTERING),this.element.classList.add(i.Classes.VISIBLE),this.isAnimating=!1,this.emit(i.EventType.OPENED)},i.prototype.close=function(){var e=this,o=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!this.isAnimating&&this.isOpen){var n=i._getSiblings(this.element),s=n.map(function(e){return e.getAttribute("data-odo-dialog-original")});n.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(i.Classes.LEAVE),this.element.classList.remove(i.Classes.VISIBLE),a.remove(this._scrollFixId),i.focusedBeforeDialog&&"function"==typeof i.focusedBeforeDialog.focus&&i.focusedBeforeDialog.focus(),document.removeEventListener("keydown",this.onKeyPress),window.removeEventListener("resize",this.onWindowResize),this.element.removeEventListener("click",this.onClick),this._closers.forEach(function(t){t.removeEventListener("click",e.close)}),!0===o?(this._closeNext(),this._closed()):i._nextFrame(function(){e._closeNext(),t.animation.onTransitionEnd(e.element,e._closed,e,null,1e3)})}},i.prototype._closeNext=function(){this.isAnimating=!0,this.element.classList.remove(i.Classes.LEAVE),this.element.classList.add(i.Classes.LEAVING)},i.prototype._closed=function(){this.isAnimating=!1,this.element.style.paddingRight="",this.element.setAttribute("aria-hidden",!0),this.element.classList.remove(i.Classes.OPEN),this.element.classList.remove(i.Classes.LEAVING),document.body.style.paddingRight="",document.body.classList.remove(i.Classes.BODY_OPEN),document.body.removeChild(this.backdrop),this.emit(i.EventType.CLOSED)},i.prototype.dispose=function(){this.isOpen&&this.close(!0),this.element=null,this.content=null,this.backdrop=null,this._closers.length=0,t.array.remove(i.Instances,this),0===i.Instances.length&&document.body.removeEventListener("click",i._handleTriggerClick)},i._nextFrame=function(e){window.requestAnimationFrame(window.requestAnimationFrame.bind(null,e))},i._handleTriggerClick=function(e){var t=e.target.closest("[data-odo-dialog-open]");if(null!==t){e.preventDefault();var o=t.getAttribute("data-odo-dialog-open"),n=i.getDialogById(o);n.emit(i.EventType.TRIGGER_CLICKED,t),n.open()}},i._trapTabKey=function(e,t){var o=i._getFocusableChildren(e),n=o.indexOf(document.activeElement);t.shiftKey&&0===n?(o[o.length-1].focus(),t.preventDefault()):t.shiftKey||n!==o.length-1||(o[0].focus(),t.preventDefault())},i._getFocusableChildren=function(e){return Array.from(e.querySelectorAll(d)).filter(i._isVisibleElement)},i._isVisibleElement=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},i._getSiblings=function(e){var t=["script","link","meta"];return Array.from(e.parentNode.children).filter(function(i){return i!==e&&!t.includes(i.nodeName.toLowerCase())})},i._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},i._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 i=t.offsetTop>0;return document.body.removeChild(e),i},i.initializeAll=function(e){return i.disposeAll(),Array.from(document.querySelectorAll("."+i.Classes.BASE)).map(function(t){return new i(t,e)})},i.disposeAll=function(){i.Instances.slice().forEach(function(e){e.dispose()})},i.getDialogById=function(e){return i.Instances.find(function(t){return t.id===e})},i}(e);return c.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"},c.EventType={OPENED:"ododialog:open",CLOSED:"ododialog:closed",TRIGGER_CLICKED:"ododialog:triggerclicked"},c.Keys={ESC:27,TAB:9},c.Defaults={dismissable:!0,scrollableElement:".odo-dialog"},c.Instances=[],c.ScrollFix=a,c.focusedBeforeDialog=null,c.SUPPORTS_AUTO_MARGINS=c._autoMarginTest(),c.SCROLLBAR_WIDTH=c._getScrollbarWidth(),c}); | ||
//# sourceMappingURL=odo-dialog.min.js.map |
{ | ||
"name": "@odopod/odo-dialog", | ||
"description": "Responsive window dialog component focused on a11y and extendibility", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"main": "dist/odo-dialog.js", | ||
@@ -26,3 +26,3 @@ "style": "css/odo-dialog.css", | ||
"src", | ||
"index.js" | ||
"index.d.ts" | ||
], | ||
@@ -29,0 +29,0 @@ "odoKeywords": [ |
@@ -23,2 +23,2 @@ # Odo Dialog | ||
[permalink]: https://odopod.github.io/odo/odo-dialog/ | ||
[permalink]: https://code.odopod.com/odo-dialog/ |
@@ -30,9 +30,9 @@ /** | ||
/** | ||
* Dialog that can contain static images, carousels, or videos | ||
* @param {Element} element Main element. | ||
* | ||
* @constructor | ||
*/ | ||
class Dialog extends TinyEmitter { | ||
/** | ||
* Dialog that can contain static images, carousels, or videos | ||
* @param {Element} element Main element. | ||
* @param {object} [opts] Instance options. | ||
* @constructor | ||
*/ | ||
constructor(element, opts) { | ||
@@ -51,2 +51,6 @@ super(); | ||
/** | ||
* Options object. | ||
* @type {object} | ||
*/ | ||
this.options = Object.assign({}, Dialog.Defaults, opts); | ||
@@ -142,2 +146,3 @@ | ||
this._bindContexts(); | ||
this.onResize(); | ||
this._addA11yAttributes(); | ||
@@ -163,2 +168,5 @@ this._ensureBodyChild(); | ||
this.close = this.close.bind(this); | ||
// Bind undefined as the first parameter so that the event object will be | ||
// the second parameter and the optional viewportHeight parameter will work. | ||
this.onWindowResize = this.onResize.bind(this, undefined); | ||
} | ||
@@ -242,2 +250,15 @@ | ||
/** | ||
* The dialog has a height of 100vh, which, in mobile safari, is incorrect | ||
* when the toolbars are visible, not allowing the user to scroll the full | ||
* height of the content within it. | ||
* The viewportHeight parameter is optional so that it can be read in the open() | ||
* method with all the other DOM reads. This avoids read->write->read #perfmatters. | ||
* @param {number} [viewportHeight=window.innerHeight] Height of the viewport. | ||
* @protected | ||
*/ | ||
onResize(viewportHeight = window.innerHeight) { | ||
this.element.style.height = viewportHeight + 'px'; | ||
} | ||
/** | ||
* Checks to see if a dialog is already open or animating If not, opens dialog. | ||
@@ -251,2 +272,3 @@ * @param {boolean} [sync=false] Whether to open with transitions or not. | ||
const viewportHeight = window.innerHeight; | ||
Dialog.focusedBeforeDialog = document.activeElement; | ||
@@ -267,2 +289,3 @@ this._hasBodyScrollbar = document.body.clientWidth < window.innerWidth; | ||
this.isOpen = true; | ||
this.onResize(viewportHeight); | ||
this.element.removeAttribute('aria-hidden'); | ||
@@ -283,2 +306,3 @@ this.element.classList.add(Dialog.Classes.OPEN); | ||
document.addEventListener('keydown', this.onKeyPress); | ||
window.addEventListener('resize', this.onWindowResize); | ||
this.element.addEventListener('click', this.onClick); | ||
@@ -352,3 +376,6 @@ this._closers.forEach((element) => { | ||
if (Dialog.focusedBeforeDialog) { | ||
// Support: IE11 | ||
// Clicking on an SVG element inside an <a> will set the `focusedBeforeDialog` | ||
// to the SVG, but SVG doesn't have a `focus()` method in IE. | ||
if (Dialog.focusedBeforeDialog && typeof Dialog.focusedBeforeDialog.focus === 'function') { | ||
Dialog.focusedBeforeDialog.focus(); | ||
@@ -358,2 +385,3 @@ } | ||
document.removeEventListener('keydown', this.onKeyPress); | ||
window.removeEventListener('resize', this.onWindowResize); | ||
this.element.removeEventListener('click', this.onClick); | ||
@@ -400,4 +428,3 @@ this._closers.forEach((element) => { | ||
/** | ||
* Disposes of global Dialog variables | ||
* @public | ||
* Close the dialog, remove event listeners and element references. | ||
*/ | ||
@@ -438,8 +465,10 @@ dispose() { | ||
static _handleTriggerClick(evt) { | ||
const elem = evt.target.closest('[data-odo-dialog-open]'); | ||
const trigger = evt.target.closest('[data-odo-dialog-open]'); | ||
if (elem !== null) { | ||
if (trigger !== null) { | ||
evt.preventDefault(); | ||
const id = elem.getAttribute('data-odo-dialog-open'); | ||
Dialog.getDialogById(id).open(); | ||
const id = trigger.getAttribute('data-odo-dialog-open'); | ||
const instance = Dialog.getDialogById(id); | ||
instance.emit(Dialog.EventType.TRIGGER_CLICKED, trigger); | ||
instance.open(); | ||
} | ||
@@ -550,4 +579,3 @@ } | ||
* @param {Object} options Object of all dialog options. Is optional. | ||
* @return {Array.<Dialog>} | ||
* @public | ||
* @return {Dialog[]} | ||
*/ | ||
@@ -563,5 +591,3 @@ static initializeAll(options) { | ||
/** | ||
* Clear all references to dialogs so there are no duplicates | ||
* @param {Object} options Object of all dialog options. Is optional. | ||
* @public | ||
* Clear all references to dialogs so there are no duplicates. | ||
*/ | ||
@@ -605,2 +631,3 @@ static disposeAll() { | ||
CLOSED: 'ododialog:closed', | ||
TRIGGER_CLICKED: 'ododialog:triggerclicked', | ||
}; | ||
@@ -620,3 +647,3 @@ | ||
/** @enum {Array} */ | ||
/** @enum {Dialog[]} */ | ||
Dialog.Instances = []; | ||
@@ -623,0 +650,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
1
139589
1725