From 5ed1341cff9a3e95370a9854cf582b1d54d92d7e Mon Sep 17 00:00:00 2001 From: mertsincan Date: Thu, 1 Sep 2022 00:34:50 +0100 Subject: [PATCH] Fixed #2918 - Improve focus method to Components --- src/components/accordion/Accordion.vue | 2 +- src/components/autocomplete/AutoComplete.vue | 14 +++++++------- src/components/cascadeselect/CascadeSelect.vue | 8 ++++---- src/components/listbox/Listbox.vue | 6 +++--- src/components/tabview/TabView.vue | 2 +- src/components/utils/DomHandler.js | 4 ++++ src/components/utils/Utils.d.ts | 1 + 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/components/accordion/Accordion.vue b/src/components/accordion/Accordion.vue index 4134d9554..4e5fb537f 100755 --- a/src/components/accordion/Accordion.vue +++ b/src/components/accordion/Accordion.vue @@ -196,7 +196,7 @@ export default { }, changeFocusedTab(event, element) { if (element) { - element.focus(); + DomHandler.focus(element); if (this.selectOnFocus) { const index = parseInt(element.parentElement.parentElement.dataset.index, 10); diff --git a/src/components/autocomplete/AutoComplete.vue b/src/components/autocomplete/AutoComplete.vue index 31782caab..ce5ebe53e 100755 --- a/src/components/autocomplete/AutoComplete.vue +++ b/src/components/autocomplete/AutoComplete.vue @@ -278,7 +278,7 @@ export default { this.overlayVisible = true; this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1); - isFocus && this.$refs.focusInput.focus(); + isFocus && DomHandler.focus(this.$refs.focusInput); }, hide(isFocus) { const _hide = () => { @@ -287,7 +287,7 @@ export default { this.overlayVisible = false; this.focusedOptionIndex = -1; - isFocus && this.$refs.focusInput && this.$refs.focusInput.focus(); + isFocus && DomHandler.focus(this.$refs.focusInput); } setTimeout(() => { _hide() }, 0); // For ScreenReaders @@ -446,7 +446,7 @@ export default { } if (!this.overlay || !this.overlay.contains(event.target)) { - this.$refs.focusInput.focus(); + DomHandler.focus(this.$refs.focusInput); } }, onDropdownClick(event) { @@ -456,7 +456,7 @@ export default { this.hide(true); } else { - this.$refs.focusInput.focus(); + DomHandler.focus(this.$refs.focusInput); query = this.$refs.focusInput.value; if (this.dropdownMode === 'blank') @@ -544,7 +544,7 @@ export default { if (this.multiple) { if (ObjectUtils.isEmpty(target.value) && this.hasSelectedOption) { - this.$refs.multiContainer.focus(); + DomHandler.focus(this.$refs.multiContainer); this.focusedMultipleOptionIndex = this.modelValue.length; } else { @@ -625,7 +625,7 @@ export default { if (this.focusedMultipleOptionIndex > (this.modelValue.length - 1)) { this.focusedMultipleOptionIndex = -1; - this.$refs.focusInput.focus(); + DomHandler.focus(this.$refs.focusInput); } }, onBackspaceKeyOnMultiple(event) { @@ -783,7 +783,7 @@ export default { this.updateModel(event, value); this.$emit('item-unselect', { originalEvent: event, value: removedOption }); this.dirty = true; - this.$refs.focusInput.focus(); + DomHandler.focus(this.$refs.focusInput); }, changeFocusedOptionIndex(event, index) { if (this.focusedOptionIndex !== index) { diff --git a/src/components/cascadeselect/CascadeSelect.vue b/src/components/cascadeselect/CascadeSelect.vue index 9fcbd7978..95dd3dab7 100644 --- a/src/components/cascadeselect/CascadeSelect.vue +++ b/src/components/cascadeselect/CascadeSelect.vue @@ -200,7 +200,7 @@ export default { this.focusedOptionInfo = { index: (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1), level: 0, parentKey: '' }; } - isFocus && this.$refs.focusInput.focus(); + isFocus && DomHandler.focus(this.$refs.focusInput); }, hide(isFocus) { const _hide = () => { @@ -209,7 +209,7 @@ export default { this.activeOptionPath = []; this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' }; - isFocus && this.$refs.focusInput && this.$refs.focusInput.focus(); + isFocus && DomHandler.focus(this.$refs.focusInput); } setTimeout(() => { _hide() }, 0); // For ScreenReaders @@ -305,7 +305,7 @@ export default { this.activeOptionPath = activeOptionPath; grouped ? this.onOptionGroupSelect(originalEvent, processedOption) : this.onOptionSelect(originalEvent, processedOption, isHide); - isFocus && this.$refs.focusInput.focus(); + isFocus && DomHandler.focus(this.$refs.focusInput); }, onOptionSelect(event, processedOption, isHide = true) { const value = this.getOptionValue(processedOption.option); @@ -325,7 +325,7 @@ export default { if (!this.overlay || !this.overlay.contains(event.target)) { this.overlayVisible ? this.hide() : this.show(); - this.$refs.focusInput.focus(); + DomHandler.focus(this.$refs.focusInput); } this.$emit('click', event); diff --git a/src/components/listbox/Listbox.vue b/src/components/listbox/Listbox.vue index 8460e59e0..ec2b77233 100755 --- a/src/components/listbox/Listbox.vue +++ b/src/components/listbox/Listbox.vue @@ -187,7 +187,7 @@ export default { return (this.optionGroupLabel ? index - this.visibleOptions.slice(0, index).filter(option => this.isOptionGroup(option)).length : index) + 1; }, onFirstHiddenFocus() { - this.list.focus(); + DomHandler.focus(this.list); const firstFocusableEl = DomHandler.getFirstFocusableElement(this.$el, ':not(.p-hidden-focusable)'); this.$refs.lastHiddenFocusableElement.tabIndex = ObjectUtils.isEmpty(firstFocusableEl) ? -1 : undefined; @@ -198,11 +198,11 @@ export default { if (relatedTarget === this.list) { const firstFocusableEl = DomHandler.getFirstFocusableElement(this.$el, ':not(.p-hidden-focusable)'); - firstFocusableEl && firstFocusableEl.focus(); + DomHandler.focus(firstFocusableEl); this.$refs.firstHiddenFocusableElement.tabIndex = undefined; } else { - this.$refs.firstHiddenFocusableElement.focus(); + DomHandler.focus(this.$refs.firstHiddenFocusableElement); } this.$refs.lastHiddenFocusableElement.tabIndex = -1; diff --git a/src/components/tabview/TabView.vue b/src/components/tabview/TabView.vue index 5e7787414..606879761 100755 --- a/src/components/tabview/TabView.vue +++ b/src/components/tabview/TabView.vue @@ -231,7 +231,7 @@ export default { }, changeFocusedTab(event, element) { if (element) { - element.focus(); + DomHandler.focus(element); this.scrollInView({ element }); if (this.selectOnFocus) { diff --git a/src/components/utils/DomHandler.js b/src/components/utils/DomHandler.js index acd99b059..0a31699bf 100755 --- a/src/components/utils/DomHandler.js +++ b/src/components/utils/DomHandler.js @@ -503,6 +503,10 @@ export default { return !!(typeof window !== 'undefined' && window.document && window.document.createElement); }, + focus(el, options) { + el && document.activeElement !== el && el.focus(options); + }, + getFocusableElements(element, selector = '') { let focusableElements = this.find(element, `button:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden])${selector}, [href][clientHeight][clientWidth]:not([tabindex = "-1"]):not([disabled]):not([style*="display:none"]):not([hidden])${selector}, diff --git a/src/components/utils/Utils.d.ts b/src/components/utils/Utils.d.ts index 64eb332da..c122c2de8 100644 --- a/src/components/utils/Utils.d.ts +++ b/src/components/utils/Utils.d.ts @@ -44,6 +44,7 @@ export declare class DomHandler { static invokeElementMethod(el: HTMLElement, methodName: string, args: any): void; static isExist(el: HTMLElement): boolean; static isClient(): boolean; + static focus(el: HTMLElement, options?: FocusOptions): void; static getFocusableElements(el: HTMLElement, selector?: string): any[]; static getFirstFocusableElement(el: HTMLElement, selector?: string): any; static isClickable(el: HTMLElement): boolean;