【发布时间】:2011-07-17 10:11:00
【问题描述】:
我们的 Web 应用程序使用 jqGrid 进行数据输入,并且数据是内联和成行编辑的。
客户希望获得更“类似于 Excel”的体验,以便在通过单击单元格将行切换到内联编辑时,该单元格会获得焦点(目前,该行中的第一个单元格会获得焦点)。
【问题讨论】:
标签: javascript jquery jqgrid
我们的 Web 应用程序使用 jqGrid 进行数据输入,并且数据是内联和成行编辑的。
客户希望获得更“类似于 Excel”的体验,以便在通过单击单元格将行切换到内联编辑时,该单元格会获得焦点(目前,该行中的第一个单元格会获得焦点)。
【问题讨论】:
标签: javascript jquery jqgrid
我遇到了同样的问题。非常令人沮丧。我修改了 jquery.jqGrid.js 文件以适应在单击的单元格上设置焦点。
在我的 editRow 函数中,我添加了以下代码:
function editRow(id, row, col, z)
{
grid.jqGrid("editRow", id, true, function ()
{
var f = $("input, select", z.target).focus();
return f;
});
}
这将创建一个变量 f,最终将传递给 $.jgrid.extend 中的“oneditfunc”
问题出在 setTimeout 函数中。
$("td:eq("+focus+") input",ind).focus();
因为这会在焦点设置到上面 .each 函数的第一个可编辑字段的情况下执行。这将是传递焦点索引的好地方,但不可能。
// End compatible
return this.each(function ()
{
var $t = this, nm, tmp, editable, cnt = 0, focus = null, svr = {}, ind, cm, bfer;
...
然后我添加了以下代码。 (带 >>> 的行没有变化,只是为了帮助你在代码中找到插入点。)
>>> $($t).triggerHandler("jqGridInlineEditRow", [rowid, o]);
if ($.isFunction(o.oneditfunc))
{
// modified to allow for setting focus on the
// field clicked on
// sets a return value. this was added to the original code. if using
// legacy code, should see no change as r will be undefined
var r = o.oneditfunc.call($t, rowid);
// if get a return value, this indicates you want to set focus
if (r && r[0])
{
var focusIndex = focus;
var i = 0;
// look for the field name that was clicked on
// cm, which is built above, has no index value associated
// with it, so we must keep track of
var focusField = $.grep(cm, function(c)
{
// find the field name which was clicked on
if (c.name == r[0].name)
focusIndex = i;
i++;
return c.name == r[0].name;
});
// if the field is editable, then update focus index
// which is defined above
if (focusField[0].editable)
{
focus = focusIndex;
}
}
}
最优雅的解决方案?可能不会,但它确实允许所有遗留代码工作并确定单击了哪个字段以便设置焦点
【讨论】:
不幸的是,网格只能将焦点设置到行中的第一个可编辑字段。你可以在grid.inlinedit.js的源代码中看到这一点。在这里,它通过遍历它们并找到第一个来计算要设置焦点的行的索引:
if(cm[i].editable===true) {
if(focus===null) { focus = i; }
然后它会设置焦点:
$("td:eq("+focus+") input",ind).focus();
选择存储在 focus 变量中的索引处的元素 - 有关参考,请参阅 :eq selector 文档。
也就是说,如果您愿意,可以编辑这部分代码以添加您自己的自定义逻辑来控制哪个元素获得焦点...
【讨论】:
我同意贾斯汀的观点,即 jqGrid 没有直接支持您需要的行为。作为 jqGrid 的一种选择,您可以接收所需的方式可能会更复杂。从the answer 看the code。希望对你有帮助。
【讨论】:
这是 jqGrid 的严重缺陷。 如果网格比窗口宽,您还需要向右滚动以使单击的单元格可见。为此,您可以使用来自 http://www.trirand.com/blog/?page_id=393/help/inline-edit-problem-with-scrolling/
if (rowID && rowID !== lastSelectedRow) {
var scrollPosition = 0;
scrollPosition = grid2.closest(".ui-jqgrid-bdiv").scrollLeft();
grid2.jqGrid('restoreRow', lastSelectedRow);
grid.jqGrid('editRow', rowID, true);
lastSelectedRow = rowID;
setTimeout(function(){
grid2.closest(".ui-jqgrid-bdiv").scrollLeft(scrollPosition);
},100);
【讨论】:
就我而言,我使用 Justin Ethier 和 Steve 的答案提出了我自己的解决方案(针对 jqGrid 4.4.3):
在jqGrid的源码中,我只是注释掉了下面一行(这是为了防止编辑行的第一个输入获得焦点):
// commented out
// $("td:eq("+focus+") input",ind).focus();
然后,我创建一个全局 js 变量来保存网格上的点击源:
var clickedCell;
最后,在单击单元格时设置该变量。
$('#myJqGrid td').on('click', function(e){ clickedCell = this; });
为了能够将事件附加到表格单元格,我们需要确保网格已创建,因此必须在 jqGrid 的“gridComplete”函数中完成,例如:
$('#myJqGrid').jqGrid('setGridParam', {
gridComplete: function(id){
$('#myJqGrid td').on('click', function(e){ clickedCell = this; });
}
});
最后,在编辑行时,我检索单击的单元格(保存在变量“clickedCell”中),并将焦点放在其中的输入或文本区域。这必须在 jqGrid 的“onSelectRow”函数中完成:
$('#myJqGrid').jqGrid('setGridParam',
{
onSelectRow : function(id) {
...
//switching the selected row to editmode
$('#myJqGrid').jqGrid(
'editRow',
id,
{
keys: true,
// when editing the row, give the focus to the input
//or textarea within the last clicked cell
oneditfunc: function() {
$('input, textarea', clickedCell).focus();
}
);
...
}
}
});
唯一的问题是,如果不触及 jqGrid 的源代码,就真的没有解决方案。如果你不这样做,它仍然可以工作,但第一个输入仍然会首先获得焦点,移动页面的水平滚动,即使在分配了正确的焦点之后也是如此。
【讨论】:
我在另一个与 stackoverflow 相关的问题中发布了这个答案。希望这适用于您。
我通过将 dblclick 事件附加到表的每个 td 以某种方式成功地实现了这一点,我知道这不是最好的方法,但你可以随意优化它,你也可以忽略使用的 setTimeout仅用于测试。
$("#jqGrid").on("dblclick", "td", function (event) {
// setTimeout(function () {
console.log(this);
$(event.target).find("input,select").focus();
// }, 0);
});
希望这会对你有所帮助。
【讨论】: