From 98f9ab2579db9d1a0d8420340f2d33410d3d0199 Mon Sep 17 00:00:00 2001 From: cagataycivici Date: Fri, 1 Nov 2019 11:30:06 +0300 Subject: [PATCH] Fixed #77 - Modal dialog not blocking background --- src/components/dialog/Dialog.vue | 47 ++++++++++++++++++++++++++++++ src/components/utils/DomHandler.js | 17 +++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/components/dialog/Dialog.vue b/src/components/dialog/Dialog.vue index 786e8c4fa..9b90816b4 100644 --- a/src/components/dialog/Dialog.vue +++ b/src/components/dialog/Dialog.vue @@ -50,6 +50,10 @@ export default { } }, mask: null, + documentKeydownListener: null, + destroyed() { + //this.unbindDocumentKeydownListener(); + }, methods: { close() { this.$emit('update:visible', false); @@ -85,6 +89,7 @@ export default { DomHandler.addMultipleClasses(this.mask, 'p-component-overlay p-dialog-mask p-fadein'); document.body.appendChild(this.mask); DomHandler.addClass(document.body, 'p-overflow-hidden'); + this.bindDocumentKeydownListener(); } }, disableModality() { @@ -92,6 +97,48 @@ export default { document.body.removeChild(this.mask); DomHandler.removeClass(document.body, 'p-overflow-hidden'); this.mask = null; + this.unbindDocumentKeydownListener(); + } + }, + onKeyDown(event) { + if (event.which === 9) { + event.preventDefault(); + + let focusableElements = DomHandler.getFocusableElements(this.$refs.container); + + if (focusableElements && focusableElements.length > 0) { + if (!document.activeElement) { + focusableElements[0].focus(); + } + else { + let focusedIndex = focusableElements.indexOf(document.activeElement); + + if (event.shiftKey) { + if (focusedIndex == -1 || focusedIndex === 0) + focusableElements[focusableElements.length - 1].focus(); + else + focusableElements[focusedIndex - 1].focus(); + } + else { + if (focusedIndex == -1 || focusedIndex === (focusableElements.length - 1)) + focusableElements[0].focus(); + else + focusableElements[focusedIndex + 1].focus(); + } + } + } + } + }, + bindDocumentKeydownListener() { + if (!this.documentKeydownListener) { + this.documentKeydownListener = this.onKeyDown.bind(this); + window.document.addEventListener('keydown', this.documentKeydownListener); + } + }, + unbindDocumentKeydownListener() { + if (this.documentKeydownListener) { + window.document.removeEventListener('keydown', this.documentKeydownListener); + this.documentKeydownListener = null; } } }, diff --git a/src/components/utils/DomHandler.js b/src/components/utils/DomHandler.js index eabfc109e..eaba6ec64 100644 --- a/src/components/utils/DomHandler.js +++ b/src/components/utils/DomHandler.js @@ -384,4 +384,21 @@ export default class DomHandler { static invokeElementMethod(element, methodName, args) { (element)[methodName].apply(element, args); } + + static getFocusableElements(element) { + let focusableElements = DomHandler.find(element, `button:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden]), + [href][clientHeight][clientWidth]:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden]), + input:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden]), select:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden]), + textarea:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden]), [tabIndex]:not([tabIndex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden]), + [contenteditable]:not([tabIndex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden])` + ); + + let visibleFocusableElements = []; + for (let focusableElement of focusableElements) { + if (getComputedStyle(focusableElement).display != "none" && getComputedStyle(focusableElement).visibility != "hidden") + visibleFocusableElements.push(focusableElement); + } + + return visibleFocusableElements; + } } \ No newline at end of file