如何在免费的 jqgrid 中将焦点设置为内联编辑的自动完成内容

How to set focus to autocomplete contents on inline edit in free jqgrid

免费 jqgrid 第一列是 Jquery UI 使用自定义编辑类型自动完成。 使用 focusField: true

使字段可聚焦
$.extend(true,$.jgrid.inlineEdit, {
    position: "beforeSelected",
    focusField: true,
    keys: true } );

如果开始内联编辑,jqgrid 会将焦点放在自动完成下拉按钮上。 如何解决焦点放在自动完成输入元素上的问题?

自动完成按钮定义为 tabindex=-1:

<button type='button' class='btn btn-default btn-form-dropdown' tabindex=-1 aria-label='Open menu'>
<span class='caret'></span></button>

在内联编辑中按tab键不会获得焦点

jqgrid代码包含:

    getFocusable = function (elem) {
        return $(elem).find("input,textarea,select,button,object,*[tabindex]")
                                            .filter(":input:visible:not(:disabled)");
                                },

所以 jqgrid 将焦点放在元素上,即使它包含 tabindex=-1

如何解决这个问题?

也发布在 https://github.com/free-jqgrid/jqGrid/issues/186

更新

重现问题的步骤:

  1. 在Chrome
  2. 中打开下面的页面
  3. Select行
  4. 单击内联编辑按钮

观察到:

按钮获得焦点

预计:

输入元素应该获得焦点

重现代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.css" />
    <link rel="stylesheet" href="http://rawgit.com/free-jqgrid/jqGrid/master/css/ui.jqgrid.css" type="text/css" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
    <script src="http://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.src.js"></script>
    <script>
        $(document).ready(function () {
            var mydata = [
                { id: 0, Name: "Indiana", Category: "IN" },
                { id: 1, Name: "California", Category: "CA" },
                { id: 2, Name: "Pennsylvania", Category: "PA" },
                { id: 3, Name: "Texas", Category: "TX" }
            ];
            var lastSel;
            var grid = $("#list");

            grid.jqGrid({
                data: mydata,
                datatype: 'local',
                colModel: [
                    {
                        name: 'Name', editable: true, width: 200,
                        edittype: 'custom',
                        editoptions: {
                            custom_element: combobox_element,
                            custom_value: function (elem) {
                                return elem.find("input").val();
                            }
                        }
                    },

                { name: 'Category', index: 'Category', width: 50, editable: true }
                ],
                ignoreCase: true,
                gridview: true,
                viewrecords: true,
                rownumbers: true,
                pager: '#pager',
                editurl: 'clientArray',
                ondblClickRow: function (id, ri, ci) {
                    grid.jqGrid('editRow', id, true, null, null, 'clientArray', {});
                },
                onSelectRow: function (id) {
                    if (id && id !== lastSel) {
                        if (typeof lastSel !== "undefined") {
                            grid.jqGrid('restoreRow', lastSel);
                        }
                        lastSel = id;
                    }
                }
            }).
            jqGrid("inlineNav", '#pager');
        });

        var getColumnByName = function (grid, columnName) {
            var cm = grid.jqGrid('getGridParam', 'colModel'), i = 0, l = cm.length;
            for (; i < l; ++i) {
                if (cm[i].name === columnName) {
                    return cm[i];
                }
            }
            return null;
        };

        function combobox_element(value, options) {
            var elemStr = '<div><input class="FormElement', newel, width;
            if (options.id === options.name) {
                elemStr += '" size="' +
                        options.size + '"' + ' id="' + options.id + '"';
            }
            else {
                elemStr += ' form-control jqgrid-inlineedit-autocomplete" ' +
                   ' style="width:' + width + 'px" ' + ' id="' + options.id + '_x"';
            }
            elemStr += ' value="' + value + '" lookup="' + options.lookup + '"/>';
            elemStr += "<button type='button' class='btn btn-default btn-form-dropdown' tabindex=-1 aria-label='Open menu'>" +
        "<span class='caret'></span></button>";
            elemStr += '</div>';
            newel = $(elemStr)[0];
            setTimeout(function () {
                input_autocomplete(newel);
            }, 50);
            return newel;
        }

        function input_autocomplete(newel) {
            var input = $("input", newel);
            input.autocomplete({
                source: ["Indiana", 
                "California",
                "Pennsylvania"
                ]
            }
           );
            $("button", newel)
            .bind({
                click: function () {
                    input.focus();
                }
            });
        }
    </script>
</head>

<body>
    <table id="list"></table>
    <div id="pager"></div>
</body>
</html>

我不确定你到底在做什么。您的代码的哪一部分放置 <button type='button' ... tabindex=-1 ...?

tabindex=-1 的放置仅意味着如果用户按下 Tab 或 Shift-Tab,该字段不应获得焦点,但这意味着该字段应该可以通过 API 调用获得焦点。另一方面,tabindex 的存在使其可聚焦,但 tabindex 的负值仅告知将元素从 顺序聚焦导航 中排除。 W3标准将其表述为(见here

The user agent must set the element's tabindex focus flag, but should not allow the element to be reached using sequential focus navigation.

如果不想让按钮成为焦点,应该删除 tabindex 属性。

如果您不创建属性并且它做了一些您使用的控件,但您仍然不想将焦点设置在 <button>,那么您可以将焦点设置在另一个可编辑的柱子。您可以使用 focusField: "someColumnName"focusField: indexOfSomeColumn 将焦点设置在特定列上。

更新: 我发布了 the fix,它在调用 .focus() 之前添加了 .first() 的用法。更改后,您发布的演示效果很好。