otsdaq_utilities  v2_05_02_indev
edit.js
1 var Edit = function(table){
2  this.table = table; //hold Tabulator object
3  this.currentCell = false; //hold currently editing cell
4  this.mouseClick = false; //hold mousedown state to prevent click binding being overriden by editor opening
5  this.recursionBlock = false; //prevent focus recursion
6  this.invalidEdit = false;
7 };
8 
9 
10 //initialize column editor
11 Edit.prototype.initializeColumn = function(column){
12  var self = this,
13  config = {
14  editor:false,
15  blocked:false,
16  check:column.definition.editable,
17  params:column.definition.editorParams || {}
18  };
19 
20  //set column editor
21  switch(typeof column.definition.editor){
22  case "string":
23 
24  if(column.definition.editor === "tick"){
25  column.definition.editor = "tickCross";
26  console.warn("DEPRECATION WARNING - the tick editor has been deprecated, please use the tickCross editor");
27  }
28 
29  if(self.editors[column.definition.editor]){
30  config.editor = self.editors[column.definition.editor];
31  }else{
32  console.warn("Editor Error - No such editor found: ", column.definition.editor);
33  }
34  break;
35 
36  case "function":
37  config.editor = column.definition.editor;
38  break;
39 
40  case "boolean":
41 
42  if(column.definition.editor === true){
43 
44  if(typeof column.definition.formatter !== "function"){
45 
46  if(column.definition.formatter === "tick"){
47  column.definition.formatter = "tickCross";
48  console.warn("DEPRECATION WARNING - the tick editor has been deprecated, please use the tickCross editor");
49  }
50 
51  if(self.editors[column.definition.formatter]){
52  config.editor = self.editors[column.definition.formatter];
53  }else{
54  config.editor = self.editors["input"];
55  }
56  }else{
57  console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ", column.definition.formatter);
58  }
59  }
60  break;
61  }
62 
63  if(config.editor){
64  column.modules.edit = config;
65  }
66 };
67 
68 Edit.prototype.getCurrentCell = function(){
69  return this.currentCell ? this.currentCell.getComponent() : false;
70 };
71 
72 Edit.prototype.clearEditor = function(){
73  var cell = this.currentCell,
74  cellEl;
75 
76  this.invalidEdit = false;
77 
78  if(cell){
79  this.currentCell = false;
80 
81  cellEl = cell.getElement();
82  cellEl.classList.remove("tabulator-validation-fail");
83  cellEl.classList.remove("tabulator-editing");
84  while(cellEl.firstChild) cellEl.removeChild(cellEl.firstChild);
85 
86  cell.row.getElement().classList.remove("tabulator-row-editing");
87  }
88 };
89 
90 Edit.prototype.cancelEdit = function(){
91 
92  if(this.currentCell){
93  var cell = this.currentCell;
94  var component = this.currentCell.getComponent();
95 
96  this.clearEditor();
97  cell.setValueActual(cell.getValue());
98 
99  if(cell.column.cellEvents.cellEditCancelled){
100  cell.column.cellEvents.cellEditCancelled.call(this.table, component);
101  }
102 
103  this.table.options.cellEditCancelled.call(this.table, component);
104  }
105 };
106 
107 //return a formatted value for a cell
108 Edit.prototype.bindEditor = function(cell){
109  var self = this,
110  element = cell.getElement();
111 
112  element.setAttribute("tabindex", 0);
113 
114  element.addEventListener("click", function(e){
115  if(!element.classList.contains("tabulator-editing")){
116  element.focus();
117  }
118  });
119 
120  element.addEventListener("mousedown", function(e){
121  self.mouseClick = true;
122  });
123 
124  element.addEventListener("focus", function(e){
125  if(!self.recursionBlock){
126  self.edit(cell, e, false);
127  }
128  });
129 };
130 
131 Edit.prototype.focusCellNoEvent = function(cell, block){
132  this.recursionBlock = true;
133  if(!(block && this.table.browser === "ie")){
134  cell.getElement().focus();
135  }
136  this.recursionBlock = false;
137 };
138 
139 Edit.prototype.editCell = function(cell, forceEdit){
140  this.focusCellNoEvent(cell);
141  this.edit(cell, false, forceEdit);
142 };
143 
144 Edit.prototype.edit = function(cell, e, forceEdit){
145  var self = this,
146  allowEdit = true,
147  rendered = function(){},
148  element = cell.getElement(),
149  cellEditor, component, params;
150 
151  //prevent editing if another cell is refusing to leave focus (eg. validation fail)
152  if(this.currentCell){
153  if(!this.invalidEdit){
154  this.cancelEdit();
155  }
156  return;
157  }
158 
159  //handle successfull value change
160  function success(value){
161 
162  if(self.currentCell === cell){
163  var valid = true;
164 
165  if(cell.column.modules.validate && self.table.modExists("validate")){
166  valid = self.table.modules.validate.validate(cell.column.modules.validate, cell.getComponent(), value);
167  }
168 
169  if(valid === true){
170  self.clearEditor();
171  cell.setValue(value, true);
172 
173  if(self.table.options.dataTree && self.table.modExists("dataTree")){
174  self.table.modules.dataTree.checkForRestyle(cell);
175  }
176 
177  return true;
178  }else{
179  self.invalidEdit = true;
180  element.classList.add("tabulator-validation-fail");
181  self.focusCellNoEvent(cell, true);
182  rendered();
183  self.table.options.validationFailed.call(self.table, cell.getComponent(), value, valid);
184 
185  return false;
186  }
187  }else{
188  // console.warn("Edit Success Error - cannot call success on a cell that is no longer being edited");
189  }
190  }
191 
192  //handle aborted edit
193  function cancel(){
194  if(self.currentCell === cell){
195  self.cancelEdit();
196 
197  if(self.table.options.dataTree && self.table.modExists("dataTree")){
198  self.table.modules.dataTree.checkForRestyle(cell);
199  }
200  }else{
201  // console.warn("Edit Success Error - cannot call cancel on a cell that is no longer being edited");
202  }
203  }
204 
205  function onRendered(callback){
206  rendered = callback;
207  }
208 
209  if(!cell.column.modules.edit.blocked){
210  if(e){
211  e.stopPropagation();
212  }
213 
214  switch(typeof cell.column.modules.edit.check){
215  case "function":
216  allowEdit = cell.column.modules.edit.check(cell.getComponent());
217  break;
218 
219  case "boolean":
220  allowEdit = cell.column.modules.edit.check;
221  break;
222  }
223 
224  if(allowEdit || forceEdit){
225 
226  self.cancelEdit();
227 
228  self.currentCell = cell;
229 
230  component = cell.getComponent();
231 
232  if(this.mouseClick){
233  this.mouseClick = false;
234 
235  if(cell.column.cellEvents.cellClick){
236  cell.column.cellEvents.cellClick.call(this.table, e, component);
237  }
238  }
239 
240  if(cell.column.cellEvents.cellEditing){
241  cell.column.cellEvents.cellEditing.call(this.table, component);
242  }
243 
244  self.table.options.cellEditing.call(this.table, component);
245 
246  params = typeof cell.column.modules.edit.params === "function" ? cell.column.modules.edit.params(component) : cell.column.modules.edit.params;
247 
248  cellEditor = cell.column.modules.edit.editor.call(self, component, onRendered, success, cancel, params);
249 
250  //if editor returned, add to DOM, if false, abort edit
251  if(cellEditor !== false){
252 
253  if(cellEditor instanceof Node){
254  element.classList.add("tabulator-editing");
255  cell.row.getElement().classList.add("tabulator-row-editing");
256  while(element.firstChild) element.removeChild(element.firstChild);
257  element.appendChild(cellEditor);
258 
259  //trigger onRendered Callback
260  rendered();
261 
262  //prevent editing from triggering rowClick event
263  var children = element.children;
264 
265  for (var i = 0; i < children.length; i++) {
266  children[i].addEventListener("click", function(e){
267  e.stopPropagation();
268  });
269  }
270  }else{
271  console.warn("Edit Error - Editor should return an instance of Node, the editor returned:", cellEditor);
272  element.blur();
273  return false;
274  }
275 
276  }else{
277  element.blur();
278  return false;
279  }
280 
281  return true;
282  }else{
283  this.mouseClick = false;
284  element.blur();
285  return false;
286  }
287  }else{
288  this.mouseClick = false;
289  element.blur();
290  return false;
291  }
292 };
293 
294 //default data editors
295 Edit.prototype.editors = {
296 
297  //input element
298  input:function(cell, onRendered, success, cancel, editorParams){
299 
300  //create and style input
301  var cellValue = cell.getValue(),
302  input = document.createElement("input");
303 
304  input.setAttribute("type", editorParams.search ? "search" : "text");
305 
306  input.style.padding = "4px";
307  input.style.width = "100%";
308  input.style.boxSizing = "border-box";
309 
310  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
311  for (let key in editorParams.elementAttributes){
312  if(key.charAt(0) == "+"){
313  key = key.slice(1);
314  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
315  }else{
316  input.setAttribute(key, editorParams.elementAttributes[key]);
317  }
318  }
319  }
320 
321  input.value = typeof cellValue !== "undefined" ? cellValue : "";
322 
323  onRendered(function(){
324  input.focus();
325  input.style.height = "100%";
326  });
327 
328  function onChange(e){
329  if(((cellValue === null || typeof cellValue === "undefined") && input.value !== "") || input.value != cellValue){
330 
331  if(success(input.value)){
332  cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
333  }
334  }else{
335  cancel();
336  }
337  }
338 
339  //submit new value on blur or change
340  input.addEventListener("change", onChange);
341  input.addEventListener("blur", onChange);
342 
343  //submit new value on enter
344  input.addEventListener("keydown", function(e){
345  switch(e.keyCode){
346  case 13:
347  onChange(e);
348  break;
349 
350  case 27:
351  cancel();
352  break;
353  }
354  });
355 
356  return input;
357  },
358 
359  //resizable text area element
360  textarea:function(cell, onRendered, success, cancel, editorParams){
361  var self = this,
362  cellValue = cell.getValue(),
363  vertNav = editorParams.verticalNavigation || "hybrid",
364  value = String(cellValue !== null && typeof cellValue !== "undefined" ? cellValue : ""),
365  count = (value.match(/(?:\r\n|\r|\n)/g) || []).length + 1,
366  input = document.createElement("textarea"),
367  scrollHeight = 0;
368 
369  //create and style input
370  input.style.display = "block";
371  input.style.padding = "2px";
372  input.style.height = "100%";
373  input.style.width = "100%";
374  input.style.boxSizing = "border-box";
375  input.style.whiteSpace = "pre-wrap";
376  input.style.resize = "none";
377 
378  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
379  for (let key in editorParams.elementAttributes){
380  if(key.charAt(0) == "+"){
381  key = key.slice(1);
382  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
383  }else{
384  input.setAttribute(key, editorParams.elementAttributes[key]);
385  }
386  }
387  }
388 
389  input.value = value;
390 
391  onRendered(function(){
392  input.focus();
393  input.style.height = "100%";
394  });
395 
396  function onChange(e){
397 
398  if(((cellValue === null || typeof cellValue === "undefined") && input.value !== "") || input.value != cellValue){
399 
400  if(success(input.value)){
401  cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
402  }
403 
404  setTimeout(function(){
405  cell.getRow().normalizeHeight();
406  },300)
407  }else{
408  cancel();
409  }
410  }
411 
412  //submit new value on blur or change
413  input.addEventListener("change", onChange);
414  input.addEventListener("blur", onChange);
415 
416  input.addEventListener("keyup", function(){
417 
418  input.style.height = "";
419 
420  var heightNow = input.scrollHeight;
421 
422  input.style.height = heightNow + "px";
423 
424  if(heightNow != scrollHeight){
425  scrollHeight = heightNow;
426  cell.getRow().normalizeHeight();
427  }
428  });
429 
430  input.addEventListener("keydown", function(e){
431 
432  switch(e.keyCode){
433  case 27:
434  cancel();
435  break;
436 
437  case 38: //up arrow
438  if(vertNav == "editor" || (vertNav == "hybrid" && input.selectionStart)){
439  e.stopImmediatePropagation();
440  e.stopPropagation();
441  }
442 
443  break;
444 
445  case 40: //down arrow
446  if(vertNav == "editor" || (vertNav == "hybrid" && input.selectionStart !== input.value.length)){
447  e.stopImmediatePropagation();
448  e.stopPropagation();
449  }
450  break;
451  }
452  });
453 
454  return input;
455  },
456 
457  //input element with type of number
458  number:function(cell, onRendered, success, cancel, editorParams){
459 
460  var cellValue = cell.getValue(),
461  vertNav = editorParams.verticalNavigation || "editor",
462  input = document.createElement("input");
463 
464  input.setAttribute("type", "number");
465 
466  if(typeof editorParams.max != "undefined"){
467  input.setAttribute("max", editorParams.max);
468  }
469 
470  if(typeof editorParams.min != "undefined"){
471  input.setAttribute("min", editorParams.min);
472  }
473 
474  if(typeof editorParams.step != "undefined"){
475  input.setAttribute("step", editorParams.step);
476  }
477 
478  //create and style input
479  input.style.padding = "4px";
480  input.style.width = "100%";
481  input.style.boxSizing = "border-box";
482 
483  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
484  for (let key in editorParams.elementAttributes){
485  if(key.charAt(0) == "+"){
486  key = key.slice(1);
487  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
488  }else{
489  input.setAttribute(key, editorParams.elementAttributes[key]);
490  }
491  }
492  }
493 
494  input.value = cellValue;
495 
496  var blurFunc = function(e){
497  onChange();
498  };
499 
500  onRendered(function () {
501  //submit new value on blur
502  input.removeEventListener("blur", blurFunc);
503 
504  input.focus();
505  input.style.height = "100%";
506 
507  //submit new value on blur
508  input.addEventListener("blur", blurFunc);
509  });
510 
511  function onChange(){
512  var value = input.value;
513 
514  if(!isNaN(value) && value !==""){
515  value = Number(value);
516  }
517 
518  if(value != cellValue){
519  if(success(value)){
520  cellValue = value; //persist value if successfully validated incase editor is used as header filter
521  }
522  }else{
523  cancel();
524  }
525  }
526 
527  //submit new value on enter
528  input.addEventListener("keydown", function(e){
529  switch(e.keyCode){
530  case 13:
531  // case 9:
532  onChange();
533  break;
534 
535  case 27:
536  cancel();
537  break;
538 
539  case 38: //up arrow
540  case 40: //down arrow
541  if(vertNav == "editor"){
542  e.stopImmediatePropagation();
543  e.stopPropagation();
544  }
545  break;
546  }
547  });
548 
549  return input;
550  },
551 
552  //input element with type of number
553  range:function(cell, onRendered, success, cancel, editorParams){
554 
555  var cellValue = cell.getValue(),
556  input = document.createElement("input");
557 
558  input.setAttribute("type", "range");
559 
560  if (typeof editorParams.max != "undefined") {
561  input.setAttribute("max", editorParams.max);
562  }
563 
564  if (typeof editorParams.min != "undefined") {
565  input.setAttribute("min", editorParams.min);
566  }
567 
568  if (typeof editorParams.step != "undefined") {
569  input.setAttribute("step", editorParams.step);
570  }
571 
572  //create and style input
573  input.style.padding = "4px";
574  input.style.width = "100%";
575  input.style.boxSizing = "border-box";
576 
577  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
578  for (let key in editorParams.elementAttributes){
579  if(key.charAt(0) == "+"){
580  key = key.slice(1);
581  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
582  }else{
583  input.setAttribute(key, editorParams.elementAttributes[key]);
584  }
585  }
586  }
587 
588  input.value = cellValue;
589 
590  onRendered(function () {
591  input.focus();
592  input.style.height = "100%";
593  });
594 
595  function onChange(){
596  var value = input.value;
597 
598  if(!isNaN(value) && value !==""){
599  value = Number(value);
600  }
601 
602  if(value != cellValue){
603  if(success(value)){
604  cellValue = value; //persist value if successfully validated incase editor is used as header filter
605  }
606  }else{
607  cancel();
608  }
609  }
610 
611  //submit new value on blur
612  input.addEventListener("blur", function(e){
613  onChange();
614  });
615 
616  //submit new value on enter
617  input.addEventListener("keydown", function(e){
618  switch(e.keyCode){
619  case 13:
620  case 9:
621  onChange();
622  break;
623 
624  case 27:
625  cancel();
626  break;
627  }
628  });
629 
630  return input;
631  },
632 
633  //select
634  select:function(cell, onRendered, success, cancel, editorParams){
635  var self = this,
636  cellEl = cell.getElement(),
637  initialValue = cell.getValue(),
638  vertNav = editorParams.verticalNavigation || "editor",
639  initialDisplayValue = typeof initialValue !== "undefined" || initialValue === null ? initialValue : (typeof editorParams.defaultValue !== "undefined" ? editorParams.defaultValue : ""),
640  input = document.createElement("input"),
641  listEl = document.createElement("div"),
642  dataItems = [],
643  displayItems = [],
644  currentItem = {},
645  blurable = true;
646 
647  this.table.rowManager.element.addEventListener("scroll", cancelItem);
648 
649  if(Array.isArray(editorParams) || (!Array.isArray(editorParams) && typeof editorParams === "object" && !editorParams.values)){
650  console.warn("DEPRECATION WANRING - values for the select editor must now be passed into the values property of the editorParams object, not as the editorParams object");
651  editorParams = {values:editorParams};
652  }
653 
654  function getUniqueColumnValues(field){
655  var output = {},
656  data = self.table.getData(),
657  column;
658 
659  if(field){
660  column = self.table.columnManager.getColumnByField(field);
661  }else{
662  column = cell.getColumn()._getSelf();
663  }
664 
665  if(column){
666  data.forEach(function(row){
667  var val = column.getFieldValue(row);
668 
669  if(val !== null && typeof val !== "undefined" && val !== ""){
670  output[val] = true;
671  }
672  });
673 
674  if(editorParams.sortValuesList){
675  if(editorParams.sortValuesList == "asc"){
676  output = Object.keys(output).sort();
677  }else{
678  output = Object.keys(output).sort().reverse();
679  }
680  }else{
681  output = Object.keys(output);
682  }
683  }else{
684  console.warn("unable to find matching column to create select lookup list:", field);
685  }
686 
687  return output;
688  }
689 
690  function parseItems(inputValues, curentValue){
691  var dataList = [];
692  var displayList = [];
693 
694  function processComplexListItem(item){
695  var item = {
696  label:editorParams.listItemFormatter ? editorParams.listItemFormatter(item.value, item.label) : item.label,
697  value:item.value,
698  element:false,
699  };
700 
701  if(item.value === curentValue || (!isNaN(parseFloat(item.value)) && !isNaN(parseFloat(item.value)) && parseFloat(item.value) === parseFloat(curentValue))){
702  setCurrentItem(item);
703  }
704 
705  dataList.push(item);
706  displayList.push(item);
707 
708  return item;
709  }
710 
711  if(typeof inputValues == "function"){
712  inputValues = inputValues(cell);
713  }
714 
715  if(Array.isArray(inputValues)){
716  inputValues.forEach(function(value){
717  var item;
718 
719  if(typeof value === "object"){
720 
721  if(value.options){
722  item = {
723  label:value.label,
724  group:true,
725  element:false,
726  };
727 
728  displayList.push(item);
729 
730  value.options.forEach(function(item){
731  processComplexListItem(item);
732  });
733  }else{
734  processComplexListItem(value);
735  }
736 
737  }else{
738 
739  item = {
740  label:editorParams.listItemFormatter ? editorParams.listItemFormatter(value, value) : value,
741  value:value,
742  element:false,
743  };
744 
745  if(item.value === curentValue || (!isNaN(parseFloat(item.value)) && !isNaN(parseFloat(item.value)) && parseFloat(item.value) === parseFloat(curentValue))){
746  setCurrentItem(item);
747  }
748 
749  dataList.push(item);
750  displayList.push(item);
751  }
752  });
753  }else{
754  for(var key in inputValues){
755  var item = {
756  label:editorParams.listItemFormatter ? editorParams.listItemFormatter(key, inputValues[key]) : inputValues[key],
757  value:key,
758  element:false,
759  };
760 
761  if(item.value === curentValue || (!isNaN(parseFloat(item.value)) && !isNaN(parseFloat(item.value)) && parseFloat(item.value) === parseFloat(curentValue))){
762  setCurrentItem(item);
763  }
764 
765  dataList.push(item);
766  displayList.push(item);
767  }
768  }
769 
770  dataItems = dataList;
771  displayItems = displayList;
772 
773  fillList();
774  }
775 
776  function fillList(){
777  while(listEl.firstChild) listEl.removeChild(listEl.firstChild);
778 
779  displayItems.forEach(function(item){
780  var el = item.element;
781 
782  if(!el){
783 
784  if(item.group){
785  el = document.createElement("div");
786  el.classList.add("tabulator-edit-select-list-group");
787  el.tabIndex = 0;
788  el.innerHTML = item.label === "" ? "&nbsp;" : item.label;
789  }else{
790  el = document.createElement("div");
791  el.classList.add("tabulator-edit-select-list-item");
792  el.tabIndex = 0;
793  el.innerHTML = item.label === "" ? "&nbsp;" : item.label;
794 
795  el.addEventListener("click", function(){
796  setCurrentItem(item);
797  chooseItem();
798  });
799 
800  if(item === currentItem){
801  el.classList.add("active");
802  }
803  }
804 
805  el.addEventListener("mousedown", function(){
806  blurable = false;
807 
808  setTimeout(function(){
809  blurable = true;
810  }, 10);
811  });
812 
813  item.element = el;
814 
815 
816  }
817 
818  listEl.appendChild(el);
819  });
820  }
821 
822 
823  function setCurrentItem(item){
824 
825  if(currentItem && currentItem.element){
826  currentItem.element.classList.remove("active");
827  }
828 
829 
830  currentItem = item;
831  input.value = item.label === "&nbsp;" ? "" : item.label;
832 
833  if(item.element){
834  item.element.classList.add("active");
835  }
836  }
837 
838 
839  function chooseItem(){
840  hideList();
841 
842  if(initialValue !== currentItem.value){
843  initialValue = currentItem.value;
844  success(currentItem.value);
845  }else{
846  cancel();
847  }
848  }
849 
850  function cancelItem(){
851  hideList();
852  cancel();
853  }
854 
855  function showList(){
856  if(!listEl.parentNode){
857 
858  if(editorParams.values === true){
859  parseItems(getUniqueColumnValues(), initialDisplayValue);
860  }else if(typeof editorParams.values === "string"){
861  parseItems(getUniqueColumnValues(editorParams.values), initialDisplayValue);
862  }else{
863  parseItems(editorParams.values || [], initialDisplayValue);
864  }
865 
866 
867  var offset = Tabulator.prototype.helpers.elOffset(cellEl);
868 
869  listEl.style.minWidth = cellEl.offsetWidth + "px";
870 
871  listEl.style.top = (offset.top + cellEl.offsetHeight) + "px";
872  listEl.style.left = offset.left + "px";
873  document.body.appendChild(listEl);
874  }
875  }
876 
877  function hideList(){
878  if(listEl.parentNode){
879  listEl.parentNode.removeChild(listEl);
880  }
881 
882  removeScrollListener();
883  }
884 
885  function removeScrollListener() {
886  self.table.rowManager.element.removeEventListener("scroll", cancelItem);
887  }
888 
889  //style input
890  input.setAttribute("type", "text");
891 
892  input.style.padding = "4px";
893  input.style.width = "100%";
894  input.style.boxSizing = "border-box";
895  input.style.cursor = "default";
896  input.readOnly = (this.currentCell != false);
897 
898  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
899  for (let key in editorParams.elementAttributes){
900  if(key.charAt(0) == "+"){
901  key = key.slice(1);
902  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
903  }else{
904  input.setAttribute(key, editorParams.elementAttributes[key]);
905  }
906  }
907  }
908 
909  input.value = typeof initialValue !== "undefined" || initialValue === null ? initialValue : "";
910 
911  // if(editorParams.values === true){
912  // parseItems(getUniqueColumnValues(), initialValue);
913  // }else if(typeof editorParams.values === "string"){
914  // parseItems(getUniqueColumnValues(editorParams.values), initialValue);
915  // }else{
916  // parseItems(editorParams.values || [], initialValue);
917  // }
918 
919  //allow key based navigation
920  input.addEventListener("keydown", function(e){
921  var index;
922 
923  switch(e.keyCode){
924  case 38: //up arrow
925  index = dataItems.indexOf(currentItem);
926 
927  if(vertNav == "editor" || (vertNav == "hybrid" && index)){
928  e.stopImmediatePropagation();
929  e.stopPropagation();
930  e.preventDefault();
931 
932  if(index > 0){
933  setCurrentItem(dataItems[index - 1]);
934  }
935  }
936  break;
937 
938  case 40: //down arrow
939  index = dataItems.indexOf(currentItem);
940 
941  if(vertNav == "editor" || (vertNav == "hybrid" && index < dataItems.length - 1)){
942  e.stopImmediatePropagation();
943  e.stopPropagation();
944  e.preventDefault();
945 
946  if(index < dataItems.length - 1){
947  if(index == -1){
948  setCurrentItem(dataItems[0]);
949  }else{
950  setCurrentItem(dataItems[index + 1]);
951  }
952  }
953  }
954  break;
955 
956  case 37: //left arrow
957  case 39: //right arrow
958  e.stopImmediatePropagation();
959  e.stopPropagation();
960  e.preventDefault();
961  break;
962 
963  case 13: //enter
964  chooseItem();
965  break;
966 
967  case 27: //escape
968  cancelItem();
969  break;
970  }
971  });
972 
973  input.addEventListener("blur", function(e){
974  if(blurable){
975  cancelItem();
976  }
977  });
978 
979  input.addEventListener("focus", function(e){
980  showList();
981  });
982 
983  //style list element
984  listEl = document.createElement("div");
985  listEl.classList.add("tabulator-edit-select-list");
986 
987  onRendered(function(){
988  input.style.height = "100%";
989  input.focus();
990  });
991 
992  return input;
993  },
994 
995 
996  //autocomplete
997  autocomplete:function(cell, onRendered, success, cancel, editorParams){
998  var self = this,
999  cellEl = cell.getElement(),
1000  initialValue = cell.getValue(),
1001  vertNav = editorParams.verticalNavigation || "editor",
1002  initialDisplayValue = typeof initialValue !== "undefined" || initialValue === null ? initialValue : (typeof editorParams.defaultValue !== "undefined" ? editorParams.defaultValue : ""),
1003  input = document.createElement("input"),
1004  listEl = document.createElement("div"),
1005  allItems = [],
1006  displayItems = [],
1007  values = [],
1008  currentItem = {},
1009  blurable = true;
1010 
1011  this.table.rowManager.element.addEventListener("scroll", cancelItem);
1012 
1013  function getUniqueColumnValues(field){
1014  var output = {},
1015  data = self.table.getData(),
1016  column;
1017 
1018  if(field){
1019  column = self.table.columnManager.getColumnByField(field);
1020  }else{
1021  column = cell.getColumn()._getSelf();
1022  }
1023 
1024  if(column){
1025  data.forEach(function(row){
1026  var val = column.getFieldValue(row);
1027 
1028  if(val !== null && typeof val !== "undefined" && val !== ""){
1029  output[val] = true;
1030  }
1031  });
1032 
1033  if(editorParams.sortValuesList){
1034  if(editorParams.sortValuesList == "asc"){
1035  output = Object.keys(output).sort();
1036  }else{
1037  output = Object.keys(output).sort().reverse();
1038  }
1039  }else{
1040  output = Object.keys(output);
1041  }
1042  }else{
1043  console.warn("unable to find matching column to create autocomplete lookup list:", field);
1044  }
1045 
1046 
1047  return output;
1048  }
1049 
1050  function parseItems(inputValues, curentValue){
1051  var itemList = [];
1052 
1053  if(Array.isArray(inputValues)){
1054  inputValues.forEach(function(value){
1055  var item = {
1056  title:editorParams.listItemFormatter ? editorParams.listItemFormatter(value, value) : value,
1057  value:value,
1058  element:false,
1059  };
1060 
1061  if(item.value === curentValue || (!isNaN(parseFloat(item.value)) && !isNaN(parseFloat(item.value)) && parseFloat(item.value) === parseFloat(curentValue))){
1062  setCurrentItem(item);
1063  }
1064 
1065  itemList.push(item);
1066  });
1067  }else{
1068  for(var key in inputValues){
1069  var item = {
1070  title:editorParams.listItemFormatter ? editorParams.listItemFormatter(key, inputValues[key]) : inputValues[key],
1071  value:key,
1072  element:false,
1073  };
1074 
1075  if(item.value === curentValue || (!isNaN(parseFloat(item.value)) && !isNaN(parseFloat(item.value)) && parseFloat(item.value) === parseFloat(curentValue))){
1076  setCurrentItem(item);
1077  }
1078 
1079  itemList.push(item);
1080  }
1081  }
1082 
1083  if(editorParams.searchFunc){
1084  itemList.forEach(function(item){
1085  item.search = {
1086  title:item.title,
1087  value:item.value,
1088  };
1089  });
1090  }
1091 
1092  allItems = itemList;
1093  }
1094 
1095  function filterList(term, intialLoad){
1096  var matches = [],
1097  searchObjs = [],
1098  searchResults = [];
1099 
1100  if(editorParams.searchFunc){
1101 
1102  allItems.forEach(function(item){
1103  searchObjs.push(item.search);
1104  });
1105 
1106  searchResults = editorParams.searchFunc(term, searchObjs);
1107 
1108  searchResults.forEach(function(result){
1109  var match = allItems.find(function(item){
1110  return item.search === result;
1111  });
1112 
1113  if(match){
1114  matches.push(match);
1115  }
1116  });
1117  }else{
1118  if(term === ""){
1119 
1120  if(editorParams.showListOnEmpty){
1121  allItems.forEach(function(item){
1122  matches.push(item);
1123  });
1124  }
1125  }else{
1126  allItems.forEach(function(item){
1127 
1128  if(item.value !== null || typeof item.value !== "undefined"){
1129  if(String(item.value).toLowerCase().indexOf(String(term).toLowerCase()) > -1 || String(item.title).toLowerCase().indexOf(String(term).toLowerCase()) > -1){
1130  matches.push(item);
1131  }
1132  }
1133  });
1134  }
1135  }
1136 
1137  displayItems = matches;
1138 
1139  fillList(intialLoad);
1140  }
1141 
1142  function fillList(intialLoad){
1143  var current = false;
1144 
1145  while(listEl.firstChild) listEl.removeChild(listEl.firstChild);
1146 
1147  displayItems.forEach(function(item){
1148  var el = item.element;
1149 
1150  if(!el){
1151  el = document.createElement("div");
1152  el.classList.add("tabulator-edit-select-list-item");
1153  el.tabIndex = 0;
1154  el.innerHTML = item.title;
1155 
1156  el.addEventListener("click", function(){
1157  setCurrentItem(item);
1158  chooseItem();
1159  });
1160 
1161  el.addEventListener("mousedown", function(){
1162  blurable = false;
1163 
1164  setTimeout(function(){
1165  blurable = true;
1166  }, 10);
1167  });
1168 
1169  item.element = el;
1170 
1171  if(intialLoad && item.value == initialValue){
1172  input.value = item.title;
1173  item.element.classList.add("active");
1174  current = true;
1175  }
1176 
1177  if(item === currentItem){
1178  item.element.classList.add("active");
1179  current = true;
1180  }
1181  }
1182 
1183  listEl.appendChild(el);
1184  });
1185 
1186  if(!current){
1187  setCurrentItem(false);
1188  }
1189  }
1190 
1191 
1192  function setCurrentItem(item, showInputValue){
1193  if(currentItem && currentItem.element){
1194  currentItem.element.classList.remove("active");
1195  }
1196 
1197  currentItem = item;
1198 
1199  if(item && item.element){
1200  item.element.classList.add("active");
1201  }
1202  }
1203 
1204 
1205  function chooseItem(){
1206  hideList();
1207 
1208  if(currentItem){
1209  if(initialValue !== currentItem.value){
1210  initialValue = currentItem.value;
1211  input.value = currentItem.title;
1212  success(currentItem.value);
1213  }else{
1214  cancel();
1215  }
1216  }else{
1217  if(editorParams.freetext){
1218  initialValue = input.value;
1219  success(input.value);
1220  }else{
1221  if(editorParams.allowEmpty && input.value === ""){
1222  initialValue = input.value;
1223  success(input.value);
1224  }else{
1225  cancel();
1226  }
1227  }
1228  }
1229  }
1230 
1231  function cancelItem(){
1232  hideList();
1233  cancel();
1234  }
1235 
1236  function showList(){
1237  if(!listEl.parentNode){
1238  while(listEl.firstChild) listEl.removeChild(listEl.firstChild);
1239 
1240  if(editorParams.values === true){
1241  values = getUniqueColumnValues();
1242  }else if(typeof editorParams.values === "string"){
1243  values = getUniqueColumnValues(editorParams.values);
1244  }else{
1245  values = editorParams.values || [];
1246  }
1247 
1248  parseItems(values, initialValue);
1249 
1250  var offset = Tabulator.prototype.helpers.elOffset(cellEl);
1251 
1252  listEl.style.minWidth = cellEl.offsetWidth + "px";
1253 
1254  listEl.style.top = (offset.top + cellEl.offsetHeight) + "px";
1255  listEl.style.left = offset.left + "px";
1256  document.body.appendChild(listEl);
1257  }
1258  }
1259 
1260  function hideList(){
1261  if(listEl.parentNode){
1262  listEl.parentNode.removeChild(listEl);
1263  }
1264 
1265  removeScrollListener();
1266  }
1267 
1268  function removeScrollListener() {
1269  self.table.rowManager.element.removeEventListener("scroll", cancelItem);
1270  }
1271 
1272  //style input
1273  input.setAttribute("type", "search");
1274 
1275  input.style.padding = "4px";
1276  input.style.width = "100%";
1277  input.style.boxSizing = "border-box";
1278 
1279  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
1280  for (let key in editorParams.elementAttributes){
1281  if(key.charAt(0) == "+"){
1282  key = key.slice(1);
1283  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
1284  }else{
1285  input.setAttribute(key, editorParams.elementAttributes[key]);
1286  }
1287  }
1288  }
1289 
1290  //allow key based navigation
1291  input.addEventListener("keydown", function(e){
1292  var index;
1293 
1294  switch(e.keyCode){
1295  case 38: //up arrow
1296  index = displayItems.indexOf(currentItem);
1297 
1298  if(vertNav == "editor" || (vertNav == "hybrid" && index)){
1299  e.stopImmediatePropagation();
1300  e.stopPropagation();
1301  e.preventDefault();
1302 
1303 
1304  if(index > 0){
1305  setCurrentItem(displayItems[index - 1]);
1306  }else{
1307  setCurrentItem(false);
1308  }
1309  }
1310  break;
1311 
1312  case 40: //down arrow
1313 
1314  index = displayItems.indexOf(currentItem);
1315 
1316  if(vertNav == "editor" || (vertNav == "hybrid" && index < displayItems.length - 1)){
1317 
1318  e.stopImmediatePropagation();
1319  e.stopPropagation();
1320  e.preventDefault();
1321 
1322  if(index < displayItems.length - 1){
1323  if(index == -1){
1324  setCurrentItem(displayItems[0]);
1325  }else{
1326  setCurrentItem(displayItems[index + 1]);
1327  }
1328  }
1329  }
1330  break;
1331 
1332 
1333  case 37: //left arrow
1334  case 39: //right arrow
1335  e.stopImmediatePropagation();
1336  e.stopPropagation();
1337  e.preventDefault();
1338  break;
1339 
1340  case 13: //enter
1341  chooseItem();
1342  break;
1343 
1344  case 27: //escape
1345  cancelItem();
1346  break;
1347 
1348  case 36: //home
1349  case 35: //end
1350  //prevent table navigation while using input element
1351  e.stopImmediatePropagation();
1352  break;
1353  }
1354  });
1355 
1356  input.addEventListener("keyup", function(e){
1357 
1358  switch(e.keyCode){
1359  case 38: //up arrow
1360  case 37: //left arrow
1361  case 39: //up arrow
1362  case 40: //right arrow
1363  case 13: //enter
1364  case 27: //escape
1365  break;
1366 
1367  default:
1368  filterList(input.value);
1369  }
1370 
1371  });
1372 
1373  input.addEventListener("search", function(e){
1374  filterList(input.value);
1375  });
1376 
1377  input.addEventListener("blur", function(e){
1378  if(blurable){
1379  chooseItem();
1380  }
1381  });
1382 
1383  input.addEventListener("focus", function(e){
1384  var value = initialDisplayValue;
1385  showList();
1386  input.value = value;
1387  filterList(value, true);
1388  });
1389 
1390  //style list element
1391  listEl = document.createElement("div");
1392  listEl.classList.add("tabulator-edit-select-list");
1393 
1394  onRendered(function(){
1395  input.style.height = "100%";
1396  input.focus();
1397  });
1398 
1399  return input;
1400  },
1401 
1402  //start rating
1403  star:function(cell, onRendered, success, cancel, editorParams){
1404  var self = this,
1405  element = cell.getElement(),
1406  value = cell.getValue(),
1407  maxStars = element.getElementsByTagName("svg").length || 5,
1408  size = element.getElementsByTagName("svg")[0] ? element.getElementsByTagName("svg")[0].getAttribute("width") : 14,
1409  stars = [],
1410  starsHolder = document.createElement("div"),
1411  star = document.createElementNS('http://www.w3.org/2000/svg', "svg");
1412 
1413 
1414  //change star type
1415  function starChange(val){
1416  stars.forEach(function(star, i){
1417  if(i < val){
1418  if(self.table.browser == "ie"){
1419  star.setAttribute("class", "tabulator-star-active");
1420  }else{
1421  star.classList.replace("tabulator-star-inactive", "tabulator-star-active");
1422  }
1423 
1424  star.innerHTML = '<polygon fill="#488CE9" stroke="#014AAE" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>';
1425  }else{
1426  if(self.table.browser == "ie"){
1427  star.setAttribute("class", "tabulator-star-inactive");
1428  }else{
1429  star.classList.replace("tabulator-star-active", "tabulator-star-inactive");
1430  }
1431 
1432  star.innerHTML = '<polygon fill="#010155" stroke="#686868" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>';
1433  }
1434  });
1435  }
1436 
1437  //build stars
1438  function buildStar(i){
1439 
1440  var starHolder = document.createElement("span");
1441  var nextStar = star.cloneNode(true);
1442 
1443  stars.push(nextStar);
1444 
1445  starHolder.addEventListener("mouseenter", function(e){
1446  e.stopPropagation();
1447  e.stopImmediatePropagation();
1448  starChange(i);
1449  });
1450 
1451  starHolder.addEventListener("mousemove", function(e){
1452  e.stopPropagation();
1453  e.stopImmediatePropagation();
1454  });
1455 
1456  starHolder.addEventListener("click", function(e){
1457  e.stopPropagation();
1458  e.stopImmediatePropagation();
1459  success(i);
1460  });
1461 
1462  starHolder.appendChild(nextStar);
1463  starsHolder.appendChild(starHolder);
1464 
1465  }
1466 
1467  //handle keyboard navigation value change
1468  function changeValue(val){
1469  value = val;
1470  starChange(val);
1471  }
1472 
1473  //style cell
1474  element.style.whiteSpace = "nowrap";
1475  element.style.overflow = "hidden";
1476  element.style.textOverflow = "ellipsis";
1477 
1478  //style holding element
1479  starsHolder.style.verticalAlign = "middle";
1480  starsHolder.style.display = "inline-block";
1481  starsHolder.style.padding = "4px";
1482 
1483  //style star
1484  star.setAttribute("width", size);
1485  star.setAttribute("height", size);
1486  star.setAttribute("viewBox", "0 0 512 512");
1487  star.setAttribute("xml:space", "preserve");
1488  star.style.padding = "0 1px";
1489 
1490  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
1491  for (let key in editorParams.elementAttributes){
1492  if(key.charAt(0) == "+"){
1493  key = key.slice(1);
1494  starsHolder.setAttribute(key, starsHolder.getAttribute(key) + editorParams.elementAttributes["+" + key]);
1495  }else{
1496  starsHolder.setAttribute(key, editorParams.elementAttributes[key]);
1497  }
1498  }
1499  }
1500 
1501  //create correct number of stars
1502  for(var i=1;i<= maxStars;i++){
1503  buildStar(i);
1504  }
1505 
1506  //ensure value does not exceed number of stars
1507  value = Math.min(parseInt(value), maxStars);
1508 
1509  // set initial styling of stars
1510  starChange(value);
1511 
1512  starsHolder.addEventListener("mousemove", function(e){
1513  starChange(0);
1514  });
1515 
1516  starsHolder.addEventListener("click", function(e){
1517  success(0);
1518  });
1519 
1520  element.addEventListener("blur", function(e){
1521  cancel();
1522  });
1523 
1524  //allow key based navigation
1525  element.addEventListener("keydown", function(e){
1526  switch(e.keyCode){
1527  case 39: //right arrow
1528  changeValue(value + 1);
1529  break;
1530 
1531  case 37: //left arrow
1532  changeValue(value - 1);
1533  break;
1534 
1535  case 13: //enter
1536  success(value);
1537  break;
1538 
1539  case 27: //escape
1540  cancel();
1541  break;
1542  }
1543  });
1544 
1545  return starsHolder;
1546  },
1547 
1548  //draggable progress bar
1549  progress:function(cell, onRendered, success, cancel, editorParams){
1550  var element = cell.getElement(),
1551  max = typeof editorParams.max === "undefined" ? ( element.getElementsByTagName("div")[0].getAttribute("max") || 100) : editorParams.max,
1552  min = typeof editorParams.min === "undefined" ? ( element.getElementsByTagName("div")[0].getAttribute("min") || 0) : editorParams.min,
1553  percent = (max - min) / 100,
1554  value = cell.getValue() || 0,
1555  handle = document.createElement("div"),
1556  bar = document.createElement("div"),
1557  mouseDrag, mouseDragWidth;
1558 
1559  //set new value
1560  function updateValue(){
1561  var calcVal = (percent * Math.round(bar.offsetWidth / (element.clientWidth/100))) + min;
1562  success(calcVal);
1563  element.setAttribute("aria-valuenow", calcVal);
1564  element.setAttribute("aria-label", value);
1565  }
1566 
1567  //style handle
1568  handle.style.position = "absolute";
1569  handle.style.right = "0";
1570  handle.style.top = "0";
1571  handle.style.bottom = "0";
1572  handle.style.width = "5px";
1573  handle.classList.add("tabulator-progress-handle");
1574 
1575  //style bar
1576  bar.style.display = "inline-block";
1577  bar.style.position = "relative";
1578  // bar.style.top = "8px";
1579  // bar.style.bottom = "8px";
1580  // bar.style.left = "4px";
1581  // bar.style.marginRight = "4px";
1582  bar.style.height = "100%";
1583  bar.style.backgroundColor = "#488CE9";
1584  bar.style.maxWidth = "100%";
1585  bar.style.minWidth = "0%";
1586 
1587  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
1588  for (let key in editorParams.elementAttributes){
1589  if(key.charAt(0) == "+"){
1590  key = key.slice(1);
1591  bar.setAttribute(key, bar.getAttribute(key) + editorParams.elementAttributes["+" + key]);
1592  }else{
1593  bar.setAttribute(key, editorParams.elementAttributes[key]);
1594  }
1595  }
1596  }
1597 
1598  //style cell
1599  element.style.padding = "4px 4px";
1600 
1601  //make sure value is in range
1602  value = Math.min(parseFloat(value), max);
1603  value = Math.max(parseFloat(value), min);
1604 
1605  //workout percentage
1606  value = Math.round((value - min) / percent);
1607  // bar.style.right = value + "%";
1608  bar.style.width = value + "%";
1609 
1610  element.setAttribute("aria-valuemin", min);
1611  element.setAttribute("aria-valuemax", max);
1612 
1613  bar.appendChild(handle);
1614 
1615  handle.addEventListener("mousedown", function(e){
1616  mouseDrag = e.screenX;
1617  mouseDragWidth = bar.offsetWidth;
1618  });
1619 
1620  handle.addEventListener("mouseover", function(){
1621  handle.style.cursor = "ew-resize";
1622  });
1623 
1624  element.addEventListener("mousemove", function(e){
1625  if(mouseDrag){
1626  bar.style.width = (mouseDragWidth + e.screenX - mouseDrag) + "px";
1627  }
1628  });
1629 
1630  element.addEventListener("mouseup", function(e){
1631  if(mouseDrag){
1632  e.stopPropagation();
1633  e.stopImmediatePropagation();
1634 
1635  mouseDrag = false;
1636  mouseDragWidth = false;
1637 
1638  updateValue();
1639  }
1640  });
1641 
1642  //allow key based navigation
1643  element.addEventListener("keydown", function(e){
1644  switch(e.keyCode){
1645  case 39: //right arrow
1646  bar.style.width = (bar.clientWidth + element.clientWidth/100) + "px";
1647  break;
1648 
1649  case 37: //left arrow
1650  bar.style.width = (bar.clientWidth - element.clientWidth/100) + "px";
1651  break;
1652 
1653  case 13: //enter
1654  updateValue();
1655  break;
1656 
1657  case 27: //escape
1658  cancel();
1659  break;
1660 
1661  }
1662  });
1663 
1664  element.addEventListener("blur", function(){
1665  cancel();
1666  });
1667 
1668  return bar;
1669  },
1670 
1671  //checkbox
1672  tickCross:function(cell, onRendered, success, cancel, editorParams){
1673  var value = cell.getValue(),
1674  input = document.createElement("input"),
1675  tristate = editorParams.tristate,
1676  indetermValue = typeof editorParams.indeterminateValue === "undefined" ? null : editorParams.indeterminateValue,
1677  indetermState = false;
1678 
1679  input.setAttribute("type", "checkbox");
1680  input.style.marginTop = "5px";
1681  input.style.boxSizing = "border-box";
1682 
1683  if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
1684  for (let key in editorParams.elementAttributes){
1685  if(key.charAt(0) == "+"){
1686  key = key.slice(1);
1687  input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
1688  }else{
1689  input.setAttribute(key, editorParams.elementAttributes[key]);
1690  }
1691  }
1692  }
1693 
1694  input.value = value;
1695 
1696  if(tristate && (typeof value === "undefined" || value === indetermValue || value === "")){
1697  indetermState = true;
1698  input.indeterminate = true;
1699  }
1700 
1701  if(this.table.browser != "firefox"){ //prevent blur issue on mac firefox
1702  onRendered(function(){
1703  input.focus();
1704  });
1705  }
1706 
1707  input.checked = value === true || value === "true" || value === "True" || value === 1;
1708 
1709  function setValue(blur){
1710  if(tristate){
1711  if(!blur){
1712  if(input.checked && !indetermState){
1713  input.checked = false;
1714  input.indeterminate = true;
1715  indetermState = true;
1716  return indetermValue;
1717  }else{
1718  indetermState = false;
1719  return input.checked;
1720  }
1721  }else{
1722  if(indetermState){
1723  return indetermValue;
1724  }else{
1725  return input.checked;
1726  }
1727  }
1728  }else{
1729  return input.checked;
1730  }
1731  }
1732 
1733  //submit new value on blur
1734  input.addEventListener("change", function(e){
1735  success(setValue());
1736  });
1737 
1738  input.addEventListener("blur", function(e){
1739  success(setValue(true));
1740  });
1741 
1742  //submit new value on enter
1743  input.addEventListener("keydown", function(e){
1744  if(e.keyCode == 13){
1745  success(setValue());
1746  }
1747  if(e.keyCode == 27){
1748  cancel();
1749  }
1750  });
1751 
1752  return input;
1753  },
1754 };
1755 
1756 Tabulator.prototype.registerModule("edit", Edit);