分享

基于jquery实现表格中的上下左右键切换input的焦点

 hncdman 2023-03-18 发布于湖南

思路有用,实际无用

  前段时间在项目中遇到一个表格中要批量录入非常多的数据,鼠标键盘操作令人眼花缭乱,顿有想法要做个利用键盘的上下左右键切换输入框焦点的小插件。

  要实现的功能为:

    上键:焦点到上一行相同列的input,

    下键:焦点到下一行相同列的input,

    左键:焦点到本行左边相邻的input,

    右键:焦点到本行右边相邻的input

  当然这里说的input都在一个table中的所有的input。既然是要通过键来实现,我只能想到通过keydown的事件来处理了,通过测试,那个几个键的code分别为:

上键:38,下键:40,左键:37,右键:39.当keycode等于这几个值时我就进行处理,这里用switch行,用if,esle也可以,我比较喜欢用后者

  比较关键的地方是要找到按键后焦点该去哪个input。 如果利用jquery,首先会想到的就是查找父元素中的符合条件的input的下一个,在同一个tr中这个比较好找,但如果当前元素是本行的最后一个,如果输入右键,焦点应该跳到下一行的第一个inpput,这时候就麻烦了。并且如果单纯的利用dom就那样find来find去,很难达到目的。

  上下键的切换只要找到input间相对应的index就可以了。中间本来想通过input所在的单元格的索引来查找查找上行或者下行的同列的单元格中的input,但通过parents查找的td总是与通过tr>td中超找的相对应的td不相等,利用chome调试只有选择器有区别,其他属性都一致,可就是用index方法找不出来,始终是-1...此路就此终结

  不得不采用终极解决方案:在input上加属性,存储他是第几行第几列,到时直接取出,去找上下行的第几列就得了,所以在遍历的符合条件的input时加上这句

$(this).attr("_r_", inputRowIndex).attr("_c_", j);

  inputRowIndex为行的索引,j为列的索引.

  现在就要考虑每次要从哪去查找那些input,如果通过jquery的dom去找,每次keydown都去find,效率自然会比较低,为什么低不太好解释。这里显然用变量来存储所有的input会高效些。但又如何实现很方便的查找呢?

  比较自然的我就会想到构造一个table那样的立体结构来存储,一行一行的保存,并且都是按顺序的存储,并且我能在每个元素上取到我想要的东西,比如当前元素是第几行,第几列。我能很方便的获取数据,比如我传递第几行,第几列过去就能很方便的获取对应的input。这两样东西js都有现成的了,第一个用json,第二个,嘿嘿,非数组不能那样方便高效的获取数据了,于是我定义出如下数据格式

var rowInputs = [
     [
         { "length": len, //当前行有多少个input
          "rowindex":row, //当前行在所有数据行中的索引
          “data”:[   //input集合
               { "c": j, "input": this } //单个input元素,c为列
               。。。。
          ]}
          。。。。
     ]
     。。。
]; //所有的input集合,一个元素为一个tr中的所有的input

  这样我能比较方便的找到当前元素的第几行,第几列,然后根据keycode来计算要获得焦点的input:(查看了排版,源代码还是直接在下面看好了)

见下完整代码
$(rowInputs[r].data[c].input).focus();为设置焦点<br><br>好了,大概就这么多了吧。<br><strong>不过后面还要注意的是,如果要通用到所有的项目中,那么应该考虑隐藏的,只读的情况,那些input都不赢考虑在内</strong><br>经实际测试,有一行数据都是只读的,所有出现那样的情况,应该整行数据都抛弃:
var thisRowInputs;
if (!inputType) { //所有的input
    thisRowInputs = $(obj).find("input:not(:disabled):not(:hidden):not([readonly])");
} else {
    thisRowInputs = $(obj).find("input:not(:disabled):not(:hidden):not([readonly])[type=" + inputType + "]");
}
if (thisRowInputs.length == 0)
    return true;

完整源代码如下:

var tabTableInput = function (tableId, inputType) {
            var rowInputs = [];
            var trs = $("#" + tableId).find("tr");
            var inputRowIndex = 0;
            $.each(trs, function (i, obj) {
                if ($(obj).find("th").length > 0) { //跳过表头
                    return true;
                }
                var rowArray = [];
                var thisRowInputs;
                if (!inputType) { //所有的input
                    thisRowInputs = $(obj).find("input:not(:disabled):not(:hidden):not([readonly])");
                } else {
                    thisRowInputs = $(obj).find("input:not(:disabled):not(:hidden):not([readonly])[type=" + inputType + "]");
                }
                if (thisRowInputs.length == 0)
                    return true;
 
                thisRowInputs.each(function (j) {
                    $(this).attr("_r_", inputRowIndex).attr("_c_", j);
                    rowArray.push({ "c": j, "input": this });
 
                    $(this).keydown(function (evt) {
                        var r = $(this).attr("_r_");
                        var c = $(this).attr("_c_");
 
                        var tRow
                        if (evt.which == 38) { //上
                            if (r == 0)
                                return;
 
                            r--; //向上一行
 
                            tRow = rowInputs[r];
                            if (c > tRow.length - 1) {
                                c = tRow.length - 1;
                            }
                        } else if (evt.which == 40) { //下
                            if (r == rowInputs.length - 1) { //已经是最后一行
                                return;
                            }
 
                            r++;
                            tRow = rowInputs[r];
                            if (c > tRow.length - 1) {
                                c = tRow.length - 1;
                            }
                        } else if (evt.which == 37) { //左
                            if (r == 0 && c == 0) {  //第一行第一个,则不执行操作
                                return;
                            }
                            if (c == 0) { //某行的第一个,则要跳到上一行的最后一个,此处保证了r大于0
                                r--;
                                tRow = rowInputs[r];
                                c = tRow.length - 1;
                            } else { //否则只需向左走一个
                                c--;
                            }
                        } else if (evt.which == 39) { //右
                            tRow = rowInputs[r];
                            if (r == rowInputs.length - 1 && c == tRow.length - 1) { //最后一个不执行操作
                                return;
                            }
 
                            if (c == tRow.length - 1) { //当前行的最后一个,跳入下一行的第一个
                                r++;
                                c = 0;
                            } else {
                                c++;
                            }
                        }
 
                        $(rowInputs[r].data[c].input).focus();
                    });
                });
 
                rowInputs.push({ "length": thisRowInputs.length, "rowindex": inputRowIndex, "data": rowArray });
 
                inputRowIndex++;
 
            });
        }

调用很简单:

 new tabTableInput("tblGrid","text"); 至于后面那个参数,看下源代码就得了

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多