Excel-like enter and tab key navigation in cell editing
Asked Answered
J

4

8

one question for all advanced in jqgrid.

i have to code this usecase:

In jqGrid there are two editable columns. I have to use cell editing. User click to one editable cell and when he presses 'Enter' key, i select next editable cell UNDER actual one.

Otherwise, when he hits 'tab' key, i select next editable cell

  • if actual cell is last, i set the nearest editable cell in the next line or
  • if not, i select next editable cell in the actual row.

to sum up – i need exact behaviour like in excel.

if i had better reputation, I could have uploaded an image to demonstrate desired situation. alt text

thanks a lot.

Jeromejeromy answered 7/1, 2011 at 18:30 Comment(1)
I included image which I found from your question in the trirand forum (see trirand.com/blog/?page_id=393/help/…)Impanation
I
7

Ahoj!

To bind editable cell to your custom event handler there are common setting in jqGrid: dataEvents property of editoptions. Absolutely the same settings exist for the searching in jqGrid. You can find some code examples here, here and here. You will probably needed to use cell editing methods inside of the keyboard event handler to be able to end editing of one cell and to start editing of another one.

If you will have problem in the implementation you can append your question with the code example and then one can try to modify it.

Impanation answered 7/1, 2011 at 19:59 Comment(0)
J
11

your answer helps me a lot and directs me to right solution, although i spent longer than 3 hours to write right code, but i managed this :)

thanks a lot.

to sum up:

i defined 2 variables:

var selICol; //iCol of selected cell
var selIRow; //iRow of selected cell

i set them in beforeEditCell events:

beforeEditCell : function(rowid, cellname, value, iRow, iCol)
{
    selICol = iCol;
    selIRow = iRow;
},

and then in editoptions for both editable cells i set:

first editable cell in row (Inventúrny stav in the picture), behaviour on press tab to select next editable cell is default

editoptions: {
    dataInit : function (elem) { $(elem).focus(function(){ this.select();}) },
    dataEvents: [
        { 
            type: 'keydown', 
            fn: function(e) { 
                var key = e.charCode || e.keyCode;
                if (key == 13)//enter
                {
                    setTimeout("jQuery('#inventuraGrid').editCell(" + selIRow + " + 1, " + selICol + ", true);", 100);
                }
            }
        } 
    ]
}

second editable cell in row (Sklad. cena in the picture) - i manually set iCol for next editable cell in the next row

editoptions: {
    dataInit : function (elem) { $(elem).focus(function(){ this.select();}) },
    dataEvents: [
        { 
            type: 'keydown', 
            fn: function(e) { 
                var key = e.charCode || e.keyCode;
                if(key == 9)   // tab
                {
                    setTimeout("jQuery('#inventuraGrid').editCell(" + selIRow + " + 1, 4, true);", 100);
                }
                else if (key == 13)//enter
                {
                    setTimeout("jQuery('#inventuraGrid').editCell(" + selIRow + " + 1, " + selICol + ", true);", 100);
                }
            }
        } 
    ]
}
Jeromejeromy answered 10/1, 2011 at 15:47 Comment(11)
Nice to hear that I could help you and the problem is solved. I find very good, that you published the final solution here to share it with other. So +1 from me. Strange I find only that you have to use setTimeout(...,100). It means, that jqGrid do something parallel. Moreover you call only editCell and no time saveCell or restoreCell. Why? One small remark: for performance you can save jQuery('#inventuraGrid') in a var (var grid=jQuery('#inventuraGrid')) and not search the same element every time.Impanation
Look at the code of jqGrid: github.com/tonytomov/jqGrid/blob/master/js/grid.celledit.js#L74 and github.com/tonytomov/jqGrid/blob/master/js/…. You need do close thiings, but go in the next row if needed. It can be easer to unbind the original keydown event of jqGrid and you youth one or change nextCell to your fixed implementation (overwrite nextCell dynamically in memory): $.jgrid.extend({nextCell : function (iRow,iCol) {/*your code*/}});Impanation
Who should know, that enter sends comment immediately? :) I had to use setTimeout because firebug showed me very long js exception, when I tried to call editCell.When I used setTimeout, exception gone:) Your performance point is awesome and simple too, but when i set variable outside setTimeout statement, firebug warns me,that variable grid is not set. But I use your advice and refactored a lot of lines of my js code :) And why I called only editCell? Frankly, I don't know. Maybe because editCell set cell to editing mode and restoreCell and saveCell is called despite of my alternation od code.Jeromejeromy
To your second comment - I'm very grateful to you for enhancement, but it's over my js skills, I think :) And another problems - nextCell is called only on pressing tab. Next - I have to set user under the actual cell, even he changed nothing. I tried to play with this, but with no desirable effects. But for now my original solution works perfectly. But I admit that your suggestion is cleaner.Jeromejeromy
@kajo: I read your comments just now accidentally, because I don't receive any notification. Please use @Impanation as a prefix (see more information here meta.stackexchange.com/questions/43019/…). Now about the code. If your solution works, it is probably better to do nothing more. If you do decide to play with overriding (subclass) nextCell or other functions I could explain you later how to do thisImpanation
@Impanation - You were right :) In production I found out mistakes in my code - navigation was ok, but saving cell content was problem, so I tried to use your suggestion to override jqgrid core function and It works absolutely perfect and I'm proud of it, that I was able to play with this hardcore javascript :) I attach code of rewrited functions - jsfiddle.net/tX6yj It works for 'tab' key. Enter was a little bit harder, but I manage to navigate as I wanted. So thank U again.Jeromejeromy
@kajo: I am glad to hear this. Congratulation! How you see the overwriting of methods in JavaScript is not so difficult. More complex is to write the correct implementation for 'tab', 'enter' and so on, but having full open source of the code of jqGrid help.Impanation
@Kajo: I have similar question posted in #6782112 . how to use your code to move to next /previous row if inline edit is active?Isodiametric
@Jeromejeromy I've implemented this almost the same (binding Enter and Up and Down arrows, but not Tab), but when pressing Enter in a cell, the save cell method is being called twice. I only get this with Enter tho; it's fine with the arrow keys. So I'm assuming it's related to some way that jqgrid is already doing something with Enter key. Do you have this same issue?Allusion
@Allusion I don't remember, it was while ago. Probably I didn't face this issue. Let me know if you can solve this thing.Jeromejeromy
You can actually just use "bindKeys" trirand.com/jqgridwiki/doku.php?id=wiki:methods. It will automatically make the key up and down work like Excel.Nit
I
7

