2011-08-10 5 views
12

edytowane 5/14/12: byłem w końcu w stanie wyskoczyć z mojego lenistwa i przygotować to do dzielenia rzeczywistego EXCEL LIKE JQGRID implementation. Wybór komórki może działać dziwnie na jsfiddle w kilku przeglądarkach, ale powinien działać normalnie w twoim pudełku programistycznym. Baw się dobrze!!!!jqGrid: łatwy sposób zaimplementować cofnąć na realizację programu Excel jak jqGrid

Edytowane na 9/13/11: To jest moje pierwsze użycie JQGrid. Używam wersji 4.1.2. Spędziłem kilka tygodni, aby ułożyć program Excel jak siatkę, a największym wyzwaniem było znalezienie odpowiednich informacji o tym, jak używać JQGrid. Moja obecna konfiguracja zawiera wiele aktualizacji ajaxowych i galerii obrazów oraz użycie formatu jqgrid, ale to, co tutaj umieściłem, jest głównym kodem, który pozwala korzystać z JQgrid z stronicowaniem po stronie serwera, jak kopiuj-wklej i demonstracja kilku innych funkcji jqgrid. To jest po prostu mój sposób na zwrot za całą pomoc, którą otrzymałem od tej społeczności.

Dla osób, które właśnie przeskoczyły do ​​JQGrid, wkrótce odkryjesz, że istnieje pewne wyzwanie dla używania Textarea w jqgrid. możesz znaleźć rozwiązania here.

Original post:
Wystarczy dać trochę aktualizacji przed wprowadzeniem na moje pytanie ....

byłem w stanie wymyślić kilka dodatkowych funkcji na jqGrid że używam (po przechodzenie przez wiele forów), w tym: kopiowanie i wklejanie z Excela do jqgrid, edycję komórki przy naciśnięciu klawisza i dblclick, kopiowanie i wklejenie wielu komórek z jednego bloku do drugiego na tej samej siatce przy użyciu myszy (tutaj Using Javascript to 'sum selected cells' in IE6)

Większość funkcji wklejania kopii działa tylko w IE. Wszystkie zmiany zapiszę razem przyciskiem "Zapisz", aby wszystkie aktualizacje komórek były wyświetlane na ekranie tylko do momentu, gdy użytkownik kliknie przycisk "Zapisz".

Mimo że sprawy wciąż się zmieniają, chciałabym mieć projekt wdrożenia na papierze teraz, niż później. Szukam łatwej drogi do UNDO tylko ostatniej zmiany. Myślałem o użyciu metod "data()" i "removeData()" jQuery do wdrożenia tego, ale jeśli jest coś, co już istnieje w frameworku jqgrid, co mogłoby pomóc, chciałbym to wiedzieć. Jakieś sugestie??

