完善表格编辑功能:添加CTRL、SHIFT+按键选择功能,表格编辑面板可拖拽,ESC关闭编辑面板、ENTER打开编辑面板,编辑面板输入框自动焦点

This commit is contained in:
datagear 2018-12-14 11:22:55 +08:00
parent 99e04b9474
commit 1c9b12fd3c
6 changed files with 241 additions and 122 deletions

View File

@ -14,8 +14,8 @@
<input id="${pageId}-editGridSwitch" type="checkbox" value="1" />
</div>
<div class="edit-grid-operation">
<button type="button" class="button-cancel highlight" style="display: none;"><fmt:message key='cancel' /></button>
<button type="button" class="button-cancel-all highlight" style="display: none;"><fmt:message key='cancelAll' /></button>
<button type="button" class="button-restore highlight" style="display: none;"><fmt:message key='restore' /></button>
<button type="button" class="button-restore-all highlight" style="display: none;"><fmt:message key='restoreAll' /></button>
<button type="button" class="button-save recommended" style="display: none;"><fmt:message key='save' /></button>
</div>
</div>
@ -23,7 +23,10 @@
String editGridFormPageId_html = WebUtils.generatePageId();
request.setAttribute("editGridFormPageId", editGridFormPageId_html);
%>
<div id="<%=editGridFormPageId_html%>" class="edit-cell-form-panel ui-widget ui-widget-content ui-corner-all ui-widget-shadow">
<form id="<%=editGridFormPageId_html%>-form" method="POST" action="#">
</form>
<div id="<%=editGridFormPageId_html%>" class="page-edit-grid-form">
<div class="form-panel ui-widget ui-widget-content ui-corner-all ui-widget-shadow" tabindex="1">
<div class="form-panel-title ui-corner-all ui-widget-header"></div>
<form id="<%=editGridFormPageId_html%>-form" method="POST" action="#">
</form>
</div>
</div>

View File

