Skip to content

Commit

Permalink
continued - reimplement cell editing abstraction. Now TextEditor `<te…
Browse files Browse the repository at this point in the history
…xtarea>` is decoupled from cell selection and copy/paste keyboard handling; upgrade Bootstrap Typeahead to v2.3.0
  • Loading branch information
warpech committed Feb 25, 2013
1 parent 14e4cc1 commit 1eb01bd
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 340 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Bugfix:
- scrolls to top of table on any key press if the top is not on the screen ([#348](https://github.com/warpech/jquery-handsontable/issues/348))

Other:
- reimplement cell editing abstraction. Now TextEditor `<textarea>` is decoupled from cell selection and copy/paste keyboard handling
- upgrade Bootstrap Typeahead to v2.3.0
- build system now requires Grunt 0.4.0

## [0.8.5](https://github.com/warpech/jquery-handsontable/tree/v0.8.5) (Feb 18, 2013)
Expand Down
2 changes: 1 addition & 1 deletion dist/jquery.handsontable.full.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Licensed under the MIT license.
* http://handsontable.com/
*
* Date: Mon Feb 25 2013 13:24:19 GMT+0100 (Central European Standard Time)
* Date: Mon Feb 25 2013 19:56:16 GMT+0100 (Central European Standard Time)
*/

.handsontable {
Expand Down
177 changes: 64 additions & 113 deletions dist/jquery.handsontable.full.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Licensed under the MIT license.
* http://handsontable.com/
*
* Date: Mon Feb 25 2013 13:24:19 GMT+0100 (Central European Standard Time)
* Date: Mon Feb 25 2013 19:56:16 GMT+0100 (Central European Standard Time)
*/
/*jslint white: true, browser: true, plusplus: true, indent: 4, maxerr: 50 */

Expand Down Expand Up @@ -2260,7 +2260,7 @@ Handsontable.TableView = function (instance) {
};

Handsontable.TableView.prototype.isCellEdited = function () {
return this.instance.textEditor && this.instance.textEditor.isCellEdited;
return (this.instance.textEditor && this.instance.textEditor.isCellEdited) || (this.instance.autocompleteEditor && this.instance.autocompleteEditor.isCellEdited);
};

Handsontable.TableView.prototype.determineContainerSize = function () {
Expand Down Expand Up @@ -2615,8 +2615,6 @@ function HandsontableTextEditorClass(instance) {
overflow: 'hidden'
});

var that = this;

/*instance.that.TEXTAREA.on('blur.editor', function () {
if (that.isCellEdited) {
that.finishEditing(false);
Expand All @@ -2630,8 +2628,11 @@ function HandsontableTextEditorClass(instance) {
}
}, 0);
});*/
}

this.TEXTAREA_PARENT.on('keydown', function (event) {
HandsontableTextEditorClass.prototype.bindEvents = function () {
var that = this;
this.TEXTAREA_PARENT.off('.editor').on('keydown.editor', function (event) {
//if we are here then isCellEdited === true

var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
Expand Down Expand Up @@ -2677,7 +2678,7 @@ function HandsontableTextEditorClass(instance) {
break;

case 13: /* return/enter */
var selected = instance.getSelected();
var selected = that.instance.getSelected();
var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);
if ((event.ctrlKey && !isMultipleSelection) || event.altKey) { //if ctrl+enter or alt+enter, add new line
that.TEXTAREA.val(that.TEXTAREA.val() + '\n');
Expand Down Expand Up @@ -2875,6 +2876,7 @@ HandsontableTextEditorClass.prototype.finishEditing = function (isCancelled, ctr
this.isCellEdited = false;
var val;
if (isCancelled) {

val = [
[this.originalValue]
];
Expand All @@ -2892,17 +2894,12 @@ HandsontableTextEditorClass.prototype.finishEditing = function (isCancelled, ctr
this.instance.populateFromArray({row: this.row, col: this.col}, val, null, false, 'edit');
}
}
this.TEXTAREA.off(".editor");

this.instance.$table.off(".editor");
this.instance.$table[0].focus();
this.instance.view.wt.update('onCellDblClick', null);

this.TEXTAREA.css({
width: 0,
height: 0
});
this.TEXTAREA_PARENT.addClass('htHidden').css({
overflow: 'hidden'
});
this.TEXTAREA_PARENT.remove();

this.instance.rootElement.triggerHandler('finishediting.handsontable');
}
Expand All @@ -2922,6 +2919,8 @@ Handsontable.TextEditor = function (instance, td, row, col, prop, ___unused___,
instance.textEditor = new HandsontableTextEditorClass(instance);
}

instance.textEditor.bindEvents();

instance.textEditor.isCellEdited = false;
instance.textEditor.originalValue = instance.getDataAtCell(row, prop);

Expand Down Expand Up @@ -3005,106 +3004,59 @@ function HandsontableAutocompleteEditorClass(instance) {
typeahead.matcher = function () {
return true;
};
}

this.TEXTAREA.on('keydown', function (event) {
var restorePropagation = event.isPropagationStopped();
for (var i in HandsontableTextEditorClass.prototype) {
if (HandsontableTextEditorClass.prototype.hasOwnProperty(i)) {
HandsontableAutocompleteEditorClass.prototype[i] = HandsontableTextEditorClass.prototype[i];
}
}

//if we are here then isCellEdited === true
HandsontableAutocompleteEditorClass.prototype._bindEvents = HandsontableTextEditorClass.prototype.bindEvents;

var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
HandsontableAutocompleteEditorClass.prototype.bindEvents = function () {
var that = this;

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.stopPropagation();
return;
}
this.typeahead.listen();

this.TEXTAREA.off('keydown'); //unlisten
this.TEXTAREA.off('keyup'); //unlisten
this.TEXTAREA.off('keypress'); //unlisten

this.TEXTAREA_PARENT.off('.acEditor').on('keydown.acEditor', function (event) {
switch (event.keyCode) {
case 38: /* arrow up */
case 40: /* arrow down */
event.stopPropagation();
restorePropagation = false;
break;

case 9: /* tab */
that.finishEditing(false);
event.preventDefault();
break;

case 39: /* arrow right */
if (that.getCaretPosition(that.TEXTAREA[0]) === that.TEXTAREA.val().length) {
that.finishEditing(false);
}
else {
event.stopPropagation();
restorePropagation = false;
}
break;

case 37: /* arrow left */
if (that.getCaretPosition(that.TEXTAREA[0]) === 0) {
that.finishEditing(false);
}
else {
event.stopPropagation();
restorePropagation = false;
}
break;

case 27: /* ESC */
that.instance.destroyEditor(true);
event.stopPropagation();
restorePropagation = false;
that.typeahead.prev();
event.stopImmediatePropagation();
break;

case 13: /* return/enter */
if (!that.isMenuExpanded()) {
that.finishEditing(false, ctrlDown);
//event.stopPropagation(); //cancel because typeahead will trigger change
//restorePropagation = false;
}
else {
//event.stopPropagation(); //cancel because typeahead will trigger change
//restorePropagation = false;

var ev = $.Event('keyup'); //because core.js keydown handler moves focus
ev.keyCode = event.keyCode;
that.TEXTAREA.triggerHandler(ev);
}
event.preventDefault(); //don't add newline to field
case 40: /* arrow down */
that.typeahead.next();
event.stopImmediatePropagation();
break;

case 8: /* backspace */
case 46: /* delete */
case 36: /* home */
case 35: /* end */
event.stopPropagation();
restorePropagation = false;
case 13: /* enter */
event.preventDefault();
break;
}

if (restorePropagation) { //typeahead stops propagation but we don't want that
var ev = $.Event('keydown');
ev.keyCode = event.keyCode;
that.TEXTAREA_PARENT.trigger(ev);
}
});
}

for (var i in HandsontableTextEditorClass.prototype) {
if (HandsontableTextEditorClass.prototype.hasOwnProperty(i)) {
HandsontableAutocompleteEditorClass.prototype[i] = HandsontableTextEditorClass.prototype[i];
}
this._bindEvents();
}

HandsontableAutocompleteEditorClass.prototype._beginEditing = HandsontableTextEditorClass.prototype.beginEditing;

HandsontableAutocompleteEditorClass.prototype.beginEditing = function (row, col, prop, useOriginalValue, suffix) {
this._beginEditing(row, col, prop, useOriginalValue, suffix);
var that = this;
setTimeout(function () {
that.typeahead.show(); //otherwise typeahead appears misaligned
}, 0);
}

HandsontableAutocompleteEditorClass.prototype._finishEditing = HandsontableTextEditorClass.prototype.finishEditing;

HandsontableAutocompleteEditorClass.prototype.finishEditing = function (isCancelled, ctrlDown) {
if (this.isMenuExpanded()) {
this.typeahead.select(true);
}
this._finishEditing(isCancelled, ctrlDown);
}

HandsontableAutocompleteEditorClass.prototype.isMenuExpanded = function () {
Expand Down Expand Up @@ -3134,19 +3086,20 @@ Handsontable.AutocompleteEditor = function (instance, td, row, col, prop, __unus
instance.autocompleteEditor = new HandsontableAutocompleteEditorClass(instance);
}

instance.autocompleteEditor.bindEvents();

instance.autocompleteEditor.isCellEdited = false;
instance.autocompleteEditor.originalValue = instance.getDataAtCell(row, prop);

var typeahead = instance.autocompleteEditor.typeahead;

typeahead.select = function () {
if (instance.autocompleteEditor.dontHide) {
instance.autocompleteEditor.dontHide = false;
return;
typeahead.select = function (calledFromFinishEditing) {
if (this.$menu.find('.active').length) {
instance.autocompleteEditor.TEXTAREA.val(this.$menu.find('.active').attr('data-value'));
}
if (!calledFromFinishEditing) {
instance.destroyEditor();
}
var val = this.$menu.find('.active').attr('data-value') || instance.autocompleteEditor.TEXTAREA.val();
destroyer(true);
instance.setDataAtCell(row, prop, typeahead.updater(val));
return this.hide();
};

Expand Down Expand Up @@ -3175,57 +3128,55 @@ Handsontable.AutocompleteEditor = function (instance, td, row, col, prop, __unus
}

var that = this;
instance.autocompleteEditor.dontHide = false;
instance.$table.on('keydown.editor', function (event) {
var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
var lookupOnKeyUp = false;
if (!instance.autocompleteEditor.isCellEdited) {
if (Handsontable.helper.isPrintableChar(event.keyCode)) {
if (!ctrlDown) { //disregard CTRL-key shortcuts
instance.autocompleteEditor.beginEditing(row, col, prop);
instance.autocompleteEditor.dontHide = true;
typeahead.lookup();
lookupOnKeyUp = true;
}
}
else if (event.keyCode === 113) { //f2
instance.autocompleteEditor.beginEditing(row, col, prop, true); //show edit field
lookupOnKeyUp = true;
event.stopPropagation();
event.preventDefault(); //prevent Opera from opening Go to Page dialog
instance.autocompleteEditor.dontHide = true;
typeahead.lookup();
}
else if (event.keyCode === 13 && instance.getSettings().enterBeginsEditing) { //enter
//instance.autocompleteEditor.dontHide = true;
var selected = 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
instance.autocompleteEditor.beginEditing(row, col, prop, true, '\n'); //show edit field
lookupOnKeyUp = true;
}
else {
instance.autocompleteEditor.beginEditing(row, col, prop, true); //show edit field
lookupOnKeyUp = true;
}
event.preventDefault(); //prevent new line at the end of textarea
event.stopPropagation();

instance.autocompleteEditor.dontHide = true;
typeahead.lookup();
}
}
if (lookupOnKeyUp) {
instance.autocompleteEditor.TEXTAREA_PARENT.one('keyup.acEditor', function (event) {
instance.autocompleteEditor.typeahead.lookup();
});
}
});

function onDblClick() {
instance.autocompleteEditor.beginEditing(row, col, prop, true);
setTimeout(function () { //otherwise is misaligned in IE9
instance.autocompleteEditor.TEXTAREA.data('typeahead').lookup();
instance.autocompleteEditor.typeahead.lookup();
}, 1);
}

instance.view.wt.update('onCellDblClick', onDblClick);

var destroyer = function (isCancelled) {
instance.autocompleteEditor.finishEditing(isCancelled);
if (instance.autocompleteEditor.isMenuExpanded()) {
instance.autocompleteEditor.isMenuExpanded().hide();
}
}

return destroyer;
Expand Down
2 changes: 1 addition & 1 deletion jquery.handsontable.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Licensed under the MIT license.
* http://handsontable.com/
*
* Date: Mon Feb 25 2013 13:24:19 GMT+0100 (Central European Standard Time)
* Date: Mon Feb 25 2013 19:56:16 GMT+0100 (Central European Standard Time)
*/

.handsontable {
Expand Down
Loading

0 comments on commit 1eb01bd

Please sign in to comment.