JQGRID:任何简单的方法来实现对excel的撤消,如jqGrid实现 [英] JQGRID: any easy way to implement undo on excel like jqGrid implementation

查看:183
本文介绍了JQGRID:任何简单的方法来实现对excel的撤消,如jqGrid实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑于5/14/12:
i终于可以跳出我的懒惰,准备分享实际的 EXCEL LIKE JQGRID实现。单元格选择可能在几个浏览器上的jsfiddle上可能很奇怪,但是它在开发框中应该正常运行。有乐趣!!!!



9/13/11编辑:
这是我第一次使用JQGrid。我使用ver 4.1.2。我花了几个星期把excel和grid一起放在一起,最大的挑战是找到关于如何使用JQGrid的正确信息。我目前的设置有很多ajax更新和图像画廊和使用jqgrid格式化程序,但我在这里放置的主要代码是能够使用JQgrid与服务器端分页,excel像复制粘贴和其他几个功能的演示jqGrid的。这只是我给予我从这个社区获得的所有帮助的方式。



对于刚刚跳到JQGrid的用户,很快就会发现在jqgrid中使用Textarea有一些挑战。你可以找到一些解决方案 here



/ strong>

只是给我一些更新之前,我的问题....



我已经能够提出一些额外的功能在我使用的jqgrid(经过许多论坛之后),包括:从Excel复制粘贴到jqgrid,在按键和dblclick上编辑单元格,将多个单元格从一个块复制并粘贴到同一个网格上的另一个单元格上鼠标选择(从这里使用Javascript在IE6中选择的单元格 / a>)



大多数复制粘贴功能仅在IE上起作用。我保存所有更改在保存按钮单击,所以单元格上的所有更新都在屏幕上,直到用户点击保存按钮。



虽然,事情现在还在流氓,我现在想在纸上实现设计。我正在寻找一个简单的方式来UNDO只有最后的变化。我一直在想使用jQuery的data()和removeData()方法来实现这一点,但是如果jqgrid框架中已经有任何帮助,我想知道。任何建议?

 < style type =text / css> 
.sel {background-color:#96B9DC!important; }
.altered {}
< / style>
< script type =text / javascript>
var enableOnSelectEvent = false; //处理文本选择
< / script>
< div style =width:100%; background-color:#FFF; border:1px solid#000;>< input id =btnsavechangesvalue =保存更改style =width :120像素; class =formbutton ui-corner-alltype =buttononclick =getChanges(); return false; />< / DIV>
< table id =grd_assetwidth =100%onSelectStart =return enableOnSelectEvent;>< / table>
< div id =pfrmacstyle ='width:100%;'>< / div>
< input type =hiddenid =hidSelectedvalue =/>

<! - 从网格单元复制内容 - >
< input type =hiddenid =hidCopiedTextvalue =/>

<! - 单元格选择的开始和结束 - >
< input type =hiddenid =hidStartCellvalue =/>
< input type =hiddenid =hidEndCellvalue =/>

<! - 最后修改的单元格的开始和结束 - >
< input type =hiddenid =hidModStartCellvalue =/>
< input type =hiddenid =hidModEndCellvalue =/>

< script type =text / javascript>
/ ************************************************* **** /
/ ****************网格工具**************** /
/ ******************* /
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(changed);
}
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);
//将焦点转移到输入
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单元格编辑模式如果还没有
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){
//向下箭头
案例40:
if(!$(ele).parent()。hasClass(changed ))
$(ele).parent()。addClass(changed);

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(changed))
$(ele) .parent()addClass( 改变的)。

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;

函数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 =; (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))继续;
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\\\
);
}
$(#hidSelected)。val(concat.trim());
}