@ -27,6 +27,7 @@ WebUtils.setPageId(request, editGridFormPageId);
<script type="text/javascript">
(function(po)
{
po.element().draggable({ handle : po.element(".form-panel-title") });
po.element().hide();
po.formLabels.submit = "<fmt:message key='confirm' />";
})
@ -45,8 +46,6 @@ WebUtils.setPageId(request, gridPageId);
po.editGridFormPage = <%=editGridFormPageId%>;
po.currentEditCell = undefined;
po.editGridSwitch = function()
{
return po.element("#${pageId}-editGridSwitch");
@ -105,10 +104,9 @@ WebUtils.setPageId(request, gridPageId);
po.disableEditGrid = function()
{
po.isEnableEditGrid = false;
po.cancelAllEditCell();
var dataTable = po.table().DataTable();
dataTable.cells(".selected").deselect();
$(dataTable.table().node()).removeAttr("tabindex");
var $headOperation = po.element(".head .operation");
@ -124,6 +122,8 @@ WebUtils.setPageId(request, gridPageId);
if(po.isEnableEditGrid)
$(this).hide();
});
po.isEnableEditGrid = false;
};
po.markAsModifiedCell = function($cell)
@ -144,95 +144,82 @@ WebUtils.setPageId(request, gridPageId);
$cmt.remove();
};
po.beginEditCell = function($cell)
//打开编辑面板
po.openEditCellPanel = function(table, indexes)
{
if($cell.is(po.currentEditCell))
return;
else if(po.currentEditCell != null)
po.cancelEditCell(po.currentEditCell);
var settings = table.settings();
po.currentEditCell = $cell;
var $cellNodes = $(table.cells(indexes).nodes());
var $editFormCell = $($cellNodes[0]);
var propertyIndexes = $.getDataTablesColumnPropertyIndexes(settings, indexes);
$cell.addClass("edit-cell ui-state-highlight");
$cellNodes.removeClass("cell-edit-form");
$editFormCell.addClass("cell-edit-form");
var text = $cell.text();
var originalText = $cell.attr("original-text");
var $formPage = po.editGridFormPage.element();
if(originalText == undefined)
{
$cell.attr("original-text", text);
originalText = text;
}
if(!$formPage.parent().is(po.element(".foot")))
po.editGridFormPage.form().modelform("destroy");
if(text != originalText)
po.markAsModifiedCell($cell);
$formPage.appendTo($editFormCell).show();
var form = po.editGridFormPage.form();
//只有一个属性,隐藏标签,否则,显示标签
if(propertyIndexes.length == 1)
form.addClass("hide-form-label");
else
po.markAsUnmodifiedCell($cell);
form.removeClass("hide-form-label");
var cellIndex = $cell.index();
var settings = po.table().DataTable().settings();
var cellProperty = $.getDataTablesColumnProperty(po.editGridModel, settings, cellIndex);
po.editGridFormPage.element().appendTo($cell).show().position({my: "left top", at: "left bottom"});
po.editGridFormPage.form().modelform(
form.modelform(
{
model : po.editGridModel,
renderProperty : function(property)
renderProperty : function(property, propertyIndex)
{
return property == cellProperty;
return ($.inArray(propertyIndex, propertyIndexes) >= 0);
},
submit : function()
{
alert("save cell");
console.log("save cells");
var table = po.table().DataTable();
po.closeEditCellPanel(table);
return false;
},
labels : po.editGridFormPage.formLabels
});
//仅选中一个单元格,激活焦点
if(indexes.length == 1)
$(":input:not([readonly]):visible:eq(0)", form).focus();
};
po.storeEditCell = function($cell, value)
//关闭编辑面板
po.closeEditCellPanel = function(table, deselectCellIndexes)
{
po.cancelEditCell($cell, value);
};
po.cancelEditCell = function($cell, newText)
{
$cell.removeClass("edit-cell ui-state-highlight");
if(deselectCellIndexes)
$(table.cells(deselectCellIndexes).nodes()).removeClass("cell-edit-form");
var originalText = $cell.attr("original-text");
var text = newText;
var $formPage = po.editGridFormPage.element();
if(text == undefined)
text = originalText;
if(text != originalText)
po.markAsModifiedCell($cell);
else
po.markAsUnmodifiedCell($cell);
po.currentEditCell = null;
var editGridFormPageEle = po.editGridFormPage.element();
if(editGridFormPageEle.parent().is($cell))
var $foot = po.element(".foot");
if(!$formPage.parent().is($foot))
{
$formPage.hide();
po.editGridFormPage.form().modelform("destroy");
editGridFormPageEle.hide();
editGridFormPageEle.appendTo(po.element());
$formPage.appendTo($foot);
}
$(table.table().node()).focus();
};
po.cancelAllEditCell = function($editedCells)
//恢复单元格的数据
po.restoreEditCell = function(table, $cells)
{
if(!$editedCells)
$editedCells = po.editedCells();
$editedCells.each(function()
{
po.cancelEditCell($(this));
});
};
po.initEditGrid = function(model)
@ -262,7 +249,6 @@ WebUtils.setPageId(request, gridPageId);
{
"confirm" : function()
{
po.cancelAllEditCell($editedCells);
po.disableEditGrid();
$thisCheckbox.attr("checked", false);
@ -275,34 +261,68 @@ WebUtils.setPageId(request, gridPageId);
}
else
{
po.cancelAllEditCell($editedCells);
po.disableEditGrid();
}
}
});
po.element(".button-cancel", po.element(".edit-grid")).click(function()
po.element(".button-restore", po.element(".edit-grid")).click(function()
{
if(po.currentEditCell != null)
po.cancelAllEditCell(po.currentEditCell);
var table = po.table().DataTable();
var selectedCells = table.cells(".selected");
po.restoreEditCell(table, selectedCells);
});
po.element(".button-cancel-all", po.element(".edit-grid")).click(function()
po.element(".button-restore-all", po.element(".edit-grid")).click(function()
{
var $editedCells = po.editedCells();
var table = po.table().DataTable();
if($editedCells.length > 1)
var modifiedCells = table.cells(".modified-cell");
var count = modifiedCells.nodes().length;
if(count > 1)
{
po.confirm("<fmt:message key='data.confirmCancelAllEditedCell'><fmt:param>"+$editedCells.length+"</fmt:param></fmt:message>",
po.confirm("<fmt:message key='data.confirmCancelAllEditedCell'><fmt:param>"+count+"</fmt:param></fmt:message>",
{
"confirm" : function()
{
po.cancelAllEditCell($editedCells);
po.restoreEditCell(table, modifiedCells);
}
});
}
else
po.cancelAllEditCell($editedCells);
po.restoreEditCell(table, modifiedCells);
});
po.editGridFormPage.element()
.focusin(function()
{
var $this = $(this);
$this.addClass("focus");
})
.focusout(function()
{
var $this = $(this);
$this.removeClass("focus");
});
po.editGridFormPage.element(".form-panel")
.keydown(function(event)
{
if(event.keyCode == $.ui.keyCode.ESCAPE)
{
var table = po.table().DataTable();
po.closeEditCellPanel(table);
}
//禁止冒泡,因为这些快捷键在表格上有特殊处理逻辑
if(event.keyCode == $.ui.keyCode.ESCAPE || event.keyCode == $.ui.keyCode.ENTER
|| event.keyCode == $.ui.keyCode.DOWN || event.keyCode == $.ui.keyCode.UP
|| event.keyCode == $.ui.keyCode.LEFT|| event.keyCode == $.ui.keyCode.RIGHT)
{
event.stopPropagation();
}
});
po.table().DataTable()
@ -310,6 +330,7 @@ WebUtils.setPageId(request, gridPageId);
{
if(po.isEnableEditGrid)
{
//阻止冒泡的行选择事件
event.stopPropagation();
var target = $(event.target);
@ -329,7 +350,21 @@ WebUtils.setPageId(request, gridPageId);
{
var table = $(this).DataTable();
$.handleCellNavigationForKeydown(table, event);
if(event.keyCode == $.ui.keyCode.ESCAPE)
{
po.closeEditCellPanel(table);
}
else if(event.keyCode == $.ui.keyCode.ENTER)
{
event.preventDefault();
var selectedIndexes = table.cells(".selected").indexes();
if(selectedIndexes)
po.openEditCellPanel(table, selectedIndexes);
}
else
$.handleCellNavigationForKeydown(table, event);
}
})
.on("select", function(event, dataTable, type, indexes)
@ -338,15 +373,13 @@ WebUtils.setPageId(request, gridPageId);
{
if(type == "cell")
{
var $cells = $(dataTable.cells(indexes).nodes());
po.openEditCellPanel(dataTable, indexes);
}
else if(type == "row")
{
dataTable.cells(".selected").deselect();
}
}
console.log("select");
})
.on("deselect", function(event, dataTable, type, indexes)
{
@ -354,11 +387,12 @@ WebUtils.setPageId(request, gridPageId);
{
if(type == "cell")
{
var $cells = $(dataTable.cells(indexes).nodes());
var $selectedCells = dataTable.cells(".selected").nodes();
if($selectedCells.length == 0)
po.closeEditCellPanel(dataTable, indexes);
}
}
console.log("deselect");
})
.on("preDraw", function(event, settings)
{

View File

@ -855,24 +855,41 @@
},
/**
* 获取指定名称的Property对象
*
* @param model
* @param propName
* 获取属性索引
*/
getProperty : function(model, propName)
getPropertyIndex : function(model, propertyName)
{
var properties=model.properties;
for(var i=0; i<properties.length; i++)
{
var property=properties[i];
if(property.name == propName)
{
return property;
}
if(properties[i].name == propertyName)
return i;
}
return null;
return -1;
},
/**
* 获取指定名称的Property对象
*
* @param model
* @param propName 属性名称或者属性索引
*/
getProperty : function(model, propName)
{
//索引
if(typeof(propName) == "number")
return model.properties[propName];
//属性名
else
{
var index = this.getPropertyIndex(model, propName);
if(index < 0)
throw new Error("No property named '"+propName+"'");
return model.properties[index];
}
},
/**

View File

@ -25,7 +25,7 @@
ignorePropertyNames : undefined,
//可选是否渲染指定属性此设置优先级低于ignorePropertyNames
renderProperty : function(property)
renderProperty : function(property, propertyIndex)
{
return true;
},
@ -221,7 +221,7 @@
var property = properties[i];
var propName = property.name;
if(this._isIgnorePropertyName(property))
if(this._isIgnorePropertyName(property, i))
continue;
if($.model.hasFeatureNotReadable(property))
@ -240,7 +240,7 @@
var property = properties[i];
var propName = property.name;
if(this._isIgnorePropertyName(property))
if(this._isIgnorePropertyName(property, i))
continue;
if($.model.hasFeatureNotReadable(property))
@ -269,9 +269,10 @@
}
else
{
var property = $.model.getProperty(this.options.model, propName);
var propertyIndex = $.model.getPropertyIndex(this.options.model, propName);
var property = $.model.getProperty(this.options.model, propertyIndex);
if(property && !this._isIgnorePropertyName(property))
if(!this._isIgnorePropertyName(property, propertyIndex))
this._propertyWidgets[propName].setValue(propValue);
}
},
@ -375,7 +376,7 @@
var property = properties[i];
var propName = property.name;
if(this._isIgnorePropertyName(property))
if(this._isIgnorePropertyName(property, i))
continue;
if($.model.isAbstractedProperty(property))
@ -952,12 +953,12 @@
/**
* 判断属性是否是忽略属性
*/
_isIgnorePropertyName : function(property)
_isIgnorePropertyName : function(property, propertyIndex)
{
var ignore = $.model.containsOrEquals(this.options.ignorePropertyNames, property.name);
if(!ignore)
ignore = (this.options.renderProperty.call(this, property) == false);
ignore = (this.options.renderProperty.call(this, property, propertyIndex) == false);
return ignore;
},

View File

@ -781,23 +781,34 @@
/**
* 根据列索引获取列对应的模型属性
*/
getDataTablesColumnProperty : function(model, settings, columnIndex)
getDataTablesColumnPropertyIndexes : function(settings, cellIndexes)
{
var columns = undefined;
var columnMetas = undefined;
//column.render函数中的结构
if(settings.aoColumns)
columns = settings.aoColumns;
columnMetas = settings.aoColumns;
//.DataTable().settings()结构
else if(settings[0])
columns = settings[0].aoColumns;
columnMetas = settings[0].aoColumns;
var propertyIndex = columns[columnIndex].propertyIndex;
var columnIndexMap = {};
for(var i=0; i<cellIndexes.length; i++)
columnIndexMap[cellIndexes[i].column] = 1;
if(propertyIndex == undefined)
throw new Error("Not valid column index ["+columnIndex+"] for getting column property");
var propertyIndexes = [];
return model.properties[propertyIndex];
for(var ci in columnIndexMap)
{
var propertyIndex = columnMetas[ci].propertyIndex;
if(propertyIndex == undefined)
throw new Error("Not valid column index ["+columnIndex+"] for getting column property");
propertyIndexes.push(propertyIndex);
}
return propertyIndexes;
},
/**
@ -809,9 +820,18 @@
if(clickEvent.ctrlKey)
{
if($clickCell.hasClass("selected"))
{
dataTable.cell($clickCell).deselect();
dataTable.cells(dataTable.cells(".selected").indexes()).select();
}
else
dataTable.cell($clickCell).select();
{
var indexes = [];
indexes = indexes.concat($.makeArray(dataTable.cells(".selected").indexes()));
indexes = indexes.concat(dataTable.cell($clickCell).index());
dataTable.cells(indexes).select();
}
}
//区域选
else if(clickEvent.shiftKey)
@ -895,8 +915,32 @@
if(nextCellIndex.column < 1)
nextCellIndex.column = 1;
selectedCells.deselect();
dataTable.cell(nextCellIndex).select();
//多选
if(keydownEvent.ctrlKey)
{
var indexes = [];
indexes = indexes.concat($.makeArray(selectedCells.indexes()));
indexes = indexes.concat(nextCellIndex);
dataTable.cells(indexes).select();
}
//区域选
else if(keydownEvent.shiftKey)
{
var indexes = [];
indexes = indexes.concat($.makeArray(selectedCells.indexes()));
indexes = indexes.concat(nextCellIndex);
indexes = $.evalCellIndexesForRange(indexes);
dataTable.cells(indexes).select();
}
//单选
else
{
selectedCells.deselect();
dataTable.cell(nextCellIndex).select();
}
}
}
},

View File

@ -349,19 +349,39 @@ table.dataTable tbody th, table.dataTable tbody td{
padding: 0 0.5em;
height: 2.5em;
}
table.dataTable tbody tr td.edit-cell{
table.dataTable tbody tr td.cell-edit-form{
position: relative;
}
table.dataTable tr td.edit-cell .edit-cell-form-panel{
table.dataTable tr td.cell-edit-form .page-edit-grid-form{
opacity: 0.7;
filter: Alpha(Opacity=70);
}
table.dataTable tr td.cell-edit-form .page-edit-grid-form.focus{
opacity: 1;
filter: Alpha(Opacity=100);
}
table.dataTable tr td.cell-edit-form .page-edit-grid-form .form-panel{
position: absolute;
padding: 0.41em 0.41em;
left: -0.5em;
top: 0.75em;
display: inline-block;
z-index: 1;
padding: 1px 1px;
}
table.dataTable tr td.edit-cell .edit-cell-form-panel form .form-content .form-item .form-item-label{
table.dataTable tr td.cell-edit-form .page-edit-grid-form .form-panel .form-panel-title{
height: 10px;
cursor: move;
}
table.dataTable tr td.cell-edit-form .page-edit-grid-form .form-panel form{
width: 40em;
padding: 0.41em 0.41em;
}
table.dataTable tr td.cell-edit-form .page-edit-grid-form .form-panel form.hide-form-label{
width: 30em;
}
table.dataTable tr td.cell-edit-form .page-edit-grid-form .form-panel form.hide-form-label .form-content .form-item .form-item-label{
display: none;
}
table.dataTable tbody tr td .edit-cell-input{
}
table.dataTable tbody tr td.cell-modified{
position: relative;
}