keeweb/app/scripts/views/fields/field-view-autocomplete.js

112 lines
3.7 KiB
JavaScript
Raw Normal View History

2017-01-31 07:50:28 +01:00
const FieldViewText = require('./field-view-text');
const Keys = require('../../const/keys');
2016-02-28 12:16:05 +01:00
2017-01-31 07:50:28 +01:00
const FieldViewAutocomplete = FieldViewText.extend({
2019-08-18 10:17:09 +02:00
endEdit(newVal, extra) {
2016-02-28 12:16:05 +01:00
if (this.autocomplete) {
this.autocomplete.remove();
this.autocomplete = null;
}
delete this.selectedCopmletionIx;
2016-02-28 12:16:05 +01:00
FieldViewText.prototype.endEdit.call(this, newVal, extra);
},
2019-08-18 10:17:09 +02:00
startEdit() {
2016-02-28 12:16:05 +01:00
FieldViewText.prototype.startEdit.call(this);
2017-01-31 07:50:28 +01:00
const fieldRect = this.input[0].getBoundingClientRect();
2016-02-28 12:16:05 +01:00
this.autocomplete = $('<div class="details__field-autocomplete"></div>').appendTo('body');
this.autocomplete.css({
top: fieldRect.bottom,
left: fieldRect.left,
width: fieldRect.width - 2
});
delete this.selectedCopmletionIx;
2016-02-28 12:16:05 +01:00
this.autocomplete.mousedown(this.autocompleteClick.bind(this));
2016-05-13 15:14:13 +02:00
if (this.input.val()) {
this.autocomplete.hide();
} else {
2016-02-28 12:16:05 +01:00
this.updateAutocomplete();
}
},
2019-08-18 10:17:09 +02:00
fieldValueInput(e) {
2016-02-28 12:16:05 +01:00
e.stopPropagation();
this.updateAutocomplete();
FieldViewText.prototype.fieldValueInput.call(this, e);
},
2019-08-18 10:17:09 +02:00
fieldValueKeydown(e) {
switch (e.which) {
case Keys.DOM_VK_UP:
this.moveAutocomplete(false);
e.preventDefault();
break;
case Keys.DOM_VK_DOWN:
this.moveAutocomplete(true);
e.preventDefault();
break;
2019-08-18 10:17:09 +02:00
case Keys.DOM_VK_RETURN: {
2019-08-18 08:05:38 +02:00
const selectedItem = this.autocomplete
.find('.details__field-autocomplete-item--selected')
.text();
if (selectedItem) {
this.input.val(selectedItem);
this.endEdit(selectedItem);
}
break;
2019-08-18 10:17:09 +02:00
}
default:
delete this.selectedCopmletionIx;
}
FieldViewText.prototype.fieldValueKeydown.call(this, e);
},
2019-08-18 10:17:09 +02:00
moveAutocomplete(next) {
const completions = this.model.getCompletions(this.input.val());
if (typeof this.selectedCopmletionIx === 'number') {
2019-08-16 23:05:39 +02:00
this.selectedCopmletionIx =
2019-08-18 08:05:38 +02:00
(completions.length + this.selectedCopmletionIx + (next ? 1 : -1)) %
completions.length;
} else {
this.selectedCopmletionIx = next ? 0 : completions.length - 1;
}
this.updateAutocomplete();
},
2019-08-18 10:17:09 +02:00
updateAutocomplete() {
2017-01-31 07:50:28 +01:00
const completions = this.model.getCompletions(this.input.val());
2019-08-16 23:05:39 +02:00
const completionsHtml = completions
.map((item, ix) => {
2019-08-18 08:05:38 +02:00
const sel =
ix === this.selectedCopmletionIx
? 'details__field-autocomplete-item--selected'
: '';
return (
'<div class="details__field-autocomplete-item ' +
sel +
'">' +
_.escape(item) +
'</div>'
);
2019-08-16 23:05:39 +02:00
})
.join('');
2016-02-28 12:16:05 +01:00
this.autocomplete.html(completionsHtml);
this.autocomplete.toggle(!!completionsHtml);
},
2019-08-18 10:17:09 +02:00
autocompleteClick(e) {
2016-02-28 12:16:05 +01:00
e.stopPropagation();
if (e.target.classList.contains('details__field-autocomplete-item')) {
2017-01-31 07:50:28 +01:00
const selectedItem = $(e.target).text();
2016-02-28 12:16:05 +01:00
this.input.val(selectedItem);
this.endEdit(selectedItem);
} else {
2019-08-16 23:05:39 +02:00
this.afterPaint(function() {
this.input.focus();
});
2016-02-28 12:16:05 +01:00
}
}
});
module.exports = FieldViewAutocomplete;