3

Using jqGrid I want to open a cell-editor on double-click, so my code includes this part:

  ondblClickRow: function(rowid, iRow, iCol, e)
  {
    jQuery('#jqGrid').setGridParam({cellEdit: true});
    jQuery('#jqGrid').editCell(iRow, iCol, true);
    jQuery('#jqGrid').setGridParam({cellEdit: false});
  }

which works fine, but I don't know how to (auto-) close the cell-editor, when user click outside of the edit element, or press ESC, TAB, ENTER, etc...

000
  • 26,951
  • 10
  • 71
  • 101
Ωmega
  • 42,614
  • 34
  • 134
  • 203

3 Answers3

4

The problem is that you try to implement cell editing on double-click which is not supported. Your current code don't work because if the user press Tab, Enter or Esc key the nextCell, prevCell, saveCell or restoreCell will be really called, but the methods tests internally whether cellEdit parameter is true.

To show how to fix the problem I created the demo which uses the following code:

cellsubmit: 'clientArray',
ondblClickRow: function (rowid, iRow, iCol) {
    var $this = $(this);

    $this.jqGrid('setGridParam', {cellEdit: true});
    $this.jqGrid('editCell', iRow, iCol, true);
    $this.jqGrid('setGridParam', {cellEdit: false});
},
afterEditCell: function (rowid, cellName, cellValue, iRow) {
    var cellDOM = this.rows[iRow], oldKeydown,
        $cellInput = $('input, select, textarea', cellDOM),
        events = $cellInput.data('events'),
        $this = $(this);
    if (events && events.keydown && events.keydown.length) {
        oldKeydown = events.keydown[0].handler;
        $cellInput.unbind('keydown', oldKeydown);
        $cellInput.bind('keydown', function (e) {
            $this.jqGrid('setGridParam', {cellEdit: true});
            oldKeydown.call(this, e);
            $this.jqGrid('setGridParam', {cellEdit: false});
        });
    }
}

UPDATED: If you want to discard or save the last editing changes if the user click on any other cell one should extend the code with the following:

beforeSelectRow: function (rowid, e) {
    var $this = $(this),
        $td = $(e.target).closest('td'),
        $tr = $td.closest('tr'),
        iRow = $tr[0].rowIndex,
        iCol = $.jgrid.getCellIndex($td);

    if (typeof lastRowIndex !== "undefined" && typeof lastColIndex !== "undefined" &&
            (iRow !== lastRowIndex || iCol !== lastColIndex)) {
        $this.jqGrid('setGridParam', {cellEdit: true});
        $this.jqGrid('restoreCell', lastRowIndex, lastColIndex, true);
        $this.jqGrid('setGridParam', {cellEdit: false});
        $(this.rows[lastRowIndex].cells[lastColIndex])
            .removeClass("ui-state-highlight");
    }
    return true;
}

The new demo shows the results.

UPDATED 2: Alternatively you can use focusout to discard or save the last editing changes. See one more demo which use the code:

ondblClickRow: function (rowid, iRow, iCol) {
    var $this = $(this);

    $this.jqGrid('setGridParam', {cellEdit: true});
    $this.jqGrid('editCell', iRow, iCol, true);
    $this.jqGrid('setGridParam', {cellEdit: false});
},
afterEditCell: function (rowid, cellName, cellValue, iRow, iCol) {
    var cellDOM = this.rows[iRow].cells[iCol], oldKeydown,
        $cellInput = $('input, select, textarea', cellDOM),
        events = $cellInput.data('events'),
        $this = $(this);
    if (events && events.keydown && events.keydown.length) {
        oldKeydown = events.keydown[0].handler;
        $cellInput.unbind('keydown', oldKeydown);
        $cellInput.bind('keydown', function (e) {
            $this.jqGrid('setGridParam', {cellEdit: true});
            oldKeydown.call(this, e);
            $this.jqGrid('setGridParam', {cellEdit: false});
        }).bind('focusout', function (e) {
            $this.jqGrid('setGridParam', {cellEdit: true});
            $this.jqGrid('restoreCell', iRow, iCol, true);
            $this.jqGrid('setGridParam', {cellEdit: false});
            $(cellDOM).removeClass("ui-state-highlight");
        });
    }
}

