Skip to content

Commit ae793e0

Browse files
committed
fix: be more tolerant of slow computers when focusing the search input on open
1 parent 8aebeb8 commit ae793e0

File tree

2 files changed

+31
-34
lines changed

2 files changed

+31
-34
lines changed

playground/Coalesce.Web.Vue3/src/components/test-setup.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<template>
22
<v-container>
3+
<c-select
4+
for="Person"
5+
:params="{ pageSize: 400 }"
6+
v-model="vm.assignedTo"
7+
></c-select>
8+
39
<v-btn @click="add" prepend-icon="fa fa-plus"> Add Product </v-btn>
410
<v-btn
511
@click="vm.$bulkSave()"

src/coalesce-vue-vuetify3/src/components/input/c-select.vue

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
<v-text-field
105105
ref="searchRef"
106106
v-model="search"
107+
v-intersect="onSearchIntersect"
107108
hide-details="auto"
108109
prepend-inner-icon="fa fa-search"
109110
:loading="listCaller.isLoading"
@@ -548,13 +549,13 @@ const { inputBindAttrs, valueMeta, valueOwner } = useMetadataProps(props, (v) =>
548549
549550
const search = ref(null as string | null);
550551
const menuOpen = ref(false);
551-
const menuOpenForced = ref(false);
552552
const searchChanged = ref(new Date());
553553
const mainValue = ref("");
554554
const createItemLoading = ref(false);
555555
const createItemError = ref("" as string | null);
556556
const pendingSelection = ref(0);
557557
const selectionIndex = ref(-1);
558+
const pendingSearchSelect = ref(false);
558559
559560
/** The models representing the current selected item(s)
560561
* in the case that only the PK was provided to the component.
@@ -1230,49 +1231,41 @@ function onIntersect(isIntersecting: boolean) {
12301231
}, 50);
12311232
}
12321233
1234+
async function onSearchIntersect(isIntersecting: boolean) {
1235+
if (!isIntersecting) return;
1236+
1237+
const input = searchRef.value?.$el.querySelector("input") as HTMLInputElement;
1238+
if (!input) return;
1239+
1240+
await nextTick();
1241+
await new Promise((resolve) => setTimeout(resolve, 25));
1242+
1243+
input.focus();
1244+
1245+
if (pendingSearchSelect.value) {
1246+
input.select();
1247+
pendingSearchSelect.value = false;
1248+
}
1249+
}
1250+
12331251
async function openMenu(select?: boolean): Promise<void> {
12341252
if (!isInteractive.value || forceClosed) return;
12351253
1254+
if (menuOpen.value) return;
1255+
menuOpen.value = true;
1256+
selectionIndex.value = -1; // Reset selection index when menu opens
1257+
12361258
if (select == undefined) {
12371259
// Select the whole search input if it hasn't changed recently.
12381260
// If it /has/ changed recently, it means the user is actively typing and probably
12391261
// doesn't want to use what they're typing.
12401262
select = new Date().valueOf() - searchChanged.value.valueOf() > 1000;
12411263
}
12421264
1243-
if (menuOpen.value) return;
1244-
menuOpen.value = true;
1245-
selectionIndex.value = -1; // Reset selection index when menu opens
1246-
12471265
if (props.reloadOnOpen) listCaller();
12481266
1249-
await nextTick();
1250-
const input = searchRef.value?.$el.querySelector("input") as HTMLInputElement;
1251-
1252-
// Wait for the menu fade-in animation to unhide the content root
1253-
// before we try to focus the search input, because otherwise it wont work.
1254-
// https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
1255-
const start = performance.now();
1256-
1257-
// Force the menu open while we wait, because otherwise if a user clicks and then rapidly types a character,
1258-
// the typed character will process before the click, resulting in the click toggling the menu closed
1259-
// after the typed character opened the menu.
1260-
menuOpenForced.value = true;
1261-
1262-
while (
1263-
// cap waiting
1264-
start + 500 > performance.now() &&
1265-
(!input.offsetParent || input != document.activeElement)
1266-
) {
1267-
input.focus();
1268-
await new Promise((resolve) => setTimeout(resolve, 1));
1269-
}
1270-
1271-
menuOpenForced.value = false;
1272-
1273-
if (select) {
1274-
input.select();
1275-
}
1267+
// Store the select preference for when the input becomes visible
1268+
pendingSearchSelect.value = select ?? false;
12761269
}
12771270
12781271
let forceClosed = false;
@@ -1283,9 +1276,7 @@ function closeMenu(force = false): void {
12831276
}
12841277
12851278
if (!menuOpen.value) return;
1286-
if (menuOpenForced.value && !force) return;
12871279
1288-
menuOpenForced.value = false;
12891280
menuOpen.value = false;
12901281
selectionIndex.value = -1;
12911282
mainInputRef.value?.focus();

0 commit comments

Comments
 (0)