tabulator-tables
Version:
Interactive table generation JavaScript library
452 lines (358 loc) • 10.4 kB
JavaScript
import Helpers from '../../../../core/tools/Helpers.js';
import maskInput from '../../inputMask.js';
//autocomplete
export default function(cell, onRendered, success, cancel, editorParams){
var self = this,
cellEl = cell.getElement(),
initialValue = cell.getValue(),
vertNav = editorParams.verticalNavigation || "editor",
initialDisplayValue = typeof initialValue !== "undefined" || initialValue === null ? initialValue : (typeof editorParams.defaultValue !== "undefined" ? editorParams.defaultValue : ""),
input = document.createElement("input"),
listEl = document.createElement("div"),
allItems = [],
displayItems = [],
values = [],
currentItem = false,
blurable = true,
uniqueColumnValues = false;
//style input
input.setAttribute("type", "search");
input.style.padding = "4px";
input.style.width = "100%";
input.style.boxSizing = "border-box";
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
for (let key in editorParams.elementAttributes){
if(key.charAt(0) == "+"){
key = key.slice(1);
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
}else{
input.setAttribute(key, editorParams.elementAttributes[key]);
}
}
}
//style list element
listEl.classList.add("tabulator-edit-select-list");
listEl.addEventListener("mousedown", function(e){
blurable = false;
setTimeout(function(){
blurable = true;
}, 10);
});
function genUniqueColumnValues(){
if(editorParams.values === true){
uniqueColumnValues = getUniqueColumnValues();
}else if(typeof editorParams.values === "string"){
uniqueColumnValues = getUniqueColumnValues(editorParams.values);
}
}
function getUniqueColumnValues(field){
var output = {},
data = self.table.getData(),
column;
if(field){
column = self.table.columnManager.getColumnByField(field);
}else{
column = cell.getColumn()._getSelf();
}
if(column){
data.forEach(function(row){
var val = column.getFieldValue(row);
if(val !== null && typeof val !== "undefined" && val !== ""){
output[val] = true;
}
});
if(editorParams.sortValuesList){
if(editorParams.sortValuesList == "asc"){
output = Object.keys(output).sort();
}else{
output = Object.keys(output).sort().reverse();
}
}else{
output = Object.keys(output);
}
}else{
console.warn("unable to find matching column to create autocomplete lookup list:", field);
}
return output;
}
function filterList(term, intialLoad){
var matches = [],
values, items, searchEl;
//lookup base values list
if(uniqueColumnValues){
values = uniqueColumnValues;
}else{
values = editorParams.values || [];
}
if(editorParams.searchFunc){
matches = editorParams.searchFunc(term, values);
if(matches instanceof Promise){
addNotice(typeof editorParams.searchingPlaceholder !== "undefined" ? editorParams.searchingPlaceholder : "Searching...");
matches.then((result) => {
fillListIfNotEmpty(parseItems(result), intialLoad);
}).catch((err) => {
console.err("error in autocomplete search promise:", err);
});
}else{
fillListIfNotEmpty(parseItems(matches), intialLoad);
}
}else{
items = parseItems(values);
if(term === ""){
if(editorParams.showListOnEmpty){
matches = items;
}
}else{
items.forEach(function(item){
if(item.value !== null || typeof item.value !== "undefined"){
if(String(item.value).toLowerCase().indexOf(String(term).toLowerCase()) > -1 || String(item.title).toLowerCase().indexOf(String(term).toLowerCase()) > -1){
matches.push(item);
}
}
});
}
fillListIfNotEmpty(matches, intialLoad);
}
}
function addNotice(notice){
var searchEl = document.createElement("div");
clearList();
if(notice !== false){
searchEl.classList.add("tabulator-edit-select-list-notice");
searchEl.tabIndex = 0;
if(notice instanceof Node){
searchEl.appendChild(notice);
}else{
searchEl.innerHTML = notice;
}
listEl.appendChild(searchEl);
}
}
function parseItems(inputValues){
var itemList = [];
if(Array.isArray(inputValues)){
inputValues.forEach(function(value){
var item = {};
if(typeof value === "object"){
item.title = editorParams.listItemFormatter ? editorParams.listItemFormatter(value.value, value.label) : value.label;
item.value = value.value;
}else{
item.title = editorParams.listItemFormatter ? editorParams.listItemFormatter(value, value) : value;
item.value = value;
}
itemList.push(item);
});
}else{
for(var key in inputValues){
var item = {
title:editorParams.listItemFormatter ? editorParams.listItemFormatter(key, inputValues[key]) : inputValues[key],
value:key,
};
itemList.push(item);
}
}
return itemList;
}
function clearList(){
while(listEl.firstChild) listEl.removeChild(listEl.firstChild);
}
function fillListIfNotEmpty(items, intialLoad){
if(items.length){
fillList(items, intialLoad);
}else{
if(editorParams.emptyPlaceholder){
addNotice(editorParams.emptyPlaceholder);
}
}
}
function fillList(items, intialLoad){
var current = false;
clearList();
displayItems = items;
displayItems.forEach(function(item){
var el = item.element;
if(!el){
el = document.createElement("div");
el.classList.add("tabulator-edit-select-list-item");
el.tabIndex = 0;
el.innerHTML = item.title;
el.addEventListener("click", function(e){
setCurrentItem(item);
chooseItem();
});
el.addEventListener("mousedown", function(e){
blurable = false;
setTimeout(function(){
blurable = true;
}, 10);
});
item.element = el;
if(intialLoad && item.value == initialValue){
input.value = item.title;
item.element.classList.add("active");
current = true;
}
if(item === currentItem){
item.element.classList.add("active");
current = true;
}
}
listEl.appendChild(el);
});
if(!current){
setCurrentItem(false);
}
}
function chooseItem(){
hideList();
if(currentItem){
if(initialValue !== currentItem.value){
initialValue = currentItem.value;
input.value = currentItem.title;
success(currentItem.value);
}else{
cancel();
}
}else{
if(editorParams.freetext){
initialValue = input.value;
success(input.value);
}else{
if(editorParams.allowEmpty && input.value === ""){
initialValue = input.value;
success(input.value);
}else{
cancel();
}
}
}
}
function showList(){
if(!listEl.parentNode){
while(listEl.firstChild) listEl.removeChild(listEl.firstChild);
var offset = Helpers.elOffset(cellEl);
listEl.style.minWidth = cellEl.offsetWidth + "px";
listEl.style.top = (offset.top + cellEl.offsetHeight) + "px";
listEl.style.left = offset.left + "px";
document.body.appendChild(listEl);
}
}
function setCurrentItem(item, showInputValue){
if(currentItem && currentItem.element){
currentItem.element.classList.remove("active");
}
currentItem = item;
if(item && item.element){
item.element.classList.add("active");
}
if(item && item.element && item.element.scrollIntoView){
item.element.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'start'});
}
}
function hideList(){
if(listEl.parentNode){
listEl.parentNode.removeChild(listEl);
}
removeScrollListener();
}
function cancelItem(){
hideList();
cancel();
}
function removeScrollListener() {
self.table.rowManager.element.removeEventListener("scroll", cancelItem);
}
//allow key based navigation
input.addEventListener("keydown", function(e){
var index;
switch(e.keyCode){
case 38: //up arrow
index = displayItems.indexOf(currentItem);
if(vertNav == "editor" || (vertNav == "hybrid" && index)){
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
if(index > 0){
setCurrentItem(displayItems[index - 1]);
}else{
setCurrentItem(false);
}
}
break;
case 40: //down arrow
index = displayItems.indexOf(currentItem);
if(vertNav == "editor" || (vertNav == "hybrid" && index < displayItems.length - 1)){
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
if(index < displayItems.length - 1){
if(index == -1){
setCurrentItem(displayItems[0]);
}else{
setCurrentItem(displayItems[index + 1]);
}
}
}
break;
case 37: //left arrow
case 39: //right arrow
e.stopImmediatePropagation();
e.stopPropagation();
// e.preventDefault();
break;
case 13: //enter
chooseItem();
break;
case 27: //escape
cancelItem();
break;
case 36: //home
case 35: //end
//prevent table navigation while using input element
e.stopImmediatePropagation();
break;
}
});
input.addEventListener("keyup", function(e){
switch(e.keyCode){
case 38: //up arrow
case 37: //left arrow
case 39: //up arrow
case 40: //right arrow
case 13: //enter
case 27: //escape
break;
default:
filterList(input.value);
}
});
input.addEventListener("search", function(e){
filterList(input.value);
});
input.addEventListener("blur", function(e){
if(blurable){
chooseItem();
}
});
input.addEventListener("focus", function(e){
var value = initialDisplayValue;
genUniqueColumnValues();
showList();
input.value = value;
filterList(value, true);
});
onRendered(function(){
input.style.height = "100%";
input.focus({preventScroll: true});
});
if(editorParams.mask){
maskInput(input, editorParams);
}
setTimeout(() => {
this.table.rowManager.element.addEventListener("scroll", cancelItem);
}, 10);
genUniqueColumnValues();
input.value = initialDisplayValue;
filterList(initialDisplayValue, true);
return input;
};