$(document).ready(function(){
/ ***************** ******************************** /
/ ************ ******* THE GRID ******************* /
/ **************** ******************************* /
assetGrid.jqGrid({
ajaxGridOptions:{ contentType:application / json; charset = utf-8,键入: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;
返回JSON.stringify( postData);
},
colName s:['','AssetId','Item#','Make','Description'],
colModel:[
{name:'ctrls',width:80,fixed: 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);
}
}]
}
},
{名称:'描述',标签:'描述',固定:false,可编辑:真,编辑类型: textarea',unformat:unfrmttextarea,editoptions:{rows:10,cols:40}}
],
rowNum:10,/ *网格中的recs * /
width:1330,
rowList:[10,20,30],/ *数组在寻呼机中构造一个选择框元素* /
pager:'#pfrmac',
sortname: 'AssetID',/ *初始排序列* /
viewrecords:true,/ *显示寻呼机栏上的总记录数* /
pginput:true,
sortorder:desc ,
cellEdit:true,
shrinkToFit:true,
jsonReader:{
root:function(obj){return obj.d.SearchResultSet; },
page:function(obj){return obj.d.PageNum; },//查询的当前页面
total:function(obj){return obj.d.TotalPages; },//查询的总页面
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 :资产列表,
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&& saverow [0] .ic == iCol&& ; savedrow [0] .v!= value){
tr = $('#'+ rowid);
if(tr&!tr.hasClass(changed)){
tr.addClass(changed);
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')。 ')
alert(Error:+ assetGrid.getGridParam('userData')。
},
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) ()($(this).hasClass(edit-cell))
))){
fnassetgrid.PutCellInEdit(this,fnassetgrid.GetRowIndex($(this)),fnassetgrid.GetColIndex($(this)),true);
re转;
}
else
return true;
})。mousedown(function(){
if(fnassetgrid.IsInEditMode())
return true;
start = $(this);
selectTo );
返回false;
})。mouseover(function(){
if(fnassetgrid.IsInEditMode())返回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 ++;
}
}
}
});

函数unfrmttextarea(cellvalue,options,cellobject){
return cellvalue;
}

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


/ ***************************************** ************ /
/ ***********全局KEYUP集成*********** /
/ * ************************************************ /
$(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())返回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(您粘贴的数据是空的或不兼容的);
返回false;
}

pasteinfo(assetGrid,clipboardata);
}
else if((ctrl&& key == 90)/ * UNDO * /){
// TBD:没有jqgrid功能可以获得帮助
}
return false; //防止冒泡
}
else
返回true; //让它泡泡
});
});


/ ***************************************** ******************************* /
/ ***********方法检索和提交变更的资产信息*********** /
/ *************************** *************************************** /
函数getChanges() {
var editedxml =<?xml version ='1.0'encoding ='utf-8'?\> \\\
;
editedxml + =< ASSETS> \\\
;
assetGrid.find(tr.altered)。each(function(){
editedxml + =< ASSET> \\\
;
$(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()+> \\\
;
}
})
editedxml + =< / ASSET> \\\
;
} )
editedxml + =< / ASSETS>;

fnassetgrid.ClearMarkedChanges();

// TBD:将XML提交给AJAX服务
}


var _browserPasteData = null;
函数getClipboardData(){
if(_browserPasteData)// Safari / Chrome logic
return _browserPasteData;
if(window.clipboardData)// IE logic
{
return window.clipboardData.getData(Text);
}
else if(typeof(netscape)!=undefined)// Firefox逻辑
{
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)
返回str.value.QueryInterface(Components.interfaces.nsISupportsString).toString();
}
返回null;
}
//在Safari / Chrome中,剪贴板数据只能从onpaste事件访问
//。在这个例子中,事件处理
//关闭body元素:< body onpaste =browserPaste(event)>
function browserPaste(e){
_browserPasteData = e.clipboardData&& e.clipboardData.getData?
e.clipboardData.getData('text / plain'):null;
}

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

if(firstselectedcolindex == 0){
alert(你不能粘贴到不可编辑的列);
返回false;
}