<style type="text/css"> 
    .sel {background-color: #96B9DC !important; } 
    .altered {} 
</style> 
<script type="text/javascript"> 
    var enableOnSelectEvent = false; // handle text selection 
</script> 
<div style="width:100%; background-color:#FFF; border:1px solid #000;"><input id="btnsavechanges" value="Save Changes" style="width:120px;" class="formbutton ui-corner-all" type="button" onclick="getChanges(); return false;" /></div> 
<table id="grd_asset" width="100%" onSelectStart="return enableOnSelectEvent;"></table> 
<div id="pfrmac" style='width:100%;'></div> 
<input type="hidden" id="hidSelected" value="" /> 

<!-- copy content from the grid cells --> 
<input type="hidden" id="hidCopiedText" value="" /> 

<!-- Start and End of cell selection --> 
<input type="hidden" id="hidStartCell" value="" /> 
<input type="hidden" id="hidEndCell" value="" /> 

<!-- Start and End of last modified cell(s) --> 
<input type="hidden" id="hidModStartCell" value="" /> 
<input type="hidden" id="hidModEndCell" value="" /> 

<script type="text/javascript"> 
    /*************************************************/ 
    /**************** Grid Utilities ****************/ 
    /*************************************************/ 
    FnGrid = function() { 
     this.GridColumns = function() { 
      return assetGrid.jqGrid('getGridParam', 'colModel'); 
     } 
     this.GetSelCells = function() { 
      return assetGrid.find("td.sel"); 
     } 
     this.ClearSelection = function() { 
      assetGrid.find("td").removeClass("sel"); 
     } 
     this.ClearSavedHistory = function() { 
      assetGrid.removeData(); 
     } 
     this.ClearMarkedChanges = function() { 
      assetGrid.find("tr").removeClass("altered"); 
     } 
     this.GetRowCells = function (cell) { 
      return cell.parent().children("td") 
     } 
     this.GetRowId = function (cell) { 
      var row = cell.closest('tr.jqgrow'); 
      return row.attr('id'); 
     } 
     this.GetRowIndex = function (cell) { 
      var cellrow = cell.parent(); 
      return cellrow.parent().children("tr").index(cellrow); 
     } 
     this.GetColIndex = function (cell) { 
      return cell.parent().children("td").index(cell); 
     } 
     this.IsInEditMode = function() { 
      var savedRows = assetGrid.getGridParam('savedRow'); 
      return (savedRows && savedRows.length > 0); 
     } 
     this.PutCellInEdit = function (cell, irow, icol, edit) { 
      assetGrid.editCell(irow, icol, edit); 
      // transfer focus to the input 
      var inp = $(cell).children("input") 
      if (inp && inp.length > 0) { 
       $(inp[0]).val(''); 
       $(inp[0]).focus(); 
      } 
     } 
     this.HandleEditMode = function (cell, e) { 
      var ctrl = e.ctrlKey; 
      var alt = e.altKey; 

      var keyCode = (e.keyCode ? e.keyCode : e.which); 
      if (keyCode) { 
       if (keyCode >= 32 && keyCode <= 126 && !ctrl && !alt) { 
        // switch the cell to edit mode if not already 
        if (!($(cell).hasClass("edit-cell"))) { 
         this.PutCellInEdit(cell, this.GetRowIndex($(cell)), this.GetColIndex($(cell)), true);      } 
       } 
      } 
      return true; 
     } 
     this.HandleInputNavigation = function (ele, evt) { 
      evt = window.event || evt; 

      switch (evt.keyCode) { 
       // down arrow     
       case 40: 
        if (!$(ele).parent().hasClass("altered")) 
         $(ele).parent().addClass("altered"); 

        irow = this.GetRowIndex($(ele).parent()); 
        icol = this.GetColIndex($(ele).parent()) 
        var prevcell = irow + "," + icol; 
        $("#hidModStartCell").val(prevcell); 
        $("#hidModEndCell").val(prevcell); 

        downele = $(ele).parent() 
          .parent() 
          .next() 
          .children("td")[this.GetColIndex($(ele).parent())]; 

        this.ClearSelection(); 
        assetGrid.editCell(this.GetRowIndex($(downele)), this.GetColIndex($(downele)), true); 
        break; 

       // up arrow     
       case 38: 
        if (!$(ele).parent().hasClass("altered")) 
         $(ele).parent().addClass("altered"); 

        irow = this.GetRowIndex($(ele).parent()); 
        icol = this.GetColIndex($(ele).parent()) 
        var prevcell = irow + "," + icol; 
        $("#hidModStartCell").val(prevcell); 
        $("#hidModEndCell").val(prevcell); 

        topele = $(ele).parent() 
          .parent() 
          .prev() 
          .children("td")[this.GetColIndex($(ele).parent())]; 

        if (this.GetRowIndex($(topele)) <= 0) break; 

        this.ClearSelection(); 
        assetGrid.editCell(this.GetRowIndex($(topele)), this.GetColIndex($(topele)), true); 
        break; 
      } 
     } 
    } 

    var autocomp = new AutoCompleteRequest(); 
    var lastSel = ""; 
    var assetGrid = $('#grd_asset'); 
    var start = null; 
    var fnassetgrid = new FnGrid(); 
    var lastSel = -1; 

    function selectTo(cell) { 
     if (start == null) 
      return; 
     fnassetgrid.ClearSelection(); 
     var stop = $(cell); 
     var tbl = start.closest("table"); 
     var rs = tbl.children("tbody").children("tr"); 
     var r0 = rs.index(start.parent()), c0 = fnassetgrid.GetColIndex(start); 
     var r1 = rs.index(stop.parent()), c1 = fnassetgrid.GetColIndex(stop); 
     var concat = ""; 
     for (var i = r0; i <= r1; i++) { 
      var cells = $(rs.get(i)).children("td"); 
      var rowid = 0; 
      for (var j = c0; j <= c1; j++) { 
       var cell = $(cells.get(j)); 
       if (rowid == 0) rowid = fnassetgrid.GetRowId(cell); 
       if (cell.is(":hidden")) continue; 
       cell.addClass("sel"); 
       concat += assetGrid.getCell(rowid, j) + "\t"; 
      } 
      if (concat.lastIndexOf("\t") == concat.length - 1) 
       concat = concat.substring(0, concat.lastIndexOf("\t")); 

      concat += escape("\r\n"); 
     } 
     $("#hidSelected").val(concat.trim()); 
    } 


    $(document).ready(function() { 
     /*************************************************/ 
     /******************* THE GRID *******************/ 
     /*************************************************/ 
     assetGrid.jqGrid({ 
      ajaxGridOptions: { contentType: "application/json; charset=utf-8", type: "POST" }, 
      url: '../api/yourservices.asmx/GetData', 
      datatype: 'json', 
      serializeGridData: function (postData) { 
       if (postData.searchField === undefined) postData.searchField = null; 
       if (postData.searchString === undefined) postData.searchString = null; 
       if (postData.searchOper === undefined) postData.searchOper = null; 
       if (postData.filters === undefined) postData.filters = null; 
       return JSON.stringify(postData); 
      }, 
      colNames: [' ', 'AssetId', 'Item#', 'Make', 'Description'], 
      colModel: [ 
       { name: 'ctrls', width: 80, fixed: true, sortable: false, resize: false, formatter: 'actions', 
        formatoptions: { keys: true } 
       }, 
       { name: 'AssetID', label: 'AssetID', width: 65, key: true, hidden: true }, 
       { name: 'Sequence', label: 'Item#', width: 50, align: "right", sorttype: 'int', sortable: true, editoptions: { dataEvents: [{ type: 'keydown', fn: function (e) { fnassetgrid.HandleInputNavigation(this, e); } }]} }, 
       { name: 'Make', label: 'Make', width: 105, editable: true, edittype: 'text', editoptions: { 
        size: 18, 
        dataEvents: [{ 
         type: 'focus', 
         fn: function (e) { 
          $(this).autocomplete({ 
           source: autocomp.source, 
           delay: autocomp.delay, 
           minLength: autocomp.minLength 
          }); 

          $(this).bind("autocompleteopen", autocomp.open); 
          $(this).bind("autocompleteclose", autocomp.close); 
         } 
        }] 
       } 
       }, 
       { name: 'Description', label: 'Description', fixed: false, editable: true, edittype: 'textarea', unformat: unfrmttextarea, editoptions: { rows: "10", cols: "40"} } 
      ], 
      rowNum: 10, /* no of recs in a grid */ 
      width: 1330, 
      rowList: [10, 20, 30], /* array to construct a select box element in the pager */ 
      pager: '#pfrmac', 
      sortname: 'AssetID', /* initial sorting column */ 
      viewrecords: true, /* display the number of total records on the pager bar */ 
      pginput: true, 
      sortorder: "desc", 
      cellEdit: true, 
      shrinkToFit: true, 
      jsonReader: { 
       root: function (obj) { return obj.d.SearchResultSet; }, 
       page: function (obj) { return obj.d.PageNum; }, // current page of the query 
       total: function (obj) { return obj.d.TotalPages; }, // total pages for the query 
       records: function (obj) { return obj.d.TotalNoOfSearchResultItems; }, 
       id: "AssetID", 
       repeatitems: false, 
       userdata: function (obj) { 
        extendUserSession(); 
        return { "Error": obj.d.Error, "SearchResultSet": obj.d.SearchResultSet } 
       } 
      }, 
      loadonce: false, 
      caption: "Asset list", 
      height: '100%', 
      cellsubmit: 'clientArray', 
      beforeEditCell: function (rowid, cellname, value, iRow, iCol) { 
       enableOnSelectEvent = true; 
      }, 
      beforeSaveCell: function (rowid, cellname, value, iRow, iCol) { 
       savedrow = assetGrid.getGridParam('savedRow'); 
       if (savedrow && savedrow.length > 0) { 
        if (savedrow[0].id == iRow && savedrow[0].ic == iCol && savedrow[0].v != value) { 
         tr = $('#' + rowid); 
         if (tr && !tr.hasClass("altered")) { 
          tr.addClass("altered"); 
          there_are_unsaved_changes = 1; 
         } 
        } 
       } 
      }, 
      afterSaveCell: function (rowid, cellname, value, iRow, iCol) { 
       enableOnSelectEvent = false; 
      }, 
      afterRestoreCell: function (rowid, value, iRow, iCol) { 
       enableOnSelectEvent = false; 
      }, 
      loadComplete: function (data) { 
       if (assetGrid.getGridParam('userData').Error && assetGrid.getGridParam('userData').Error != '') 
        alert("Error: " + assetGrid.getGridParam('userData').Error); 
      }, 
      gridComplete: function() { 
       rowindex = 1; 
       rows = assetGrid.find("tr"); 

       if (rows && rows.length > 1) { 
        for (i = 1; i < rows.length; i++) { 
         $(rows[i]).find("td").each(function (evt) { 
          evt = window.event || evt; 

          start = $(this); 
          colindex = fnassetgrid.GetColIndex(start); 
          if (colindex > 0) { 
           $(this).click(function() { 
            if (!($(this).hasClass("edit-cell"))) 
             return false; 
           }).dblclick(function() { 
            if (!($(this).hasClass("edit-cell"))) { 
             fnassetgrid.PutCellInEdit(this, fnassetgrid.GetRowIndex($(this)), fnassetgrid.GetColIndex($(this)), true); 
             return; 
            } 
            else 
             return true; 
           }).mousedown(function() { 
            if (fnassetgrid.IsInEditMode()) 
             return true; 
            start = $(this); 
            selectTo(this); 
            return false; 
           }).mouseover(function() { 
            if (fnassetgrid.IsInEditMode()) return true; 
            selectTo(this); 
           }).mouseup(function() { 
            if (fnassetgrid.IsInEditMode()) return true; 
            selectTo(this); 
            $("#hidEndCell").val(fnassetgrid.GetColIndex($(this))); 
            start = null; 
           }).keypress(function (e) { 
            fnassetgrid.HandleEditMode(this, e); 
           }); 
          } 
         }); 
         rowindex++; 
        } 
       } 
      } 
     }); 

     function unfrmttextarea(cellvalue, options, cellobject) { 
      return cellvalue; 
     } 

     $("body").mouseup(function() { 
      start = null; 
     }); 


     /*************************************************/ 
     /*********** Global KEYUP integration ***********/ 
     /*************************************************/ 
     $(assetGrid).keyup(function (e) { 
      var ctrl = e.ctrlKey 
      var key = e.charCode || e.keyCode || 0; 

      if ((ctrl && key == 88) /* CUT */ || (ctrl && key == 67) /* COPY */ || (ctrl && key == 86) /* PASTE */ || (ctrl && key == 90) /* UNDO */) { 

       if ((ctrl && key == 88) /* CUT */ || (ctrl && key == 67) /* COPY */) { 
        if (fnassetgrid.IsInEditMode()) return true; 
        CopyToClipboard("hidSelected"); 

        var selectedCells = fnassetgrid.GetSelCells(); 

        if (selectedCells && selectedCells.length > 0) { 
         $("#hidStartCell").val(fnassetgrid.GetRowIndex($(selectedCells[0])) + "," + fnassetgrid.GetColIndex($(selectedCells[0]))); 
         $("#hidEndCell").val(fnassetgrid.GetRowIndex($(selectedCells[selectedCells.length - 1])) + "," + fnassetgrid.GetColIndex($(selectedCells[selectedCells.length - 1]))); 
         $("#hidCopiedText").val($("#hidSelected").val()); 
        } 
        else { 
         $("#hidStartCell").val(''); 
         $("#hidEndCell").val(''); 
        } 

        if (ctrl && key == 88) /* CUT */{ 
         assetGrid.find("td.sel").each(function() { 
          row = $(this).closest('tr.jqgrow'); 
          rowId = row.attr('id'); 
          assetGrid.setCell(rowId, (fnassetgrid.GridColumns())[fnassetgrid.GetColIndex($(this))].name, '', '', '', true); 
         }); 
         fnassetgrid.ClearSelection(); 
        } 
       } 
       else if (ctrl && key == 86) /* PASTE */{ 
        var clipboardata = getClipboardData(); 
        if (get_objtype(clipboardata) != "[object String]") { 
         alert("The data you are pasting either is empty or incompatible"); 
         return false; 
        } 

        pasteinfo(assetGrid, clipboardata); 
       } 
       else if ((ctrl && key == 90) /* UNDO */) { 
       // TBD : No jqgrid features available to get the help 
       } 
       return false; // prevent bubbling 
      } 
      else 
       return true; // let it bubble 
     }); 
    }); 


    /********************************************************************/ 
    /*********** Method to retrieve and submit altered asset information ***********/ 
    /********************************************************************/ 
    function getChanges() { 
     var editedxml = "<?xml version='1.0' encoding='utf-8' ?\>\n"; 
     editedxml += "<ASSETS>\n"; 
     assetGrid.find("tr.altered").each(function() { 
      editedxml += "<ASSET>\n"; 
      $(this).children("td").each(function() { 
       colindex = fnassetgrid.GetColIndex($(this));      
       if (colindex > 0) { 
        editedxml += "<" + (fnassetgrid.GridColumns())[colindex].name.toUpperCase() + ">" + $(this).text().trim() + "</" + (fnassetgrid.GridColumns())[colindex].name.toUpperCase() + ">\n"; 
       } 
      }) 
      editedxml += "</ASSET>\n"; 
     }) 
     editedxml += "</ASSETS>"; 

     fnassetgrid.ClearMarkedChanges(); 

     //TBD: submit XML to an AJAX service 
    } 


    var _browserPasteData = null; 
    function getClipboardData() { 
     if (_browserPasteData) // Safari/Chrome logic 
      return _browserPasteData; 
     if (window.clipboardData) // IE logic 
     { 
      return window.clipboardData.getData("Text"); 
     } 
     else if (typeof (netscape) != "undefined") // Firefox logic 
     { 
      netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); 
      var clip = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard); 
      var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable); 
      trans.addDataFlavor("text/unicode"); 
      clip.getData(trans, clip.kGlobalClipboard); 
      var str = new Object(); 
      var len = new Object(); 
      trans.getTransferData("text/unicode", str, len); 
      if (str) 
       return str.value.QueryInterface(Components.interfaces.nsISupportsString).toString(); 
     } 
     return null; 
    } 
    // In Safari/Chrome the clipboard data can only be accessed 
    // from the onpaste event. In this sample the event is handled 
    // off the body element: <body onpaste="browserPaste(event)"> 
    function browserPaste(e) { 
     _browserPasteData = e.clipboardData && e.clipboardData.getData ? 
      e.clipboardData.getData('text/plain') : null; 
    } 

    function pasteinfo(objGrid, info) { 
     selectedCells = fnassetgrid.GetSelCells(); 
     firstcell = $(selectedCells[0]); 
     firstselectedcolindex = fnassetgrid.GetColIndex(firstcell); 
     rowcellscount = fnassetgrid.GetRowCells(firstcell).length; 

     if (firstselectedcolindex == 0) { 
      alert("You cannot paste into an non-editable column"); 
      return false; 
     } 

     if (selectedCells && selectedCells.length > 0) { 
      // if the clipboard info is from the asset grid 
      if (info && info == $("#hidCopiedText").val()) { 
       // get the index values of last copied source cell 
       hidStartCell = -1; 
       if ($("#hidStartCell").val() != '' && $("#hidStartCell").val().split(',').length > 1) { 
        hidStartCell = $("#hidStartCell").val().split(',')[1]; 
       } 

       // if columns of source and dest do not match, throw warning 
       if (firstselectedcolindex != hidStartCell) { 
        if (!confirm("The data you are pasting comes from a different set of \ncolumns than those that you are pasting into.\n\nAre you sure you want to paste into these columns?")) 
         return false; 
       } 
      } 

      $("#hidModStartCell").val(fnassetgrid.GetRowIndex(firstcell) + "," + firstselectedcolindex); 

      var prevcell = null; 
      // remove the last "line break" and break clipboard info into lines 
      datarows = unescape(info).replace(/\r\n$/, '').split("\r\n"); 
      if (datarows && datarows.length > 0) { 
       currentrow = firstcell.parent(); 
       currentcell = firstcell; 

       // if the source is a single cell, allow it to be pasted over multiple cells 
       if (datarows.length == 1 && datarows[0].split("\t").length == 1) { 
        copydata = datarows[0].split("\t"); 

        $.each(selectedCells, function (index, value) { 
         prevcell = $(value); 
         if (!prevcell.parent().hasClass("altered")) { 
          prevcell.parent().addClass("altered"); 
          there_are_unsaved_changes = 1; 
         } 
         var rowId = prevcell.closest('tr.jqgrow').attr('id'); 
         var icol = fnassetgrid.GetColIndex(prevcell); 
         assetGrid.setCell(rowId, (fnassetgrid.GridColumns())[icol].name, copydata[0], '', '', true); 
        }); 
       } 
       else { 
        for (i = 0; i < datarows.length && currentrow.length > 0; ++i) { 
         if (datarows[i] == '') break; 
         // break each lines into columns 
         datarows[i] = datarows[i].split("\t"); 
         var row = null; 
         var rowId = null; 
         var rowindex = null; 
         for (j = 0; j < datarows[i].length && currentcell.length > 0; ++j) { 
          // mark the row as altered 
          if (!currentcell.parent().hasClass("altered")) { 
           currentcell.parent().addClass("altered"); 
           there_are_unsaved_changes = 1; 
          } 
          // for each outer iteration get the rowid 
          if (row == null) { 
           row = (currentcell).closest('tr.jqgrow'); 
           rowId = row.attr('id'); 
          } 
          var icol = fnassetgrid.GetColIndex(currentcell); 
          assetGrid.setCell(rowId, (fnassetgrid.GridColumns())[icol].name, datarows[i][j], '', '', true); 
          prevcell = currentcell; 

          // advance to the next visible cell -- only consider pasting into visible columns 
          do { 
           currentcell = currentcell.next(); 
          } 
          while ((currentcell.length > 0) && currentcell.is(":hidden")) 
         } 

         currentrow = currentrow.next(); 
         currentcell = $(currentrow.children("td")[firstselectedcolindex]); 
        } 
       } 
      } 
     } 

     if (prevcell.length > 0) 
      $("#hidModEndCell").val(fnassetgrid.GetRowIndex(prevcell) + "," + fnassetgrid.GetColIndex(prevcell)); 
    } 

