diff --git a/public/js/app.js b/public/js/app.js index 03273cf..2ee7ca6 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -6,7 +6,7 @@ function mySplice(s, idx, del, n) { return s.substring(0, idx) + n + s.substring(idx + del); } -function suggestionPosition(el) { +function suggestionIndex(el) { // el.parentNode is ul#tags-suggestion, which include a template. That's why // a -1 is needed here. const idx = [...el.parentNode.children].indexOf(el); @@ -52,50 +52,63 @@ document.addEventListener('alpine:init', () => { this.suggestions = await response.json(); }, - completeSuggestion(evt) { + completeSuggestion() { if (this.currentSuggestion === null) return; const value = this.$refs.tags.value; - const pos = this.inputCursor - this.query.length; + const pos = Math.max(this.inputCursor - this.query.length, 0); const tag = this.suggestions[this.currentSuggestion].display; + const newValue = mySplice(value, pos, this.query.length, tag + ' '); - this.$refs.tags.value = mySplice(value, pos, this.query.length, - tag + ' '); this.reset(); + + this.$refs.tags.value = newValue; this.inputCursor = this.$refs.tags.selectionStart = this.$refs.tags.selectionEnd = pos + tag.length + 1; + this.$refs.tags.focus(); - - // Don't switch focus if we're completing after a Tab press. - if (evt.type === "keydown" && evt.keyCode === 9) - evt.preventDefault(); }, - selectCurrentSuggestion(evt) { - this.currentSuggestion = suggestionPosition(evt.currentTarget); - this.completeSuggestion(evt); + completeClickedSuggestion(evt) { + this.currentSuggestion = suggestionIndex(evt.currentTarget); + this.completeSuggestion(); }, - setCurrentSuggestion(evt, amount = 0) { + setCurrentSuggestion(idx) { + const len = this.suggestions.length; + if (len === 0) + return; + currentSuggestionElement(this.currentSuggestion) ?.classList.remove("suggestion-hover"); - if (evt.type === 'mouseenter') - this.currentSuggestion = suggestionPosition(evt.currentTarget); - else { - const len = this.suggestions.length; - let cur = this.currentSuggestion; - - if (cur === null) - cur = amount > 0 ? -1 : amount < 0 ? len : 0; - this.currentSuggestion = (cur + amount + len) % len; - } + idx = idx % len; + if (idx < 0) + idx += len; + this.currentSuggestion = idx; currentSuggestionElement(this.currentSuggestion) ?.classList.add("suggestion-hover"); - } + }, + + setPointerSuggestion(evt) { + this.setCurrentSuggestion(suggestionIndex(evt.currentTarget)); + }, + + moveCurrentSuggestion(amount, defaultValue) { + this.setCurrentSuggestion(this.currentSuggestion === null ? + defaultValue : this.currentSuggestion + amount); + }, + + nextSuggestion(evt) { + this.moveCurrentSuggestion(1, 0); + }, + + previousSuggestion(evt) { + this.moveCurrentSuggestion(-1, -1); + }, })); }); diff --git a/templates/_search.html.ep b/templates/_search.html.ep index b4f5652..fde3f7b 100644 --- a/templates/_search.html.ep +++ b/templates/_search.html.ep @@ -11,16 +11,16 @@ x-ref="tags" @focus="fetchSuggestions" @input.debounce="fetchSuggestions" - @keydown.tab="completeSuggestion" - @keydown.up.prevent="setCurrentSuggestion($event, -1)" - @keydown.down.prevent="setCurrentSuggestion($event, +1)" + @keydown.tab.prevent="completeSuggestion" + @keydown.up.prevent="previousSuggestion" + @keydown.down.prevent="nextSuggestion" @keydown.escape="reset">