Skip to content

Instantly share code, notes, and snippets.

@lukehorvat
Last active June 20, 2024 00:09

Revisions

  1. lukehorvat revised this gist Jun 20, 2024. No changes.
  2. lukehorvat revised this gist May 28, 2013. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion excel-grid-plugin.js
    Original file line number Diff line number Diff line change
    @@ -139,9 +139,14 @@ Ext.override(Ext.Editor, {
    field.setValue(value);
    }
    else {
    // custom behaviour to handle alphanumeric key presses from non-edit mode
    // custom behaviour to handle an alphanumeric key press from non-edit mode
    field.setRawValue(newGridCellValue);
    newGridCellValue = ''; // reset global variable

    if (field instanceof Ext.form.field.ComboBox) {
    // force the combo box's filtered dropdown list to be displayed (some browsers need this)
    field.doQueryTask.delay(field.queryDelay);
    }
    }

    me.realign(true);
  3. lukehorvat created this gist May 19, 2013.
    186 changes: 186 additions & 0 deletions excel-grid-plugin.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,186 @@
    var newGridCellValue = '',
    deleteGridCellValue = false;

    Ext.define('ExcelCellEditing', {
    extend: 'Ext.grid.plugin.CellEditing',
    alias: 'plugin.excelcellediting',

    initEditTriggers: function () {
    var me = this;

    var keys = [];
    for (var i = 48; i < 58; i++) { keys.push(i); } // 0-9
    for (var i = 65; i < 91; i++) { keys.push(i); } // A-Z
    for (var i = 97; i < 123; i++) { keys.push(i); } // a-z

    // listen for particular key presses made over cells
    me.view.addListener('render', function () {
    var keyPressMap = new Ext.util.KeyMap({
    target: me.view.el,
    eventName: 'keypress',
    binding: [{
    key: keys,
    handler: me.onAlphaNumericKey,
    scope: me
    }]
    });

    var keyDownMap = new Ext.util.KeyMap({
    target: me.view.el,
    eventName: 'keydown',
    binding: [{
    key: Ext.EventObject.DELETE,
    handler: me.onDeleteKey,
    scope: me
    }, {
    key: Ext.EventObject.BACKSPACE,
    handler: me.onBackspaceKey,
    scope: me
    }]
    });

    }, me, { single: true });

    me.callParent(arguments);
    },
    onAlphaNumericKey: function (keyCode, e) { // only executes before a cell has entered edit mode
    var me = this,
    grid = me.grid,
    pos = grid.getSelectionModel().getCurrentPosition(),
    record = grid.store.getAt(pos.row),
    columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);

    if (me.getEditor(record, columnHeader)) {
    // insert the key pressed into the editor field and start editing
    newGridCellValue = String.fromCharCode(keyCode);
    me.startEdit(record, columnHeader);
    }
    },
    onBackspaceKey: function (keyCode, e) { // only executes before a cell has entered edit mode
    var me = this;

    e.stopEvent(); // cancel the default browser behaviour of navigating one page back
    me.onDeleteKey(keyCode, e);
    },
    onDeleteKey: function (keyCode, e) { // only executes before a cell has entered edit mode
    var me = this,
    grid = me.grid,
    pos = grid.getSelectionModel().getCurrentPosition(),
    record = grid.store.getAt(pos.row),
    columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);

    if (me.getEditor(record, columnHeader)) {
    // perform an "instantaneous" edit that essentially just sets the value of the cell to nothing
    deleteGridCellValue = true;
    me.startEdit(record, columnHeader);
    }
    },
    onEnterKey: function (e) { // only executes before a cell has entered edit mode
    var me = this,
    grid = me.grid,
    sm = grid.getSelectionModel();

    me.callParent(arguments);

    // cellmodel navigates left/right when tab key is pressed by default, but not up/down when enter is pressed
    // the code below enables this functionality for cells that are not editable
    if (!grid.headerCt.getHeaderAtIndex(sm.getCurrentPosition().column).getEditor()) {
    sm.move(e.shiftKey ? 'up' : 'down', e);
    }
    },
    onSpecialKey: function (ed, field, e) { // only executes when a cell is in edit mode
    var me = this,
    sm = me.grid.getSelectionModel();

    // cellmodel navigates left/right when tab key is pressed by default, but not up/down when enter is pressed
    // the code below enables this functionality for cells that are editable
    if (e.getKey() === e.ENTER) {
    me.addListener('edit', function () {
    sm.move(e.shiftKey ? 'up' : 'down', e); // navigate up/down once edit completes
    }, me, { single: true });
    }

    me.callParent(arguments);
    }
    });

    /**
    * The following override allows for keys pressed over a grid cell that isn't yet in edit mode to be persisted into
    * the cell once edit mode activates. It does this by getting the value of a temporary global variable that is set
    * by the cell editing plugin above.
    */
    Ext.override(Ext.Editor, {
    startEdit: function (el, value) {
    var me = this,
    field = me.field;

    me.completeEdit();
    me.boundEl = Ext.get(el);
    value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;

    if (!me.rendered) {
    me.render(me.parentEl || document.body);
    }

    if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
    me.startValue = value;
    me.show();
    field.reset();

    if (deleteGridCellValue) {
    field.setValue('');
    me.editing = true;
    me.completeEdit();
    deleteGridCellValue = false; // reset global variable
    }
    else {
    if (newGridCellValue == '') {
    // default behaviour of Ext.Editor (see source if needed)
    field.setValue(value);
    }
    else {
    // custom behaviour to handle alphanumeric key presses from non-edit mode
    field.setRawValue(newGridCellValue);
    newGridCellValue = ''; // reset global variable
    }

    me.realign(true);
    field.focus(false, 10);
    if (field.autoSize) {
    field.autoSize();
    }
    me.editing = true;
    }
    }
    }
    });

    /**
    * The following override fixes a quirk in Internet Explorer where the text cursor/caret is positioned at the beginning
    * of a cell's field the first time its editor is activated. The quirk makes instant grid cell editing on keypress difficult,
    * because the caret gets positioned BEFORE text already in the cell, causing the user to prepend text rather than append.
    */
    Ext.override(Ext.dom.Element, {
    focus: function (defer, dom) {
    var me = this,
    dom = dom || me.dom;

    try {
    if (Number(defer)) {
    Ext.defer(me.focus, defer, me, [null, dom]);
    } else {
    dom.focus();

    // start override
    dom.value = dom.value;
    dom.focus();
    if (dom.sof) {
    dom.select();
    }
    // end override
    }
    } catch (e) { }

    return me;
    }
    });