</script> 

Wielkie dzięki z góry!

+0

Edytowane w dniu 12/7: Naprawiono problemy z wyborem tekstu w trybie edycji komórki. Musiałem ręcznie selektywnie aktualizować części kodu ... mam nadzieję, że omawiałem wszystkie poprawki tego problemu. – justcurious

+0

Brak wszystkich plików na stronie jsfiddle. Czy możesz przesłać je, abyśmy mogli zagrać w prezentowaną wersję demo? –

Odpowiedz

1

Zamiast implementacji specyficznej dla jqgrid, jednym ze sposobów podejścia do tego byłoby posiadanie wtórnej instancji jqgrid, która nie jest związana z żadnym widocznym elementem html.

W przypadku każdej operacji sklasyfikowanej jako zatwierdzenie, wystąpienie drugorzędne jest ustawione jako bieżące (niezmienione) jqgrid, a wystąpienie podstawowe (to jest to, które faktycznie zostało wyświetlone) jest duplikatem elementu wtórnego z wymaganą zmianą.

Wtedy wszystko, co będzie potrzebne do operacji cofania, to skopiowanie wtórnej instancji z powrotem do pierwotnie wyświetlanej, nie wymagając żadnej wiedzy o konkretnej akcji zatwierdzenia.

Można również łatwo rozszerzyć do wielu operacji cofania. Może być jednak świstem zasobów.

