'use strict';
exports.__esModule = true;
var _unicode = require('./../helpers/unicode');
var _mixed = require('./../helpers/mixed');
var _string = require('./../helpers/string');
var _array = require('./../helpers/array');
var _element = require('./../helpers/dom/element');
var _handsontableEditor = require('./handsontableEditor');
var _handsontableEditor2 = _interopRequireDefault(_handsontableEditor);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var AutocompleteEditor = _handsontableEditor2.default.prototype.extend();
/**
* @private
* @editor AutocompleteEditor
* @class AutocompleteEditor
* @dependencies HandsontableEditor
*/
AutocompleteEditor.prototype.init = function () {
_handsontableEditor2.default.prototype.init.apply(this, arguments);
this.query = null;
this.strippedChoices = [];
this.rawChoices = [];
};
AutocompleteEditor.prototype.getValue = function () {
var _this2 = this;
var selectedValue = this.rawChoices.find(function (value) {
var strippedValue = _this2.stripValueIfNeeded(value);
return strippedValue === _this2.TEXTAREA.value;
});
if ((0, _mixed.isDefined)(selectedValue)) {
return selectedValue;
}
return this.TEXTAREA.value;
};
AutocompleteEditor.prototype.createElements = function () {
_handsontableEditor2.default.prototype.createElements.apply(this, arguments);
(0, _element.addClass)(this.htContainer, 'autocompleteEditor');
(0, _element.addClass)(this.htContainer, window.navigator.platform.indexOf('Mac') === -1 ? '' : 'htMacScroll');
};
var skipOne = false;
function onBeforeKeyDown(event) {
skipOne = false;
var editor = this.getActiveEditor();
if ((0, _unicode.isPrintableChar)(event.keyCode) || event.keyCode === _unicode.KEY_CODES.BACKSPACE || event.keyCode === _unicode.KEY_CODES.DELETE || event.keyCode === _unicode.KEY_CODES.INSERT) {
var timeOffset = 0;
// on ctl+c / cmd+c don't update suggestion list
if (event.keyCode === _unicode.KEY_CODES.C && (event.ctrlKey || event.metaKey)) {
return;
}
if (!editor.isOpened()) {
timeOffset += 10;
}
if (editor.htEditor) {
editor.instance._registerTimeout(setTimeout(function () {
editor.queryChoices(editor.TEXTAREA.value);
skipOne = true;
}, timeOffset));
}
}
}
AutocompleteEditor.prototype.prepare = function () {
this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
_handsontableEditor2.default.prototype.prepare.apply(this, arguments);
};
AutocompleteEditor.prototype.open = function () {
// Ugly fix for handsontable which grab window object for autocomplete scroll listener instead table element.
this.TEXTAREA_PARENT.style.overflow = 'auto';
_handsontableEditor2.default.prototype.open.apply(this, arguments);
this.TEXTAREA_PARENT.style.overflow = '';
var choicesListHot = this.htEditor.getInstance();
var _this = this;
var trimDropdown = this.cellProperties.trimDropdown === void 0 ? true : this.cellProperties.trimDropdown;
this.TEXTAREA.style.visibility = 'visible';
this.focus();
choicesListHot.updateSettings({
colWidths: trimDropdown ? [(0, _element.outerWidth)(this.TEXTAREA) - 2] : void 0,
width: trimDropdown ? (0, _element.outerWidth)(this.TEXTAREA) + (0, _element.getScrollbarWidth)() + 2 : void 0,
afterRenderer: function afterRenderer(TD, row, col, prop, value, cellProperties) {
var _this$cellProperties = _this.cellProperties,
filteringCaseSensitive = _this$cellProperties.filteringCaseSensitive,
allowHtml = _this$cellProperties.allowHtml;
var indexOfMatch = void 0;
var match = void 0;
value = (0, _mixed.stringify)(value);
if (value && !allowHtml) {
indexOfMatch = filteringCaseSensitive === true ? value.indexOf(this.query) : value.toLowerCase().indexOf(_this.query.toLowerCase());
if (indexOfMatch !== -1) {
match = value.substr(indexOfMatch, _this.query.length);
value = value.replace(match, '' + match + '');
}
}
TD.innerHTML = value;
},
autoColumnSize: true,
modifyColWidth: function modifyColWidth(width, col) {
// workaround for text overlapping the dropdown, not really accurate
var autoWidths = this.getPlugin('autoColumnSize').widths;
if (autoWidths[col]) {
width = autoWidths[col];
}
return trimDropdown ? width : width + 15;
}
});
// Add additional space for autocomplete holder
this.htEditor.view.wt.wtTable.holder.parentNode.style['padding-right'] = (0, _element.getScrollbarWidth)() + 2 + 'px';
if (skipOne) {
skipOne = false;
}
_this.instance._registerTimeout(setTimeout(function () {
_this.queryChoices(_this.TEXTAREA.value);
}, 0));
};
AutocompleteEditor.prototype.close = function () {
_handsontableEditor2.default.prototype.close.apply(this, arguments);
};
AutocompleteEditor.prototype.queryChoices = function (query) {
var _this3 = this;
this.query = query;
var source = this.cellProperties.source;
if (typeof source == 'function') {
source.call(this.cellProperties, query, function (choices) {
_this3.rawChoices = choices;
_this3.updateChoicesList(_this3.stripValuesIfNeeded(choices));
});
} else if (Array.isArray(source)) {
this.rawChoices = source;
this.updateChoicesList(this.stripValuesIfNeeded(source));
} else {
this.updateChoicesList([]);
}
};
AutocompleteEditor.prototype.updateChoicesList = function (choices) {
var pos = (0, _element.getCaretPosition)(this.TEXTAREA);
var endPos = (0, _element.getSelectionEndPosition)(this.TEXTAREA);
var sortByRelevanceSetting = this.cellProperties.sortByRelevance;
var filterSetting = this.cellProperties.filter;
var orderByRelevance = null;
var highlightIndex = null;
if (sortByRelevanceSetting) {
orderByRelevance = AutocompleteEditor.sortByRelevance(this.stripValueIfNeeded(this.getValue()), choices, this.cellProperties.filteringCaseSensitive);
}
var orderByRelevanceLength = Array.isArray(orderByRelevance) ? orderByRelevance.length : 0;
if (filterSetting === false) {
if (orderByRelevanceLength) {
highlightIndex = orderByRelevance[0];
}
} else {
var sorted = [];
for (var i = 0, choicesCount = choices.length; i < choicesCount; i++) {
if (sortByRelevanceSetting && orderByRelevanceLength <= i) {
break;
}
if (orderByRelevanceLength) {
sorted.push(choices[orderByRelevance[i]]);
} else {
sorted.push(choices[i]);
}
}
highlightIndex = 0;
choices = sorted;
}
this.strippedChoices = choices;
this.htEditor.loadData((0, _array.pivot)([choices]));
this.updateDropdownHeight();
this.flipDropdownIfNeeded();
if (this.cellProperties.strict === true) {
this.highlightBestMatchingChoice(highlightIndex);
}
this.instance.listen();
this.TEXTAREA.focus();
(0, _element.setCaretPosition)(this.TEXTAREA, pos, pos === endPos ? void 0 : endPos);
};
AutocompleteEditor.prototype.flipDropdownIfNeeded = function () {
var textareaOffset = (0, _element.offset)(this.TEXTAREA);
var textareaHeight = (0, _element.outerHeight)(this.TEXTAREA);
var dropdownHeight = this.getDropdownHeight();
var trimmingContainer = (0, _element.getTrimmingContainer)(this.instance.view.wt.wtTable.TABLE);
var trimmingContainerScrollTop = trimmingContainer.scrollTop;
var headersHeight = (0, _element.outerHeight)(this.instance.view.wt.wtTable.THEAD);
var containerOffset = {
row: 0,
col: 0
};
if (trimmingContainer !== window) {
containerOffset = (0, _element.offset)(trimmingContainer);
}
var spaceAbove = textareaOffset.top - containerOffset.top - headersHeight + trimmingContainerScrollTop;
var spaceBelow = trimmingContainer.scrollHeight - spaceAbove - headersHeight - textareaHeight;
var flipNeeded = dropdownHeight > spaceBelow && spaceAbove > spaceBelow;
if (flipNeeded) {
this.flipDropdown(dropdownHeight);
} else {
this.unflipDropdown();
}
this.limitDropdownIfNeeded(flipNeeded ? spaceAbove : spaceBelow, dropdownHeight);
return flipNeeded;
};
AutocompleteEditor.prototype.limitDropdownIfNeeded = function (spaceAvailable, dropdownHeight) {
if (dropdownHeight > spaceAvailable) {
var tempHeight = 0;
var i = 0;
var lastRowHeight = 0;
var height = null;
do {
lastRowHeight = this.htEditor.getRowHeight(i) || this.htEditor.view.wt.wtSettings.settings.defaultRowHeight;
tempHeight += lastRowHeight;
i++;
} while (tempHeight < spaceAvailable);
height = tempHeight - lastRowHeight;
if (this.htEditor.flipped) {
this.htEditor.rootElement.style.top = parseInt(this.htEditor.rootElement.style.top, 10) + dropdownHeight - height + 'px';
}
this.setDropdownHeight(tempHeight - lastRowHeight);
}
};
AutocompleteEditor.prototype.flipDropdown = function (dropdownHeight) {
var dropdownStyle = this.htEditor.rootElement.style;
dropdownStyle.position = 'absolute';
dropdownStyle.top = -dropdownHeight + 'px';
this.htEditor.flipped = true;
};
AutocompleteEditor.prototype.unflipDropdown = function () {
var dropdownStyle = this.htEditor.rootElement.style;
if (dropdownStyle.position === 'absolute') {
dropdownStyle.position = '';
dropdownStyle.top = '';
}
this.htEditor.flipped = void 0;
};
AutocompleteEditor.prototype.updateDropdownHeight = function () {
var currentDropdownWidth = this.htEditor.getColWidth(0) + (0, _element.getScrollbarWidth)() + 2;
var trimDropdown = this.cellProperties.trimDropdown;
this.htEditor.updateSettings({
height: this.getDropdownHeight(),
width: trimDropdown ? void 0 : currentDropdownWidth
});
this.htEditor.view.wt.wtTable.alignOverlaysWithTrimmingContainer();
};
AutocompleteEditor.prototype.setDropdownHeight = function (height) {
this.htEditor.updateSettings({
height: height
});
};
AutocompleteEditor.prototype.finishEditing = function (restoreOriginalValue) {
if (!restoreOriginalValue) {
this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
}
_handsontableEditor2.default.prototype.finishEditing.apply(this, arguments);
};
AutocompleteEditor.prototype.highlightBestMatchingChoice = function (index) {
if (typeof index === 'number') {
this.htEditor.selectCell(index, 0);
} else {
this.htEditor.deselectCell();
}
};
/**
* Filters and sorts by relevance
* @param value
* @param choices
* @param caseSensitive
* @returns {Array} array of indexes in original choices array
*/
AutocompleteEditor.sortByRelevance = function (value, choices, caseSensitive) {
var choicesRelevance = [];
var currentItem = void 0;
var valueLength = value.length;
var valueIndex = void 0;
var charsLeft = void 0;
var result = [];
var i = void 0;
var choicesCount = choices.length;
if (valueLength === 0) {
for (i = 0; i < choicesCount; i++) {
result.push(i);
}
return result;
}
for (i = 0; i < choicesCount; i++) {
currentItem = (0, _string.stripTags)((0, _mixed.stringify)(choices[i]));
if (caseSensitive) {
valueIndex = currentItem.indexOf(value);
} else {
valueIndex = currentItem.toLowerCase().indexOf(value.toLowerCase());
}
if (valueIndex !== -1) {
charsLeft = currentItem.length - valueIndex - valueLength;
choicesRelevance.push({
baseIndex: i,
index: valueIndex,
charsLeft: charsLeft,
value: currentItem
});
}
}
choicesRelevance.sort(function (a, b) {
if (b.index === -1) {
return -1;
}
if (a.index === -1) {
return 1;
}
if (a.index < b.index) {
return -1;
} else if (b.index < a.index) {
return 1;
} else if (a.index === b.index) {
if (a.charsLeft < b.charsLeft) {
return -1;
} else if (a.charsLeft > b.charsLeft) {
return 1;
}
}
return 0;
});
for (i = 0, choicesCount = choicesRelevance.length; i < choicesCount; i++) {
result.push(choicesRelevance[i].baseIndex);
}
return result;
};
AutocompleteEditor.prototype.getDropdownHeight = function () {
var firstRowHeight = this.htEditor.getInstance().getRowHeight(0) || 23;
var visibleRows = this.cellProperties.visibleRows;
return this.strippedChoices.length >= visibleRows ? visibleRows * firstRowHeight : this.strippedChoices.length * firstRowHeight + 8;
};
AutocompleteEditor.prototype.stripValueIfNeeded = function (value) {
return this.stripValuesIfNeeded([value])[0];
};
AutocompleteEditor.prototype.stripValuesIfNeeded = function (values) {
var allowHtml = this.cellProperties.allowHtml;
var stringifiedValues = (0, _array.arrayMap)(values, function (value) {
return (0, _mixed.stringify)(value);
});
var strippedValues = (0, _array.arrayMap)(stringifiedValues, function (value) {
return allowHtml ? value : (0, _string.stripTags)(value);
});
return strippedValues;
};
AutocompleteEditor.prototype.allowKeyEventPropagation = function (keyCode) {
var selected = { row: this.htEditor.getSelectedRange() ? this.htEditor.getSelectedRange().from.row : -1 };
var allowed = false;
if (keyCode === _unicode.KEY_CODES.ARROW_DOWN && selected.row > 0 && selected.row < this.htEditor.countRows() - 1) {
allowed = true;
}
if (keyCode === _unicode.KEY_CODES.ARROW_UP && selected.row > -1) {
allowed = true;
}
return allowed;
};
AutocompleteEditor.prototype.discardEditor = function (result) {
_handsontableEditor2.default.prototype.discardEditor.apply(this, arguments);
this.instance.view.render();
};
exports.default = AutocompleteEditor;