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.

Oleg
  • 220,925
  • 34
  • 403
  • 798
kajo
  • 5,631
  • 4
  • 31
  • 29
  • I included image which I found from your question in the trirand forum (see http://www.trirand.com/blog/?page_id=393/help/excel-like-enter-and-tab-key-navigation-in-cell-editing/#p21574) – Oleg Jan 07 '11 at 20:02

4 Answers4

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);
                }
            }
        } 
    ]
}
kajo
  • 5,631
  • 4
  • 31
  • 29
  • 1
    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. – Oleg Jan 10 '11 at 21:48
  • 1
    Look at the code of jqGrid: https://github.com/tonytomov/jqGrid/blob/master/js/grid.celledit.js#L74 and https://github.com/tonytomov/jqGrid/blob/master/js/grid.celledit.js#L307. 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*/}});` – Oleg Jan 11 '11 at 11:10
  • 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. – kajo Jan 11 '11 at 13:50
  • 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. – kajo Jan 11 '11 at 14:16
  • @kajo: I read your comments just now accidentally, because I don't receive any notification. Please use @Oleg as a prefix (see more information here http://meta.stackexchange.com/questions/43019/how-do-comment-replies-work). 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 this – Oleg Jan 11 '11 at 15:38
  • @Oleg - 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 - http://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. – kajo Jan 18 '11 at 18:11
  • @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. – Oleg Jan 18 '11 at 19:22
  • @Kajo: I have similar question posted in http://stackoverflow.com/questions/6781612/how-to-implement-excel-like-order-detail-edit-can-jqgrid-used . how to use your code to move to next /previous row if inline edit is active? – Andrus Jul 27 '11 at 11:41
  • @kajo 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? – Cocowalla Sep 14 '12 at 15:44
  • @Cocowalla I don't remember, it was while ago. Probably I didn't face this issue. Let me know if you can solve this thing. – kajo Sep 14 '12 at 19:19
  • 1
    You can actually just use "bindKeys" http://www.trirand.com/jqgridwiki/doku.php?id=wiki:methods. It will automatically make the key up and down work like Excel. – devXen Sep 24 '13 at 17:58
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.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
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.

Jarad Bond
  • 21
  • 1
  • 1
    When I tried this, the cell save function gets called *twice* when pressing the enter key in an editable cell – Cocowalla Sep 14 '12 at 14:39
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();
        }
    }
}
Ashish Mehta
  • 7,226
  • 4
  • 25
  • 52