Skip to content

Commit 98b30fc

Browse files
committed
feat(tpl): focus file item on typing prefix
1 parent 617af89 commit 98b30fc

File tree

2 files changed

+224
-42
lines changed

2 files changed

+224
-42
lines changed

src/tpl/asset/main.js

Lines changed: 120 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,29 @@
1818
return;
1919
}
2020

21-
function getFocusableSibling(container, isPrev) {
21+
function getFocusableSibling(container, isPrev, startA) {
2222
if (!container) {
2323
return
2424
}
25-
var focusA = container.querySelector(':focus');
26-
var focusLI = focusA;
27-
while (focusLI && focusLI.tagName !== 'LI') {
28-
focusLI = focusLI.parentElement;
25+
if (!startA) {
26+
startA = container.querySelector(':focus');
2927
}
30-
if (!focusLI) {
28+
var startLI = startA;
29+
while (startLI && startLI.tagName !== 'LI') {
30+
startLI = startLI.parentElement;
31+
}
32+
if (!startLI) {
3133
if (isPrev) {
32-
focusLI = container.firstElementChild;
34+
startLI = container.firstElementChild;
3335
} else {
34-
focusLI = container.lastElementChild;
36+
startLI = container.lastElementChild;
3537
}
3638
}
37-
if (!focusLI) {
39+
if (!startLI) {
3840
return;
3941
}
4042

41-
var siblingLI = focusLI;
43+
var siblingLI = startLI;
4244
do {
4345
if (isPrev) {
4446
siblingLI = siblingLI.previousElementSibling;
@@ -51,17 +53,55 @@
5153
siblingLI = container.firstElementChild;
5254
}
5355
}
54-
} while (siblingLI !== focusLI && (
56+
} while (siblingLI !== startLI && (
5557
siblingLI.classList.contains(classNone) ||
5658
siblingLI.classList.contains(classHeader)
5759
));
5860

5961
if (siblingLI) {
60-
var newFocusA = siblingLI.querySelector('a');
61-
return newFocusA;
62+
var siblingA = siblingLI.querySelector('a');
63+
return siblingA;
6264
}
6365
}
6466

67+
function getMatchedFocusableSibling(container, isPrev, startA, buf, key) {
68+
var skipRound = buf === key;
69+
var matchKeyA;
70+
var firstCheckA;
71+
var secondCheckA;
72+
var a = startA;
73+
do {
74+
if (skipRound) {
75+
skipRound = false;
76+
continue;
77+
}
78+
if (!a) {
79+
continue;
80+
}
81+
82+
// firstCheckA maybe a focused a that not belongs to the list
83+
// secondCheckA must be in the list
84+
if (!firstCheckA) {
85+
firstCheckA = a;
86+
} else if (firstCheckA === a) {
87+
return;
88+
} else if (firstCheckA && !secondCheckA) {
89+
secondCheckA = a
90+
} else if (secondCheckA === a) {
91+
return;
92+
}
93+
94+
var textContent = (a.querySelector('.name') || a).textContent.toLowerCase();
95+
if (buf.length <= textContent.length && textContent.substring(0, buf.length) === buf) {
96+
return a;
97+
}
98+
if (!matchKeyA && textContent[0] === key) {
99+
matchKeyA = a;
100+
}
101+
} while (a = getFocusableSibling(container, isPrev, a));
102+
return matchKeyA;
103+
}
104+
65105
var UP = 'Up';
66106
var DOWN = 'Down';
67107
var LEFT = 'Left';
@@ -77,53 +117,108 @@
77117
var ARROW_LEFT_CODE = 37;
78118
var ARROW_RIGHT_CODE = 39;
79119

80-
var skipTags = ['INPUT', 'BUTTON', 'TEXTAREA'];
120+
var SKIP_TAGS = ['INPUT', 'BUTTON', 'TEXTAREA'];
121+
122+
var lookupKey = '';
123+
var lookupBuffer = '';
124+
var lookupStartA = null;
125+
var lookupTimer;
126+
127+
function delayClearLookupContext() {
128+
clearTimeout(lookupTimer);
129+
lookupTimer = setTimeout(function () {
130+
lookupBuffer = '';
131+
lookupStartA = null;
132+
}, 850);
133+
}
134+
135+
function lookup(key) {
136+
key = key.toLowerCase();
137+
138+
if (key === lookupKey && key === lookupBuffer) {
139+
// same as last key, lookup next for the same key as prefix
140+
lookupStartA = itemList.querySelector(':focus');
141+
lookupBuffer = lookupKey;
142+
} else {
143+
if (!lookupStartA) {
144+
lookupStartA = itemList.querySelector(':focus');
145+
}
146+
lookupKey = key;
147+
lookupBuffer += key;
148+
}
149+
delayClearLookupContext();
150+
return getMatchedFocusableSibling(itemList, false, lookupStartA, lookupBuffer, key);
151+
}
81152

82153
document.addEventListener('keydown', function (e) {
83154
if (
84155
e.ctrlKey ||
85156
e.altKey ||
86-
e.shiftKey ||
87-
e.metaKey ||
88-
skipTags.indexOf(e.target.tagName) >= 0
157+
SKIP_TAGS.indexOf(e.target.tagName) >= 0
89158
) {
90159
return;
91160
}
92161

93162
var newFocusEl;
163+
94164
if (e.key) {
95165
switch (e.key) {
96166
case LEFT:
97167
case ARROW_LEFT:
98-
newFocusEl = getFocusableSibling(pathList, true);
168+
if (!e.shiftKey && !e.metaKey) {
169+
newFocusEl = getFocusableSibling(pathList, true);
170+
}
99171
break;
100172
case RIGHT:
101173
case ARROW_RIGHT:
102-
newFocusEl = getFocusableSibling(pathList, false);
174+
if (!e.shiftKey && !e.metaKey) {
175+
newFocusEl = getFocusableSibling(pathList, false);
176+
}
103177
break;
104178
case UP:
105179
case ARROW_UP:
106-
newFocusEl = getFocusableSibling(itemList, true);
180+
if (!e.shiftKey && !e.metaKey) {
181+
newFocusEl = getFocusableSibling(itemList, true);
182+
}
107183
break;
108184
case DOWN:
109185
case ARROW_DOWN:
110-
newFocusEl = getFocusableSibling(itemList, false);
186+
if (!e.shiftKey && !e.metaKey) {
187+
newFocusEl = getFocusableSibling(itemList, false);
188+
}
189+
break;
190+
default:
191+
if (e.key.length === 1) {
192+
newFocusEl = lookup(e.key);
193+
}
111194
break;
112195
}
113196
} else if (e.keyCode) {
114197
switch (e.keyCode) {
115198
case ARROW_LEFT_CODE:
116-
newFocusEl = getFocusableSibling(pathList, true);
199+
if (!e.shiftKey && !e.metaKey) {
200+
newFocusEl = getFocusableSibling(pathList, true);
201+
}
117202
break;
118203
case ARROW_RIGHT_CODE:
119-
newFocusEl = getFocusableSibling(pathList, false);
204+
if (!e.shiftKey && !e.metaKey) {
205+
newFocusEl = getFocusableSibling(pathList, false);
206+
}
120207
break;
121208
case ARROW_UP_CODE:
122-
newFocusEl = getFocusableSibling(itemList, true);
209+
if (!e.shiftKey && !e.metaKey) {
210+
newFocusEl = getFocusableSibling(itemList, true);
211+
}
123212
break;
124213
case ARROW_DOWN_CODE:
125-
newFocusEl = getFocusableSibling(itemList, false);
214+
if (!e.shiftKey && !e.metaKey) {
215+
newFocusEl = getFocusableSibling(itemList, false);
216+
}
126217
break;
218+
default:
219+
if (e.keyCode >= 32 && e.keyCode <= 126) {
220+
newFocusEl = lookup(String.fromCharCode(e.keyCode));
221+
}
127222
}
128223
}
129224
if (newFocusEl) {

0 commit comments

Comments
 (0)