mirror of
https://github.com/xvvvyz/tilde.git
synced 2026-03-11 14:44:24 +00:00
add suggestion preview functionality
This commit is contained in:
parent
bfdb4d5063
commit
ca2d6d65ec
1 changed files with 80 additions and 50 deletions
130
index.html
130
index.html
|
|
@ -172,8 +172,8 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-suggestion:hover,
|
||||
.search-suggestion:focus {
|
||||
.search-suggestion:focus,
|
||||
.search-suggestion.highlight {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
|
|
@ -297,12 +297,27 @@
|
|||
const $ = {
|
||||
el: s => document.querySelector(s),
|
||||
els: s => [].slice.call(document.querySelectorAll(s) || []),
|
||||
isDown: e => ['c-n', 'down'].includes($.key(e)),
|
||||
isUp: e => ['c-p', 'up'].includes($.key(e)),
|
||||
|
||||
jsonp: url => {
|
||||
let script = document.createElement('script');
|
||||
script.src = url;
|
||||
$.el('head').appendChild(script);
|
||||
},
|
||||
|
||||
key: e => {
|
||||
const ctrl = e.ctrlKey;
|
||||
|
||||
switch (e.which) {
|
||||
case 13: return 'enter';
|
||||
case 27: return 'escape';
|
||||
case 38: return 'up';
|
||||
case 40: return 'down';
|
||||
case 78: return ctrl ? 'c-n' : 'n';
|
||||
case 80: return ctrl ? 'c-p' : 'n';
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
class Clock {
|
||||
|
|
@ -368,9 +383,8 @@
|
|||
)).join('');
|
||||
}
|
||||
|
||||
_handleKeydown(event) {
|
||||
const isEsc = event.which === 27;
|
||||
if (isEsc) this.toggle(false);
|
||||
_handleKeydown(e) {
|
||||
if ($.key(e) === 'escape') this.toggle(false);
|
||||
}
|
||||
|
||||
_registerEvents() {
|
||||
|
|
@ -503,8 +517,7 @@
|
|||
</li>`
|
||||
);
|
||||
|
||||
this._suggestionsEl.classList.add('active');
|
||||
this._inputEl.classList.add('bottom-no-radius');
|
||||
this._showSuggestions();
|
||||
return ++this._totalSuggestions === CONFIG.suggestionsLimit;
|
||||
}
|
||||
|
||||
|
|
@ -516,11 +529,10 @@
|
|||
}
|
||||
|
||||
_clearSuggestions() {
|
||||
this._totalSuggestions = 0;
|
||||
this._hideSuggestions();
|
||||
this._clearClickEvents();
|
||||
this._suggestionsEl.innerHTML = '';
|
||||
this._suggestionsEl.classList.remove('active');
|
||||
this._inputEl.classList.remove('bottom-no-radius');
|
||||
this._totalSuggestions = 0;
|
||||
}
|
||||
|
||||
// [[1, 2], [1, 2, 3, 4]] -> [1, 2, 3, 4]
|
||||
|
|
@ -529,33 +541,29 @@
|
|||
}
|
||||
|
||||
_focusNext() {
|
||||
if (this._suggestionEls.length) {
|
||||
const active = document.activeElement;
|
||||
const active = $.el('.highlight');
|
||||
|
||||
if (active.classList.contains('js-search-suggestion')) {
|
||||
this._suggestionEls.forEach((el, index) => {
|
||||
const nextSuggestion = this._suggestionEls[index + 1];
|
||||
if (el === active && nextSuggestion) nextSuggestion.focus();
|
||||
});
|
||||
} else {
|
||||
this._suggestionEls[0].focus();
|
||||
}
|
||||
if (active) {
|
||||
this._suggestionEls.forEach((el, index) => {
|
||||
const next = this._suggestionEls[index + 1];
|
||||
if (el === active && next) this._highlight(next);
|
||||
});
|
||||
} else {
|
||||
this._highlight(this._suggestionEls[0]);
|
||||
}
|
||||
}
|
||||
|
||||
_focusPrevious() {
|
||||
if (this._suggestionEls.length) {
|
||||
const active = document.activeElement;
|
||||
const active = $.el('.highlight');
|
||||
|
||||
if (active.classList.contains('js-search-suggestion')) {
|
||||
this._suggestionEls.forEach((el, index) => {
|
||||
if (el === active) {
|
||||
const previousSuggestion = this._suggestionEls[index - 1];
|
||||
if (previousSuggestion) previousSuggestion.focus();
|
||||
else this._inputEl.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (active) {
|
||||
this._suggestionEls.forEach((el, index) => {
|
||||
if (el === active) {
|
||||
const previous = this._suggestionEls[index - 1];
|
||||
this._noHighlight();
|
||||
if (previous) this._highlight(previous);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,24 +572,46 @@
|
|||
.map(influencer => influencer.getSuggestionsPromise(input));
|
||||
}
|
||||
|
||||
_handleKeydown(event) {
|
||||
const isDown = event.which === 40;
|
||||
const isUp = event.which === 38;
|
||||
const isCtrlN = event.which === 78 && event.ctrlKey;
|
||||
const isCtrlP = event.which === 80 && event.ctrlKey;
|
||||
if (isDown || isUp || isCtrlN || isCtrlP) event.preventDefault();
|
||||
if (isDown || isCtrlN) this._focusNext();
|
||||
if (isUp || isCtrlP) this._focusPrevious();
|
||||
_handleKeydown(e) {
|
||||
if ($.isDown(e) || $.isUp(e)) e.preventDefault();
|
||||
if ($.isDown(e)) this._focusNext();
|
||||
if ($.isUp(e)) this._focusPrevious();
|
||||
}
|
||||
|
||||
_registerClickEvents() {
|
||||
_highlight(el) {
|
||||
this._noHighlight();
|
||||
el.classList.add('highlight');
|
||||
this._inputEl.value = el.getAttribute('data-suggestion');
|
||||
this._inputEl.focus()
|
||||
}
|
||||
|
||||
_noHighlight() {
|
||||
this._inputEl.value = this._originalValue;
|
||||
this._suggestionEls.forEach(el => el.classList.remove('highlight'));
|
||||
}
|
||||
|
||||
_showSuggestions() {
|
||||
this._inputEl.classList.add('bottom-no-radius');
|
||||
this._suggestionsEl.classList.add('active');
|
||||
}
|
||||
|
||||
_hideSuggestions() {
|
||||
this._inputEl.classList.remove('bottom-no-radius');
|
||||
this._suggestionsEl.classList.remove('active');
|
||||
}
|
||||
|
||||
_registerEvents() {
|
||||
this._suggestionEls.forEach(el => {
|
||||
const value = el.getAttribute('data-suggestion');
|
||||
el.addEventListener('mouseover', this._highlight.bind(this, el));
|
||||
el.addEventListener('mouseout', this._noHighlight.bind(this));
|
||||
el.addEventListener('click', this._handleClick.bind(null, value));
|
||||
});
|
||||
}
|
||||
|
||||
_suggest(input) {
|
||||
this._originalValue = this._inputEl.value;
|
||||
|
||||
Promise.all(this._gatherInfluencers(input)).then(res => {
|
||||
this._clearSuggestions();
|
||||
|
||||
|
|
@ -589,7 +619,7 @@
|
|||
.some(item => this._appendSuggestion(item, input));
|
||||
|
||||
this._suggestionEls = $.els('.js-search-suggestion');
|
||||
this._registerClickEvents();
|
||||
this._registerEvents();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -694,29 +724,29 @@
|
|||
this._submitWithValue = this._submitWithValue.bind(this);
|
||||
}
|
||||
|
||||
_handleKeypress(event) {
|
||||
const newChar = String.fromCharCode(event.which);
|
||||
_handleKeypress(e) {
|
||||
const newChar = String.fromCharCode(e.which);
|
||||
const newQuery = this._inputEl.value + newChar;
|
||||
const isNotEmpty = newChar.length;
|
||||
const isEnterKey = event.which !== 13;
|
||||
|
||||
if (isNotEmpty && isEnterKey) {
|
||||
if (isNotEmpty && $.key(e) !== 'enter') {
|
||||
this._help.toggle(false);
|
||||
this._inputEl.focus();
|
||||
}
|
||||
|
||||
if (CONFIG.instantRedirect) {
|
||||
this._queryParser
|
||||
.instantRedirect(event, newQuery, this._submitWithValue);
|
||||
.instantRedirect(e, newQuery, this._submitWithValue);
|
||||
}
|
||||
}
|
||||
|
||||
_handleKeyup(event) {
|
||||
_handleKeyup(e) {
|
||||
const oldVal = this._inputElVal;
|
||||
const newVal = this._inputEl.value.trim();
|
||||
const ignored = $.isDown(e) || $.isUp(e);
|
||||
this._inputElVal = newVal;
|
||||
|
||||
if (CONFIG.suggestions && oldVal !== newVal) {
|
||||
if (CONFIG.suggestions && oldVal !== newVal && !ignored) {
|
||||
this._suggester.suggest(newVal, this._submitWithValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -732,8 +762,8 @@
|
|||
this._formEl.addEventListener('submit', this._submitForm, false);
|
||||
}
|
||||
|
||||
_submitForm(event) {
|
||||
if (event) event.preventDefault();
|
||||
_submitForm(e) {
|
||||
if (e) e.preventDefault();
|
||||
const query = this._inputEl.value.trim();
|
||||
|
||||
if (!query || query === '?') {
|
||||
|
|
|
|||
Loading…
Reference in a new issue