if(selectedCells&& selectedCells.length> 0){
//如果剪贴板信息来自资产网格
if(info && info == $(#hidCopiedText)。val()){
//获取上次复制的源单元格的$ index
hidStartCell = -1;
if($(#hidStartCell)。val()!=''&& $(#hidStartCell)val()。split(',')。length> 1){
hidStartCell = $(#hidStartCell)。val()。split(',')[1];
}

//如果source和dest的列不匹配,则抛出警告
if(firstselectedcolindex!= hidStartCell){
if(!confirm(您粘贴的数据来自不同于您粘贴的数据集。\\\
\\\
您确定要粘贴到这些列中吗?))
return false;
}
}

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

var prevcell = null;
//删除最后一个换行符并将剪贴板信息分解为行
datarows = unescape(info).replace(/ \r\\\
$ /,'').split(\\ \\r\\\
);
if(datarows&& datarows.length> 0){
currentrow = firstcell.parent();
currentcell = firstcell;

//如果源是单个单元格,则允许它通过多个单元格粘贴
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(changed ){
prevcell.parent()。addClass(changed);
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;
//将每一行分成列
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){
//将行标记为已更改
if(!currentcell.parent()。hasClass(changed)){
currentcell.parent()。addClass(changed);
there_are_unsaved_changes = 1;
}
//为每个外部迭代获取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;

//提前到下一个可见单元格 - 只考虑粘贴到可视列中
do {
currentcell = currentcell.next();
}
while((currentcell.length> 0)&& currentcell.is(:hidden))
}

currentrow = currentrow。下一个();
currentcell = $(currentrow.children(td)[firstselectedcolindex]);
}
}
}
}

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

< / script>

提前谢谢!

解决方案

一种可能性是将最后一个值作为可以使用以下

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

其中rowid是您正在处理的行,colIndex是要保存的列的编号的值。这将创建一个名为lastval的属性,可以与您的undo功能一起使用。这种方法的缺点是,整个网格将在刷新时更新,并且您将丢失网格中存储的属性。



假设这是可以接受的,那么你可以使用

  loadComplete:function(){
$(#list)保存每个单元格的最后一个值.find(td)。each(function(index,elem){
$(elem).attr('lastval',$(elem).html());
});
},

其中'list'是您最初创建的jqGrid的ID。 / p>

您可以根据您希望维持最后一次的方式更新lastval作为beforeSubmit或其他回调的一部分。



我确定有更有效的技巧来做上面的工作,但随着刷新时间的丢失,我不知道这将真正帮助你想要做的。 A better approach would be to store these attributes elsewhere in the DOM or back on the server. However, if I’m reading the above comments correctly, you want to keep the lastval in the grid itself.


Edited on 5/14/12: i was finally able to jump out of my laziness and prepare this to share the actual EXCEL LIKE JQGRID implementation. The cell selection may work weird on jsfiddle on few browsers but it should work normal on your development box. Have fun!!!!

Edited on 9/13/11: This is my first use of JQGrid. I'm using ver 4.1.2. I spent few weeks to put together the excel like grid and the biggest challenge was to find the right information on how to use JQGrid. My current setup has lots of ajax updates and image galleries and use of jqgrid formatter but what I've put here is the main code to be able to use JQgrid with server side paging, excel like copy-paste and demonstration of few other features on jqgrid. This is just my way of giving back for all the help that I got from this community.

For people who just jumped to JQGrid, you will soon find out that there is some challenge to using Textarea in jqgrid. you can find some solutions here.

Original post:
Just to give little update before putting my question....

I've been able to come up with some additional features on the jqgrid that I'm using (after going through many forums) including: copy-paste back and forth from Excel to jqgrid, edit cell on keypress and dblclick, copy and paste multiple cells from one block to another on the same grid using mouse selection (from here Using Javascript to 'sum selected cells' in IE6)

Most of the copy paste features works on IE only as of now. I save all the changes together on "Save" button click so all the updates on the cells are on screen only until user hits the "Save" button.

Although, things are still in flux right now, I'd like to have the implementation design on paper now than later. I'm looking for an easy way to UNDO only the LAST change. I've been thinking of using jQuery's "data()" and "removeData()" methods to implement this but if there is anything already existing in jqgrid framework that would help, I would like to know. Any suggestions??

<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>

Many Thanks in advance!

解决方案

One possibility is to store the last value as an attribute of the cell which can be done using the following

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

where rowid is the row you are working on and colIndex is the number of the column you wish to save the value in. This will create an attribute called lastval that can be used with your undo function. The drawback of this approach is that the entire grid will be updated on a refresh and you will lose the attributes stored within the grid.

Assuming that this is acceptable, then you can save the last value of every cell using

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

where 'list' is the id of the jqGrid you initially created.

You can update the lastval as part of a beforeSubmit or other callback depending on how you want to maintain the lastval.

I'm sure there are more efficient techniques for doing the above, but with the values getting lost during refresh, I'm not sure this will really help with what you're trying to do. A better approach would be to store these attributes elsewhere in the DOM or back on the server. However, if I'm reading the above comments correctly, you want to keep the lastval in the grid itself.

这篇关于JQGRID:任何简单的方法来实现对excel的撤消,如jqGrid实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