Skip to content

Commit

Permalink
Fixed #3342 - Improve search operation on PanelMenu
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Nov 28, 2022
1 parent 23840ec commit 68c6b42
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/components/panelmenu/PanelMenuList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export default {
default: true
}
},
searchTimeout: null,
searchValue: null,
data() {
return {
focused: false,
Expand All @@ -66,6 +68,9 @@ export default {
getItemProp(processedItem, name) {
return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name]) : undefined;
},
getItemLabel(processedItem) {
return this.getItemProp(processedItem, 'label');
},
isItemVisible(processedItem) {
return this.getItemProp(processedItem, 'visible') !== false;
},
Expand All @@ -85,8 +90,11 @@ export default {
onBlur() {
this.focused = false;
this.focusedItem = null;
this.searchValue = '';
},
onKeyDown(event) {
const metaKey = event.metaKey || event.ctrlKey;
switch (event.code) {
case 'ArrowDown':
this.onArrowDownKey(event);
Expand Down Expand Up @@ -131,6 +139,10 @@ export default {
break;
default:
if (!metaKey && ObjectUtils.isPrintableCharacter(event.key)) {
this.searchItems(event, event.key);
}
break;
}
},
Expand Down Expand Up @@ -216,6 +228,9 @@ export default {
return panel && panel.contains(element);
},
isItemMatched(processedItem) {
return this.isValidItem(processedItem) && this.getItemLabel(processedItem).toLocaleLowerCase(this.searchLocale).startsWith(this.searchValue.toLocaleLowerCase(this.searchLocale));
},
isVisibleItem(processedItem) {
return !!processedItem && (processedItem.level === 0 || this.isItemActive(processedItem)) && this.isItemVisible(processedItem);
},
Expand All @@ -240,6 +255,48 @@ export default {
return matchedItem || processedItem;
},
searchItems(event, char) {
this.searchValue = (this.searchValue || '') + char;
let matchedItem = null;
let matched = false;
if (ObjectUtils.isNotEmpty(this.focusedItem)) {
const focusedItemIndex = this.visibleItems.findIndex((processedItem) => processedItem.key === this.focusedItem.key);
matchedItem = this.visibleItems.slice(focusedItemIndex).find((processedItem) => this.isItemMatched(processedItem));
matchedItem = ObjectUtils.isEmpty(matchedItem) ? this.visibleItems.slice(0, focusedItemIndex).find((processedItem) => this.isItemMatched(processedItem)) : matchedItem;
} else {
matchedItem = this.visibleItems.find((processedItem) => this.isItemMatched(processedItem));
}
if (ObjectUtils.isNotEmpty(matchedItem)) {
matched = true;
}
if (ObjectUtils.isEmpty(matchedItem) && ObjectUtils.isEmpty(this.focusedItem)) {
matchedItem = this.findFirstItem();
}
if (ObjectUtils.isNotEmpty(matchedItem)) {
this.changeFocusedItem({
originalEvent: event,
processedItem: matchedItem,
allowHeaderFocus: false
});
}
if (this.searchTimeout) {
clearTimeout(this.searchTimeout);
}
this.searchTimeout = setTimeout(() => {
this.searchValue = '';
this.searchTimeout = null;
}, 500);
return matched;
},
changeFocusedItem(event) {
const { originalEvent, processedItem, focusOnNext, selfCheck, allowHeaderFocus = true } = event;
Expand Down
4 changes: 4 additions & 0 deletions src/views/panelmenu/PanelMenuDoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,10 @@ export default {
</td>
<td>If node is open, closes the node otherwise moves focus to the parent node.</td>
</tr>
<tr>
<td><i>any printable character</i></td>
<td>Moves focus to the visible option whose label starts with the characters being typed.</td>
</tr>
</tbody>
</table>
</div>
Expand Down

0 comments on commit 68c6b42

Please sign in to comment.