use event delegation

This commit is contained in:
Cade Scroggins
2022-07-27 19:39:53 -07:00
parent 684c11ecae
commit f54caf8405
+35 -28
View File
@@ -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);
} }
} }
} }