use event delegation
This commit is contained in:
+35
-28
@@ -258,7 +258,7 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
class CommandsComponent extends HTMLElement {
|
class CommandsComponent extends HTMLElement {
|
||||||
#refs = {
|
#refs = {
|
||||||
commandsContainer: null,
|
commands: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -266,7 +266,7 @@
|
|||||||
this.attachShadow({ mode: 'open' });
|
this.attachShadow({ mode: 'open' });
|
||||||
const template = document.getElementById('commands-template');
|
const template = document.getElementById('commands-template');
|
||||||
const clone = template.content.cloneNode(true);
|
const clone = template.content.cloneNode(true);
|
||||||
this.#refs.commandsContainer = clone.querySelector('.commands');
|
this.#refs.commands = clone.querySelector('.commands');
|
||||||
this.#renderCommands();
|
this.#renderCommands();
|
||||||
this.shadowRoot.append(clone);
|
this.shadowRoot.append(clone);
|
||||||
}
|
}
|
||||||
@@ -279,7 +279,7 @@
|
|||||||
clone.querySelector('.command').href = url;
|
clone.querySelector('.command').href = url;
|
||||||
clone.querySelector('.key').innerText = key;
|
clone.querySelector('.key').innerText = key;
|
||||||
clone.querySelector('.name').innerText = name;
|
clone.querySelector('.name').innerText = name;
|
||||||
this.#refs.commandsContainer.append(clone);
|
this.#refs.commands.append(clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,18 +305,22 @@
|
|||||||
border: none;
|
border: none;
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
left: 0;
|
left: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog[open] {
|
.dialog[open] {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
font-size: var(--font-size-2);
|
font-size: var(--font-size-2);
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
@@ -417,8 +421,7 @@
|
|||||||
dialog: null,
|
dialog: null,
|
||||||
form: null,
|
form: null,
|
||||||
input: null,
|
input: null,
|
||||||
suggestions: [],
|
suggestions: null,
|
||||||
suggestionsContainer: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -429,10 +432,10 @@
|
|||||||
this.#refs.dialog = clone.querySelector('.dialog');
|
this.#refs.dialog = clone.querySelector('.dialog');
|
||||||
this.#refs.form = clone.querySelector('.form');
|
this.#refs.form = clone.querySelector('.form');
|
||||||
this.#refs.input = clone.querySelector('.input');
|
this.#refs.input = clone.querySelector('.input');
|
||||||
this.#refs.suggestionsContainer = clone.querySelector('.suggestions');
|
this.#refs.suggestions = clone.querySelector('.suggestions');
|
||||||
|
this.#refs.form.addEventListener('submit', this.#onSubmit, false);
|
||||||
this.#refs.input.addEventListener('input', this.#onInput);
|
this.#refs.input.addEventListener('input', this.#onInput);
|
||||||
const onSubmit = () => this.#execute(this.#refs.input.value);
|
this.#refs.suggestions.addEventListener('click', this.#onSuggestionClick);
|
||||||
this.#refs.form.addEventListener('submit', onSubmit, false);
|
|
||||||
document.addEventListener('keydown', this.#onKeydown);
|
document.addEventListener('keydown', this.#onKeydown);
|
||||||
this.shadowRoot.append(clone);
|
this.shadowRoot.append(clone);
|
||||||
}
|
}
|
||||||
@@ -531,16 +534,11 @@
|
|||||||
return `${parser.protocol}//${parser.hostname}`;
|
return `${parser.protocol}//${parser.hostname}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
#clearSuggestions() {
|
|
||||||
this.#refs.suggestions = [];
|
|
||||||
this.#refs.suggestionsContainer.innerHTML = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
#close() {
|
#close() {
|
||||||
this.#refs.input.value = '';
|
this.#refs.input.value = '';
|
||||||
this.#refs.input.blur();
|
this.#refs.input.blur();
|
||||||
this.#refs.dialog.close();
|
this.#refs.dialog.close();
|
||||||
this.#clearSuggestions();
|
this.#refs.suggestions.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#execute(query) {
|
#execute(query) {
|
||||||
@@ -551,17 +549,17 @@
|
|||||||
|
|
||||||
#focusNextSuggestion(previous = false) {
|
#focusNextSuggestion(previous = false) {
|
||||||
const active = this.shadowRoot.activeElement;
|
const active = this.shadowRoot.activeElement;
|
||||||
const activeIndex = this.#refs.suggestions.indexOf(active);
|
|
||||||
let nextIndex;
|
let nextIndex;
|
||||||
|
|
||||||
if (activeIndex === -1) {
|
if (active.dataset.index) {
|
||||||
nextIndex = previous ? this.#refs.suggestions.length - 1 : 0;
|
const activeIndex = Number(active.dataset.index);
|
||||||
} else {
|
|
||||||
nextIndex = previous ? activeIndex - 1 : activeIndex + 1;
|
nextIndex = previous ? activeIndex - 1 : activeIndex + 1;
|
||||||
|
} else {
|
||||||
|
nextIndex = previous ? this.#refs.suggestions.childElementCount - 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = this.#refs.suggestions[nextIndex];
|
const next = this.#refs.suggestions.children[nextIndex];
|
||||||
if (next) next.focus();
|
if (next) next.querySelector('.suggestion').focus();
|
||||||
else this.#refs.input.focus();
|
else this.#refs.input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,16 +619,26 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#onSubmit = () => {
|
||||||
|
this.#execute(this.#refs.input.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
#onSuggestionClick = (e) => {
|
||||||
|
const ref = e.target.closest('.suggestion');
|
||||||
|
if (!ref) return;
|
||||||
|
this.#execute(ref.dataset.suggestion);
|
||||||
|
};
|
||||||
|
|
||||||
#renderSuggestions(suggestions, query) {
|
#renderSuggestions(suggestions, query) {
|
||||||
this.#clearSuggestions();
|
this.#refs.suggestions.innerHTML = '';
|
||||||
const sliced = suggestions.slice(0, SearchComponent.#SUGGESTION_LIMIT);
|
const sliced = suggestions.slice(0, SearchComponent.#SUGGESTION_LIMIT);
|
||||||
|
|
||||||
for (const suggestion of sliced) {
|
for (const [index, suggestion] of sliced.entries()) {
|
||||||
const template = document.getElementById('suggestion-template');
|
const template = document.getElementById('suggestion-template');
|
||||||
const clone = template.content.cloneNode(true);
|
const clone = template.content.cloneNode(true);
|
||||||
const ref = clone.querySelector('.suggestion');
|
const ref = clone.querySelector('.suggestion');
|
||||||
const onClick = this.#execute.bind(this, suggestion);
|
ref.dataset.index = index;
|
||||||
ref.addEventListener('click', onClick);
|
ref.dataset.suggestion = suggestion;
|
||||||
const escapedQuery = SearchComponent.#escapeRegexCharacters(query);
|
const escapedQuery = SearchComponent.#escapeRegexCharacters(query);
|
||||||
const matched = suggestion.match(new RegExp(escapedQuery, 'i'));
|
const matched = suggestion.match(new RegExp(escapedQuery, 'i'));
|
||||||
|
|
||||||
@@ -648,8 +656,7 @@
|
|||||||
ref.innerText = suggestion;
|
ref.innerText = suggestion;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#refs.suggestions.push(ref);
|
this.#refs.suggestions.append(clone);
|
||||||
this.#refs.suggestionsContainer.append(clone);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user