Ahoj!

To bind editable cell to your custom event handler there are common setting in jqGrid: dataEvents property of editoptions. Absolutely the same settings exist for the searching in jqGrid. You can find some code examples here, here and here. You will probably needed to use cell editing methods inside of the keyboard event handler to be able to end editing of one cell and to start editing of another one.

If you will have problem in the implementation you can append your question with the code example and then one can try to modify it.

Impanation answered 7/1, 2011 at 19:59 Comment(0)
B
2

I realize this is an old topic, but I recently wrestled with this and thought I would share the approach that worked for me:

jQuery('#grid').jqGrid({
  ...,  
  cellEdit: true,  // Make sure we are using cell edit
  afterEditCell: function(rowid, cellname, value, iRow, iCol) {

    // Get a handle to the actual input field
    var inputControl = jQuery('#' + (iRow) + '_' + cellname);

    // Listen for enter (and shift-enter)
    inputControl.bind("keydown",function(e) {

      if (e.keyCode === 13) {  // Enter key:
        var increment = e.shiftKey ? -1 : 1;

        // Do not go out of bounds
        var lastRowInd = jQuery("#grid").jqGrid("getGridParam","reccount")
        if ( iRow+increment == 0 || iRow+increment == lastRowInd+1)
          return;   // we could re-edit current cell or wrap
        else
          jQuery("#grid").jqGrid("editCell",iRow+increment,iCol,true);
      }
    }); // End keydown binding
  })
}); // End jqGrid initialization

I came up with this approach after reading how jqGrid's editCell function deals with tab and enter keys during an edit operation. jqGrid's keydown binding should fire first, followed by this one. This code simply tells it to start an edit in the next row after jqGrid's ENTER handler is processed. It works exactly like tab does now, keeping the edit control open.

I was never able to fully decipher the editoptions: { dataEvents:... } structure, so that might be a better approach. If so, feel free to explain how it is superior.

Bolling answered 9/9, 2011 at 0:20 Comment(1)
When I tried this, the cell save function gets called twice when pressing the enter key in an editable cellAllusion
M
0
{
    type: 'keydown',
    fn: function(e) {
        var key = e.charCode || e.keyCode;
        //TAB
        if(key == jq.ui.keyCode.TAB) {
             setTimeout(function() { 
               jq('#' + currentRowId + '_nextColName').focus();
               jq('#' + currentRowId + '_nextColName').select(); 
             }, 500);
        }
        //ENTER
        else if (key == jq.ui.keyCode.ENTER) {
             var nextRow = parseInt(currentRowId) + 1;
             jq('#' + currentRowId + '_thisColName').blur();
             jq('#' + nextRow + '_firstColName').select();
        }
    }
}
Miosis answered 20/11, 2013 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.