UPDATED 3: Starting with jQuery 1.8 one should use $._data($cellInput[0], 'events'); instead of $cellInput.data('events') to get the list of all events of $cellInput.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Looks great, but would it be possible also add a functionality when user click outside of active cell or outside ot grid component, that active inline editor close itself? – Ωmega Mar 02 '12 at 01:19
  • @stackoverflow: It's also possible. See the "UPDATED" part of the answer and new demo. – Oleg Mar 02 '12 at 08:10
  • Great progress! But when I click outside of cells or rows (e.g. grid toolbar, grid column title, etc.), or outside of grid, inline editor is still active and does not close. Is it possible to add such functionality as well? Thanks. – Ωmega Mar 02 '12 at 12:28
  • @stackoverflow: Everything is possible: see "UPDATED 2" part of my answer. – Oleg Mar 02 '12 at 12:50
0
// This worked Perfectly fine for me, hope will work for you as well.
var selectedCellId;
    var $gridTableObj = $('#jqGridTable');
    $gridTableObj.jqGrid({
        datatype : "jsonstring",
        datastr : gridJSON,
        height : ($(window).height() - 110),
        width : ($(window).width() - 80),
        gridview : true,
        loadonce : false,
        colNames : columnNames,
        colModel : columnModel,
        rowNum : gridJSON.length,
        viewrecords : true,
        subGrid : false,
        autoheight : true,
        autowidth : false,
        shrinkToFit : true,
        cellsubmit : 'clientArray',
        cellEdit : true,
        jsonReader : {
            root : "rows",
            repeatitems : false
        },
        onCellSelect : function(id, cellidx, cellvalue) { // use this event to capture edited cellID
            selectedCellId = cellidx; // save the cellId to a variable
        },
        loadComplete : function(data) {
            jQuery("tr.jqgrow:odd").addClass("oddRow");
            jQuery("tr.jqgrow:even").addClass("evenRow");
        }
    });

// Attach on click event jqgrid "saveCell" to save the cell.

var gridCellWasClicked = false;
window.parent.document.body.onclick = saveEditedCell; // attach to parent window if any
document.body.onclick = saveEditedCell; // attach to current document.
function saveEditedCell(evt) {
    var target = $(evt.target);
    var isCellClicked = $gridTableObj.find(target).length; // check if click is inside jqgrid
    if(gridCellWasClicked && !isCellClicked) // check if a valid click
        {
        var rowid = $gridTableObj.jqGrid('getGridParam', 'selrow');
    $gridTableObj.jqGrid("saveCell", rowid, selectedCellId);
    gridCellWasClicked = false;
    }
    if(isCellClicked){
        gridCellWasClicked = true; // flat to check if there is a cell been edited.
    }
};
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Arun Pratap Singh
  • 3,428
  • 30
  • 23
0

Declare the common variable:-

  var lastRowId=-1;

   $(document).ready(function() {
          // put all your jQuery goodness in here.
    });
 .
 .
 .
 .

  ondblClickRow: function(rowid, iRow, iCol, e)
   {
      if(lastRowId!=-1)
         $("#jqGrid").saveRow(lastRowId, true, 'clientArray');
      $('#jqGrid').setGridParam({cellEdit: true});
      $('#jqGrid').editCell(iRow, iCol, true);
      lastRowId= rowid;

  }

After you want finish your edit

          $("#jqGrid").saveRow(jqMFPLastRowId, true, 'clientArray');




                    (or)

===========================================================================

Declare the common variable:-

  var lastRowId=-1;
  $(document).ready(function() {
          // put all your jQuery goodness in here.
    });
 .
 .
 .
 .
  ondblClickRow: function (rowid, iRow, iCol) {
        var $this = $(this);
        $this.jqGrid('setGridParam', {cellEdit: true});
        $this.jqGrid('editCell', iRow, iCol, true);
        $this.jqGrid('setGridParam', {cellEdit: false});
        lastRowId=rowid;
   },

  afterEditCell: function (rowid, cellName, cellValue, iRow) {
   if(lastRowId!=-1)
        $("#jqGrid").saveRow(lastRowId, true, 'clientArray');
}
Lawren Alex
  • 110
  • 5