+0

Dzięki. Na razie wolałbym raczej przechowywać tylko ostatnią zmianę w jakimś obiekcie DOM. Jeśli miałbym wdrożyć wiele cofnięć, mógłbym mieć problemy z Twoją sugestią, jeśli dokonano wielu zmian w tej samej komórce. – justcurious

2

Jedną z możliwości jest przechowywanie ostatnią wartość jako atrybut komórki, które mogą być wykonywane przy użyciu następujących

$('#' + rowid + ' > td:eq(' + colIndex + ')').attr('lastval', valueToSave); 

gdzie rowid jest hałas podczas pracy na i colIndex to numer kolumny ty chcesz zapisać wartość w. Stworzy to atrybut o nazwie lastval, który może być użyty z twoją funkcją cofania. Wadą tego podejścia jest to, że cała siatka zostanie zaktualizowana po odświeżeniu i utracisz atrybuty przechowywane w siatce.

Zakładając, że jest to dopuszczalne, a następnie można zapisać ostatnią wartość każdej komórce za pomocą

loadComplete: function() { 
    $("#list").find("td").each(function(index, elem) { 
     $(elem).attr('lastval', $(elem).html()); 
    }); 
}, 

gdzie „lista” jest id początkowo utworzonego jqGrid.

Możesz zaktualizować lastval jako część beforeSubmit lub inne wywołanie zwrotne w zależności od tego, jak chcesz zachować ostatnią.

Jestem pewien, że istnieją bardziej wydajne techniki wykonywania powyższych czynności, ale z utratą wartości podczas odświeżania, nie jestem pewien, czy to naprawdę pomoże w tym, co próbujesz zrobić. Lepszym rozwiązaniem byłoby przechowywanie tych atrybutów w dowolnym miejscu w DOM lub na serwerze. Jednakże, jeśli poprawnie czytam powyższe komentarze, chcesz zachować ostatnią wartość w samej siatce.

+0

Masz rację zakładając, że chcę zapisać ostatnią wartość lokalnie na stronie. Mam javascript ostrzegający użytkowników, jeśli spróbują odejść (włączając odświeżenie) ze strony, gdy mają niezapisane zmiany w siatce, więc nie będę się martwić, że stracę tak dużo.
Twoja sugestia brzmi dla mnie dobrze, z tym, że nie mam okazji jej wypróbować, ponieważ pracuję w innym projekcie. Ten projekt jest już w produkcji bez operacji cofania. Zamierzam spróbować twojej sugg. w następnej nadchodzącej fazie 2. – justcurious