Skip to content

Instantly share code, notes, and snippets.

@paulduran
Created November 18, 2014 06:13
Show Gist options
  • Save paulduran/e70a3084e925ce0ff27b to your computer and use it in GitHub Desktop.
Save paulduran/e70a3084e925ce0ff27b to your computer and use it in GitHub Desktop.
Update of select2 editor for handsontable (compatible with 0.11.4). Original source at https://github.com/trebuchetty/Handsontable-select2-editor
/// select2 plugin
(function (Handsontable) {
"use strict";
var Select2Editor = Handsontable.editors.TextEditor.prototype.extend();
Select2Editor.prototype.prepare = function (td, row, col, prop, value, cellProperties) {
Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);
this.options = {};
if (this.cellProperties.select2Options) {
this.options = $.extend(this.options, cellProperties.select2Options);
}
};
Select2Editor.prototype.createElements = function () {
this.$body = $(document.body);
this.TEXTAREA = document.createElement('input');
this.TEXTAREA.setAttribute('type', 'text');
this.$textarea = $(this.TEXTAREA);
Handsontable.Dom.addClass(this.TEXTAREA, 'handsontableInput');
this.textareaStyle = this.TEXTAREA.style;
this.textareaStyle.width = 0;
this.textareaStyle.height = 0;
this.TEXTAREA_PARENT = document.createElement('DIV');
Handsontable.Dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder');
this.textareaParentStyle = this.TEXTAREA_PARENT.style;
this.textareaParentStyle.top = 0;
this.textareaParentStyle.left = 0;
this.textareaParentStyle.display = 'none';
this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
this.instance.rootElement[0].appendChild(this.TEXTAREA_PARENT);
var that = this;
this.instance._registerTimeout(setTimeout(function () {
that.refreshDimensions();
}, 0));
};
var onSelect2Changed = function () {
this.close();
this.finishEditing();
};
var onSelect2Closed = function () {
this.close();
this.finishEditing();
};
var onBeforeKeyDown = function (event) {
var instance = this;
var that = instance.getActiveEditor();
var keyCodes = Handsontable.helper.keyCode;
var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
//Process only events that have been fired in the editor
if (!$(event.target).hasClass('select2-input') || event.isImmediatePropagationStopped()) {
return;
}
if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
//when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
event.stopImmediatePropagation();
return;
}
var target = event.target;
switch (event.keyCode) {
case keyCodes.ARROW_RIGHT:
if (Handsontable.Dom.getCaretPosition(target) !== target.value.length) {
event.stopImmediatePropagation();
} else {
that.$textarea.select2('close');
}
break;
case keyCodes.ARROW_LEFT:
if (Handsontable.Dom.getCaretPosition(target) !== 0) {
event.stopImmediatePropagation();
} else {
that.$textarea.select2('close');
}
break;
case keyCodes.ENTER:
var selected = that.instance.getSelected();
var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);
if ((ctrlDown && !isMultipleSelection) || event.altKey) { //if ctrl+enter or alt+enter, add new line
if (that.isOpened()) {
that.val(that.val() + '\n');
that.focus();
} else {
that.beginEditing(that.originalValue + '\n')
}
event.stopImmediatePropagation();
}
event.preventDefault(); //don't add newline to field
break;
case keyCodes.A:
case keyCodes.X:
case keyCodes.C:
case keyCodes.V:
if (ctrlDown) {
event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
}
break;
case keyCodes.BACKSPACE:
case keyCodes.DELETE:
case keyCodes.HOME:
case keyCodes.END:
event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)
break;
}
};
Select2Editor.prototype.open = function () {
this.refreshDimensions();
this.textareaParentStyle.display = 'block';
this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
this.$textarea.css({
height: $(this.TD).height() + 4,
'min-width': $(this.TD).outerWidth() - 4
});
//display the list
this.$textarea.show();
//make sure that list positions matches cell position
this.$textarea.offset($(this.TD).offset());
var self = this;
this.$textarea.select2(this.options)
.on('change', onSelect2Changed.bind(this))
.on('select2-close', onSelect2Closed.bind(this));
self.$textarea.select2('open');
};
Select2Editor.prototype.init = function () {
Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
};
Select2Editor.prototype.close = function () {
this.instance.listen();
this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
this.$textarea.off();
this.$textarea.hide();
Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);
};
Select2Editor.prototype.val = function (value) {
if (typeof value == 'undefined') {
return this.$textarea.val();
} else {
this.$textarea.val(value);
}
};
Select2Editor.prototype.focus = function () {
this.instance.listen();
// 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
//Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
};
Select2Editor.prototype.beginEditing = function (initialValue) {
var onBeginEditing = this.instance.getSettings().onBeginEditing;
if (onBeginEditing && onBeginEditing() === false) {
return;
}
Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);
};
Select2Editor.prototype.finishEditing = function (isCancelled, ctrlDown) {
this.instance.listen();
return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
};
Handsontable.editors.Select2Editor = Select2Editor;
Handsontable.editors.registerEditor('select2', Select2Editor);
})(Handsontable);
@motin
Copy link

motin commented Jul 7, 2015

Thanks. I included this fix in the following PR: trebuchetty/Handsontable-select2-editor#4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment