Skip to content

Commit

Permalink
Fixed #5130 - Add focusOnHover props to some components
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Jan 23, 2024
1 parent f0880cd commit 2072631
Show file tree
Hide file tree
Showing 18 changed files with 354 additions and 187 deletions.
12 changes: 6 additions & 6 deletions components/lib/api/FilterService.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const FilterService = {
},
filters: {
startsWith(value, filter, filterLocale) {
if (filter === undefined || filter === null || filter.trim() === '') {
if (filter === undefined || filter === null || filter === '') {
return true;
}

Expand All @@ -44,7 +44,7 @@ const FilterService = {
return stringValue.slice(0, filterValue.length) === filterValue;
},
contains(value, filter, filterLocale) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
if (filter === undefined || filter === null || filter === '') {
return true;
}

Expand All @@ -58,7 +58,7 @@ const FilterService = {
return stringValue.indexOf(filterValue) !== -1;
},
notContains(value, filter, filterLocale) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
if (filter === undefined || filter === null || filter === '') {
return true;
}

Expand All @@ -72,7 +72,7 @@ const FilterService = {
return stringValue.indexOf(filterValue) === -1;
},
endsWith(value, filter, filterLocale) {
if (filter === undefined || filter === null || filter.trim() === '') {
if (filter === undefined || filter === null || filter === '') {
return true;
}

Expand All @@ -86,7 +86,7 @@ const FilterService = {
return stringValue.indexOf(filterValue, stringValue.length - filterValue.length) !== -1;
},
equals(value, filter, filterLocale) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
if (filter === undefined || filter === null || filter === '') {
return true;
}

Expand All @@ -98,7 +98,7 @@ const FilterService = {
else return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) == ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
},
notEquals(value, filter, filterLocale) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
if (filter === undefined || filter === null || filter === '') {
return false;
}

Expand Down
5 changes: 5 additions & 0 deletions components/lib/autocomplete/AutoComplete.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,11 @@ export interface AutoCompleteProps {
* @defaultValue false
*/
selectOnFocus?: boolean | undefined;
/**
* When enabled, the focus is placed on the hovered option.
* @defaultValue true
*/
focusOnHover?: boolean | undefined;
/**
* Locale to use in searching. The default locale is the host environment's current locale.
*/
Expand Down
36 changes: 23 additions & 13 deletions components/lib/autocomplete/AutoComplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ export default {
overlay: null,
virtualScroller: null,
searchTimeout: null,
focusOnHover: false,
dirty: false,
data() {
return {
id: this.$attrs.id,
clicked: false,
focused: false,
focusedOptionIndex: -1,
focusedMultipleOptionIndex: -1,
Expand Down Expand Up @@ -298,6 +298,7 @@ export default {
this.$emit('before-hide');
this.dirty = isFocus;
this.overlayVisible = false;
this.clicked = false;
this.focusedOptionIndex = -1;
isFocus && DomHandler.focus(this.$refs.focusInput);
Expand All @@ -319,8 +320,12 @@ export default {
this.dirty = true;
this.focused = true;
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
this.overlayVisible && this.scrollInView(this.focusedOptionIndex);
if (this.overlayVisible) {
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
this.scrollInView(this.focusedOptionIndex);
}
this.$emit('focus', event);
},
onBlur(event) {
Expand Down Expand Up @@ -394,6 +399,8 @@ export default {
default:
break;
}
this.clicked = false;
},
onInput(event) {
if (this.searchTimeout) {
Expand Down Expand Up @@ -479,6 +486,8 @@ export default {
}
},
onContainerClick(event) {
this.clicked = true;
if (this.disabled || this.searching || this.loading || this.isInputClicked(event) || this.isDropdownClicked(event)) {
return;
}
Expand Down Expand Up @@ -545,7 +554,7 @@ export default {
return;
}
const optionIndex = this.focusedOptionIndex !== -1 ? this.findNextOptionIndex(this.focusedOptionIndex) : this.findFirstFocusedOptionIndex();
const optionIndex = this.focusedOptionIndex !== -1 ? this.findNextOptionIndex(this.focusedOptionIndex) : this.clicked ? this.findFirstOptionIndex() : this.findFirstFocusedOptionIndex();
this.changeFocusedOptionIndex(event, optionIndex);
Expand All @@ -564,7 +573,7 @@ export default {
this.overlayVisible && this.hide();
event.preventDefault();
} else {
const optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.findLastFocusedOptionIndex();
const optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.clicked ? this.findLastOptionIndex() : this.findLastFocusedOptionIndex();
this.changeFocusedOptionIndex(event, optionIndex);
Expand Down Expand Up @@ -618,6 +627,7 @@ export default {
},
onEnterKey(event) {
if (!this.overlayVisible) {
this.focusedOptionIndex = -1; // reset
this.onArrowDownKey(event);
} else {
if (this.focusedOptionIndex !== -1) {
Expand Down Expand Up @@ -838,16 +848,16 @@ export default {
}
},
scrollInView(index = -1) {
const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
this.$nextTick(() => {
const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
if (element) {
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
} else if (!this.virtualScrollerDisabled) {
setTimeout(() => {
if (element) {
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
} else if (!this.virtualScrollerDisabled) {
this.virtualScroller && this.virtualScroller.scrollToIndex(index !== -1 ? index : this.focusedOptionIndex);
}, 0);
}
}
});
},
autoUpdateModel() {
if ((this.selectOnFocus || this.autoHighlight) && this.autoOptionFocus && !this.hasSelectedOption) {
Expand Down
4 changes: 4 additions & 0 deletions components/lib/autocomplete/BaseAutoComplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ export default {
type: Boolean,
default: false
},
focusOnHover: {
type: Boolean,
default: true
},
searchLocale: {
type: String,
default: undefined
Expand Down
4 changes: 4 additions & 0 deletions components/lib/cascadeselect/BaseCascadeSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ export default {
type: Boolean,
default: false
},
focusOnHover: {
type: Boolean,
default: true
},
searchLocale: {
type: String,
default: undefined
Expand Down
5 changes: 5 additions & 0 deletions components/lib/cascadeselect/CascadeSelect.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ export interface CascadeSelectProps {
* @defaultValue false
*/
selectOnFocus?: boolean | undefined;
/**
* When enabled, the focus is placed on the hovered option.
* @defaultValue true
*/
focusOnHover?: boolean | undefined;
/**
* Locale to use in searching. The default locale is the host environment's current locale.
*/
Expand Down
76 changes: 49 additions & 27 deletions components/lib/cascadeselect/CascadeSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
:optionGroupLabel="optionGroupLabel"
:optionGroupChildren="optionGroupChildren"
@option-change="onOptionChange"
@option-focus-change="onOptionFocusChange"
:pt="pt"
:unstyled="unstyled"
/>
Expand Down Expand Up @@ -95,10 +96,10 @@ export default {
overlay: null,
searchTimeout: null,
searchValue: null,
focusOnHover: false,
data() {
return {
id: this.$attrs.id,
clicked: false,
focused: false,
focusedOptionInfo: { index: -1, level: 0, parentKey: '' },
activeOptionPath: [],
Expand Down Expand Up @@ -169,9 +170,9 @@ export default {
if (this.hasSelectedOption && ObjectUtils.isNotEmpty(this.activeOptionPath)) {
const processedOption = this.activeOptionPath[this.activeOptionPath.length - 1];
this.focusedOptionInfo = { index: this.autoOptionFocus ? processedOption.index : -1, level: processedOption.level, parentKey: processedOption.parentKey };
this.focusedOptionInfo = { index: processedOption.index, level: processedOption.level, parentKey: processedOption.parentKey };
} else {
this.focusedOptionInfo = { index: this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1, level: 0, parentKey: '' };
this.focusedOptionInfo = { index: this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : this.findSelectedOptionIndex(), level: 0, parentKey: '' };
}
isFocus && DomHandler.focus(this.$refs.focusInput);
Expand All @@ -180,6 +181,7 @@ export default {
const _hide = () => {
this.$emit('before-hide');
this.overlayVisible = false;
this.clicked = false;
this.activeOptionPath = [];
this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' };
Expand Down Expand Up @@ -272,6 +274,8 @@ export default {
break;
}
this.clicked = false;
},
onOptionChange(event) {
const { originalEvent, processedOption, isFocus, isHide } = event;
Expand All @@ -285,12 +289,21 @@ export default {
activeOptionPath.push(processedOption);
this.focusedOptionInfo = originalEvent?.type === 'click' ? { index: -1, level, parentKey } : { index, level, parentKey };
this.focusedOptionInfo = { index, level, parentKey };
this.activeOptionPath = activeOptionPath;
grouped ? this.onOptionGroupSelect(originalEvent, processedOption) : this.onOptionSelect(originalEvent, processedOption, isHide);
isFocus && DomHandler.focus(this.$refs.focusInput);
},
onOptionFocusChange(event) {
if (this.focusOnHover) {
const { originalEvent, processedOption } = event;
const { index, level, parentKey } = processedOption;
this.focusedOptionInfo = { index, level, parentKey };
this.changeFocusedOptionIndex(originalEvent, index);
}
},
onOptionSelect(event, processedOption, isHide = true) {
const value = this.getOptionValue(processedOption?.option);
Expand All @@ -312,6 +325,7 @@ export default {
DomHandler.focus(this.$refs.focusInput);
}
this.clicked = true;
this.$emit('click', event);
},
onOverlayClick(event) {
Expand All @@ -331,11 +345,14 @@ export default {
}
},
onArrowDownKey(event) {
const optionIndex = this.focusedOptionInfo.index !== -1 ? this.findNextOptionIndex(this.focusedOptionInfo.index) : this.findFirstFocusedOptionIndex();
if (!this.overlayVisible) {
this.show();
} else {
const optionIndex = this.focusedOptionInfo.index !== -1 ? this.findNextOptionIndex(this.focusedOptionInfo.index) : this.clicked ? this.findFirstOptionIndex() : this.findFirstFocusedOptionIndex();
this.changeFocusedOptionIndex(event, optionIndex);
this.changeFocusedOptionIndex(event, optionIndex);
}
!this.overlayVisible && this.show();
event.preventDefault();
},
onArrowUpKey(event) {
Expand All @@ -350,7 +367,7 @@ export default {
this.overlayVisible && this.hide();
event.preventDefault();
} else {
const optionIndex = this.focusedOptionInfo.index !== -1 ? this.findPrevOptionIndex(this.focusedOptionInfo.index) : this.findLastFocusedOptionIndex();
const optionIndex = this.focusedOptionInfo.index !== -1 ? this.findPrevOptionIndex(this.focusedOptionInfo.index) : this.clicked ? this.findLastOptionIndex() : this.findLastFocusedOptionIndex();
this.changeFocusedOptionIndex(event, optionIndex);
Expand Down Expand Up @@ -412,6 +429,7 @@ export default {
},
onEnterKey(event) {
if (!this.overlayVisible) {
this.focusedOptionInfo.index !== -1; // reset
this.onArrowDownKey(event);
} else {
if (this.focusedOptionInfo.index !== -1) {
Expand Down Expand Up @@ -595,23 +613,25 @@ export default {
let optionIndex = -1;
let matched = false;
if (this.focusedOptionInfo.index !== -1) {
optionIndex = this.visibleOptions.slice(this.focusedOptionInfo.index).findIndex((processedOption) => this.isOptionMatched(processedOption));
optionIndex = optionIndex === -1 ? this.visibleOptions.slice(0, this.focusedOptionInfo.index).findIndex((processedOption) => this.isOptionMatched(processedOption)) : optionIndex + this.focusedOptionInfo.index;
} else {
optionIndex = this.visibleOptions.findIndex((processedOption) => this.isOptionMatched(processedOption));
}
if (ObjectUtils.isNotEmpty(this.searchValue)) {
if (this.focusedOptionInfo.index !== -1) {
optionIndex = this.visibleOptions.slice(this.focusedOptionInfo.index).findIndex((processedOption) => this.isOptionMatched(processedOption));
optionIndex = optionIndex === -1 ? this.visibleOptions.slice(0, this.focusedOptionInfo.index).findIndex((processedOption) => this.isOptionMatched(processedOption)) : optionIndex + this.focusedOptionInfo.index;
} else {
optionIndex = this.visibleOptions.findIndex((processedOption) => this.isOptionMatched(processedOption));
}
if (optionIndex !== -1) {
matched = true;
}
if (optionIndex !== -1) {
matched = true;
}
if (optionIndex === -1 && this.focusedOptionInfo.index === -1) {
optionIndex = this.findFirstFocusedOptionIndex();
}
if (optionIndex === -1 && this.focusedOptionInfo.index === -1) {
optionIndex = this.findFirstFocusedOptionIndex();
}
if (optionIndex !== -1) {
this.changeFocusedOptionIndex(event, optionIndex);
if (optionIndex !== -1) {
this.changeFocusedOptionIndex(event, optionIndex);
}
}
if (this.searchTimeout) {
Expand All @@ -636,12 +656,14 @@ export default {
}
},
scrollInView(index = -1) {
const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
this.$nextTick(() => {
const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
if (element) {
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
}
if (element) {
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
}
});
},
autoUpdateModel() {
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
Expand Down
Loading

0 comments on commit 2072631

Please sign in to comment.