Enable keyboard shortcuts for autocomplete @username selection in chat (#11235)

* Chat autocomplete mouse hover styling

* Enable keyboard shortcuts for chat autocomplete

- Tab/down to select next
- Shift-tab/up to select previous
- Enter to make selection
- Escape to cancel
This commit is contained in:
Jack Cogdill 2019-07-14 08:55:50 -07:00 committed by Matteo Pagliazzi
parent 7b1032e898
commit e091072367
2 changed files with 91 additions and 12 deletions

View file

@ -3,8 +3,8 @@
.autocomplete-results.d-flex.align-items-center(
v-for='result in searchResults',
@click='select(result)',
@mouseenter='result.hover = true',
@mouseleave='result.hover = false',
@mouseenter='setHover(result)',
@mouseleave='resetSelection()',
:class='{"hover-background": result.hover}',
)
span
@ -27,6 +27,7 @@
.hover-background {
background-color: rgba(213, 200, 255, 0.32);
cursor: pointer;
}
.hover-foreground {
@ -86,6 +87,7 @@ export default {
tier9,
tierNPC,
}),
selected: null,
};
},
computed: {
@ -120,12 +122,6 @@ export default {
mounted () {
this.grabUserNames();
},
created () {
document.addEventListener('keyup', this.handleEsc);
},
destroyed () {
document.removeEventListener('keyup', this.handleEsc);
},
watch: {
text (newText) {
if (!newText[newText.length - 1] || newText[newText.length - 1] === ' ') {
@ -154,6 +150,7 @@ export default {
this.searchActive = false;
this.searchEscaped = false;
this.tmpSelections = [];
this.resetSelection();
},
grabUserNames () {
let usersThatMessage = groupBy(this.chat, 'user');
@ -189,13 +186,50 @@ export default {
const targetName = `${result.username || result.displayName} `;
newText = newText.replace(new RegExp(`${this.currentSearch}$`), targetName);
this.$emit('select', newText);
this.resetSelection();
},
handleEsc (e) {
if (e.keyCode === 27) {
this.searchActive = false;
this.searchEscaped = true;
setHover (result) {
this.resetSelection();
result.hover = true;
},
clearHover () {
for (const selection of this.searchResults) {
selection.hover = false;
}
},
resetSelection () {
this.clearHover();
this.selected = null;
},
selectNext () {
if (this.searchResults.length > 0) {
this.clearHover();
this.selected = this.selected === null ?
0 :
(this.selected + 1) % this.searchResults.length;
this.searchResults[this.selected].hover = true;
}
},
selectPrevious () {
if (this.searchResults.length > 0) {
this.clearHover();
this.selected = this.selected === null ?
this.searchResults.length - 1 :
(this.selected - 1 + this.searchResults.length) % this.searchResults.length;
this.searchResults[this.selected].hover = true;
}
},
makeSelection () {
if (this.searchResults.length > 0 && this.selected !== null) {
const result = this.searchResults[this.selected];
this.select(result);
}
},
cancel () {
this.searchActive = false;
this.searchEscaped = true;
this.resetSelection();
},
},
mixins: [styleHelper],
};

View file

@ -11,11 +11,17 @@
:class='{"user-entry": newMessage}',
@keydown='updateCarretPosition',
@keyup.ctrl.enter='sendMessageShortcut()',
@keydown.tab='handleTab($event)',
@keydown.up='selectPreviousAutocomplete($event)',
@keydown.down='selectNextAutocomplete($event)',
@keydown.enter='selectAutocomplete($event)',
@keydown.esc='handleEscape($event)',
@paste='disableMessageSendShortcut()',
maxlength='3000'
)
span {{ currentLength }} / 3000
autocomplete(
ref='autocomplete',
:text='newMessage',
v-on:select="selectedAutocomplete",
:textbox='textbox',
@ -165,6 +171,45 @@
}, 500);
},
handleTab (e) {
if (this.$refs.autocomplete.searchActive) {
e.preventDefault();
if (e.shiftKey) {
this.$refs.autocomplete.selectPrevious();
} else {
this.$refs.autocomplete.selectNext();
}
}
},
handleEscape (e) {
if (this.$refs.autocomplete.searchActive) {
e.preventDefault();
this.$refs.autocomplete.cancel();
}
},
selectNextAutocomplete (e) {
if (this.$refs.autocomplete.searchActive) {
e.preventDefault();
this.$refs.autocomplete.selectNext();
}
},
selectPreviousAutocomplete (e) {
if (this.$refs.autocomplete.searchActive) {
e.preventDefault();
this.$refs.autocomplete.selectPrevious();
}
},
selectAutocomplete (e) {
if (this.$refs.autocomplete.searchActive) {
e.preventDefault();
this.$refs.autocomplete.makeSelection();
}
},
selectedAutocomplete (newText) {
this.newMessage = newText;
},