handsontable-chosen-editor.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /// chosen plugin
  2. import Handsontable from "handsontable-pro"
  3. import 'handsontable-pro/dist/handsontable.full.css'
  4. import zhCN from 'handsontable-pro/languages/zh-CN';
  5. import $ from 'jquery'
  6. (function(Handsontable) {
  7. "use strict";
  8. var ChosenEditor = Handsontable.editors.TextEditor.prototype.extend();
  9. ChosenEditor.prototype.prepare = function(row, col, prop, td, originalValue, cellProperties) {
  10. Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);
  11. this.options = {};
  12. if (this.cellProperties.chosenOptions) {
  13. this.options = $.extend(this.options, cellProperties.chosenOptions);
  14. }
  15. cellProperties.chosenOptions = $.extend({}, cellProperties.chosenOptions);
  16. };
  17. ChosenEditor.prototype.createElements = function() {
  18. this.$body = $(document.body);
  19. this.TEXTAREA = document.createElement('select');
  20. //this.TEXTAREA.setAttribute('type', 'text');
  21. this.$textarea = $(this.TEXTAREA);
  22. Handsontable.dom.addClass(this.TEXTAREA, 'handsontableInput');
  23. this.textareaStyle = this.TEXTAREA.style;
  24. this.textareaStyle.width = 0;
  25. this.textareaStyle.height = 0;
  26. this.TEXTAREA_PARENT = document.createElement('DIV');
  27. Handsontable.dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder');
  28. this.textareaParentStyle = this.TEXTAREA_PARENT.style;
  29. this.textareaParentStyle.top = 0;
  30. this.textareaParentStyle.left = 0;
  31. this.textareaParentStyle.display = 'none';
  32. this.textareaParentStyle.width = "200px";
  33. this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
  34. this.instance.rootElement.appendChild(this.TEXTAREA_PARENT);
  35. var that = this;
  36. this.instance._registerTimeout(setTimeout(function() {
  37. that.refreshDimensions();
  38. }, 0));
  39. };
  40. var onChosenChanged = function() {
  41. var options = this.cellProperties.chosenOptions;
  42. if (!options.multiple) {
  43. this.close();
  44. this.finishEditing();
  45. }
  46. };
  47. var onChosenClosed = function() {
  48. var options = this.cellProperties.chosenOptions;
  49. if (!options.multiple) {
  50. this.close();
  51. this.finishEditing();
  52. } else {}
  53. };
  54. var onBeforeKeyDown = function(event) {
  55. var instance = this;
  56. var that = instance.getActiveEditor();
  57. var keyCodes = Handsontable.helper.KEY_CODES;
  58. var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
  59. //Process only events that have been fired in the editor
  60. if (event.target.tagName !== "INPUT") {
  61. return;
  62. }
  63. if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
  64. //when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
  65. event.stopImmediatePropagation();
  66. return;
  67. }
  68. var target = event.target;
  69. switch (event.keyCode) {
  70. case keyCodes.ARROW_RIGHT:
  71. if (Handsontable.dom.getCaretPosition(target) !== target.value.length) {
  72. event.stopImmediatePropagation();
  73. } else {
  74. that.$textarea.trigger("chosen:close");
  75. }
  76. break;
  77. case keyCodes.ARROW_LEFT:
  78. if (Handsontable.dom.getCaretPosition(target) !== 0) {
  79. event.stopImmediatePropagation();
  80. } else {
  81. that.$textarea.trigger("chosen:close");
  82. }
  83. break;
  84. case keyCodes.ENTER:
  85. if (that.cellProperties.chosenOptions.multiple) {
  86. event.stopImmediatePropagation();
  87. event.preventDefault();
  88. event.stopPropagation();
  89. }
  90. break;
  91. case keyCodes.A:
  92. case keyCodes.X:
  93. case keyCodes.C:
  94. case keyCodes.V:
  95. if (ctrlDown) {
  96. event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
  97. }
  98. break;
  99. case keyCodes.BACKSPACE:
  100. var txt = $(that.TEXTAREA_PARENT).find("input").val();
  101. $(that.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
  102. event.stopImmediatePropagation();
  103. break;
  104. case keyCodes.DELETE:
  105. case keyCodes.HOME:
  106. case keyCodes.END:
  107. event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)
  108. break;
  109. }
  110. };
  111. ChosenEditor.prototype.open = function(keyboardEvent) {
  112. this.refreshDimensions();
  113. this.textareaParentStyle.display = 'block';
  114. this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
  115. this.$textarea.css({
  116. height: $(this.TD).height() + 4,
  117. 'min-width': $(this.TD).outerWidth() - 4
  118. });
  119. //display the list
  120. this.$textarea.hide();
  121. //make sure that list positions matches cell position
  122. //this.$textarea.offset($(this.TD).offset());
  123. var options = $.extend({}, this.options, {
  124. width: "100%",
  125. search_contains: true
  126. });
  127. if (options.multiple) {
  128. this.$textarea.attr("multiple", true);
  129. } else {
  130. this.$textarea.attr("multiple", false);
  131. }
  132. this.$textarea.empty();
  133. this.$textarea.append("<option value=''></option>");
  134. var el = null;
  135. var originalValue = (this.originalValue + "").split(",");
  136. if (options.data && options.data.length) {
  137. for (var i = 0; i < options.data.length; i++) {
  138. // el = $("<option />");
  139. // el.attr("value", options.data[i].Code);
  140. // el.html(options.data[i].Name);
  141. // if (originalValue.indexOf(options.data[i].Code + "") > -1) {
  142. // el.attr("selected", true);
  143. // }
  144. // this.$textarea.append(el);
  145. if (options.data[i].content && options.data[i].content.length) {
  146. for (var k = 0; k < options.data[i].content.length; k++) {
  147. if (options.data[i].content[k] && options.data[i].content[k].length) {
  148. for (var j = 0; j < options.data[i].content[k].length; j++) {
  149. el = $("<option />");
  150. el.attr("value", options.data[i].content[k].content[j].Code);
  151. el.html(options.data[i].content[k].content[j].Name);
  152. if (originalValue.indexOf(options.data[i].content[k].content[j].Code + "") > -1) {
  153. el.attr("selected", true);
  154. }
  155. this.$textarea.append(el);
  156. }
  157. } else {
  158. el = $("<option />");
  159. el.attr("value", options.data[i].content[k].Code);
  160. el.html(options.data[i].content[k].Name);
  161. if (originalValue.indexOf(options.data[i].content[k].Code + "") > -1) {
  162. el.attr("selected", true);
  163. }
  164. this.$textarea.append(el);
  165. }
  166. }
  167. } else {
  168. el = $("<option />");
  169. el.attr("value", options.data[i].Code);
  170. el.html(options.data[i].Name);
  171. if (originalValue.indexOf(options.data[i].Code + "") > -1) {
  172. el.attr("selected", true);
  173. }
  174. this.$textarea.append(el);
  175. }
  176. }
  177. }
  178. if ($(this.TEXTAREA_PARENT).find(".chosen-container").length) {
  179. this.$textarea.chosen("destroy");
  180. }
  181. this.$textarea.chosen(options);
  182. var self = this;
  183. setTimeout(function() {
  184. self.$textarea.on('change', onChosenChanged.bind(self));
  185. self.$textarea.on('chosen:hiding_dropdown', onChosenClosed.bind(self));
  186. self.$textarea.trigger("chosen:open");
  187. $(self.TEXTAREA_PARENT).find("input").on("keydown", function(e) {
  188. if (e.keyCode === Handsontable.helper.KEY_CODES.ENTER /*|| e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE*/ ) {
  189. if ($(this).val()) {
  190. e.preventDefault();
  191. e.stopPropagation();
  192. } else {
  193. e.preventDefault();
  194. e.stopPropagation();
  195. self.close();
  196. self.finishEditing();
  197. }
  198. }
  199. if (e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE) {
  200. var txt = $(self.TEXTAREA_PARENT).find("input").val();
  201. $(self.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
  202. e.preventDefault();
  203. e.stopPropagation();
  204. }
  205. if (e.keyCode === Handsontable.helper.KEY_CODES.ARROW_DOWN || e.keyCode === Handsontable.helper.KEY_CODES.ARROW_UP) {
  206. e.preventDefault();
  207. e.stopPropagation();
  208. }
  209. });
  210. setTimeout(function() {
  211. self.$textarea.trigger("chosen:activate").focus();
  212. if (keyboardEvent && keyboardEvent.keyCode && keyboardEvent.keyCode != 113) {
  213. var key = keyboardEvent.keyCode;
  214. var keyText = (String.fromCharCode((96 <= key && key <= 105) ? key - 48 : key)).toLowerCase();
  215. $(self.TEXTAREA_PARENT).find("input").val(keyText).trigger("keyup.chosen");
  216. self.$textarea.trigger("chosen:activate");
  217. }
  218. }, 1);
  219. }, 1);
  220. };
  221. ChosenEditor.prototype.init = function() {
  222. Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
  223. };
  224. ChosenEditor.prototype.close = function() {
  225. this.instance.listen();
  226. this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
  227. this.$textarea.off();
  228. this.$textarea.hide();
  229. Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);
  230. };
  231. ChosenEditor.prototype.getValue = function() {
  232. if (!this.$textarea.val()) {
  233. return "";
  234. }
  235. if (typeof this.$textarea.val() === "object") {
  236. return this.$textarea.val().join(",");
  237. }
  238. return this.$textarea.val();
  239. };
  240. ChosenEditor.prototype.focus = function() {
  241. this.instance.listen();
  242. // DO NOT CALL THE BASE TEXTEDITOR FOCUS METHOD HERE, IT CAN MAKE THIS EDITOR BEHAVE POORLY AND HAS NO PURPOSE WITHIN THE CONTEXT OF THIS EDITOR
  243. //Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
  244. };
  245. ChosenEditor.prototype.beginEditing = function(initialValue) {
  246. var onBeginEditing = this.instance.getSettings().onBeginEditing;
  247. if (onBeginEditing && onBeginEditing() === false) {
  248. return;
  249. }
  250. Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);
  251. };
  252. ChosenEditor.prototype.finishEditing = function(isCancelled, ctrlDown) {
  253. this.instance.listen();
  254. return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
  255. };
  256. Handsontable.editors.ChosenEditor = ChosenEditor;
  257. Handsontable.editors.registerEditor('chosen', ChosenEditor);
  258. })(Handsontable);