How to make the jqgrid accessible dialog keyboard available

The answer in How to enable input in jqgrid advanced search box describes how to enable input and other keys in jqgrid advanced search dialog.

After clicking Add Group, Add Subgroup, Remove Rule, or Remove Group in the expanded search dialog, Enter, and the rest of the keys are still ignored. How do I set focus on an added item, or after removing a remaining item, to enable Enter and other keys?

+1


source to share


1 answer


The current version of the Advanced Find dialog (see definition jqFilter

in grid.filter.js

) recreate all the controls of the change someone dialog. See the reDraw code which looks like

this.reDraw = function() {
    $("table.group:first",this).remove();
    var t = this.createTableForGroup(p.filter, null);
    $(this).append(t);
    if($.isFunction(this.p.afterRedraw) ) {
        this.p.afterRedraw.call(this, this.p);
    }
};

      

As you can see the first line to $("table.group:first",this).remove();

delete the contents of the whole filter The current focus will be lost and you have the problems you described.

I suggest fixing the code reDraw

with the document.activeElement element, which was originally introduced in Internet Explorer (at least in IE4) and which is now supported in all web browsers as it is part of the HTML5 standard (see here ). The element that has focus initially will be destroyed and later will not be able to focus on it. So I suggest storing the name of the element and its classes (like input.add-group

or input.add-rule.ui-add

) and finding the position of the element in the search dialog. Later, after the dialog element is recreated, we will focus on the element with the same index.

I suggest changing the code reDraw

to the following

this.reDraw = function() {
    var activeElement = document.activeElement, selector, $dialog, activeIndex = -1, $newElem, $buttons,
        buttonClass,
        getButtonClass = function (classNames) {
            var arClasses = ['add-group', 'add-rule', 'delete-group', 'delete-rule'], i, n, className;
            for (i = 0, n = classNames.length; i < n; i++) {
                className = classNames[i];
                if ($.inArray(className, arClasses) >= 0) {
                    return className;
                }
            }
            return null;
        };
    if (activeElement) {
        selector = activeElement.nodeName.toLowerCase();
        buttonClass = getButtonClass(activeElement.className.split(' '));
        if (buttonClass !== null) {
            selector += '.' + buttonClass;
            if (selector === "input.delete-rule") {
                $buttons = $(activeElement).closest('table.group')
                    .find('input.add-rule,input.delete-rule');
                activeIndex = $buttons.index(activeElement);
                if (activeIndex > 0) {
                    // find the previous "add-rule" button
                    while (activeIndex--) {
                        $newElem = $($buttons[activeIndex]);
                        if ($newElem.hasClass("add-rule")) {
                            activeElement = $newElem[0];
                            selector = activeElement.nodeName.toLowerCase() + "." +
                                getButtonClass(activeElement.className.split(' '));
                            break;
                        }
                    }
                }
            } else if (selector === "input.delete-group") {
                // change focus to "Add Rule" of the parent group
                $newElem = $(activeElement).closest('table.group')
                    .parent()
                    .closest('table.group')
                    .find('input.add-rule');
                if ($newElem.length > 1) {
                    activeElement = $newElem[$newElem.length-2];
                    selector = activeElement.nodeName.toLowerCase() + "." +
                        getButtonClass(activeElement.className.split(' '));
                }
            }
            $dialog = $(activeElement).closest(".ui-jqdialog");
            activeIndex = $dialog.find(selector).index(activeElement);
        }
    }
    $("table.group:first",this).remove();
    $(this).append(this.createTableForGroup(this.p.filter, null));
    if($.isFunction(this.p.afterRedraw) ) {
        this.p.afterRedraw.call(this, this.p);
    }
    if (activeElement && activeIndex >=0) {
        $newElem = $dialog.find(selector + ":eq(" + activeIndex + ")");
        if ($newElem.length>0) {
            $newElem.focus();
        } else {
            $dialog.find("input.add-rule:first").focus();
        }
    }
};

      

As shown in the following demo , the focus in the search dialog remains the same after clicking the Add Subgroup or Add Rule Buttons. I set it on the "Add Rule" buttons of the previous row group in case of clicking "Delete Group".

Another demo uses jQuery UI styling for buttons and texts in buttons (see answer ). After clicking the Delete button (rule or group), I tried to set focus to the previous Add Rule button, because I think it is dangerous to set focus to another Delete button (rule or group).

Also, in the demo, I am using

afterShowSearch: function ($form) {
    var $lastInput = $form.find(".input-elm:last");
    if ($lastInput.length > 0) {
        $lastInput.focus();
    }
}

      

because it seems to me advisable to set initial focus on the last input field when the dialog is opened.

UPDATED : I find it even more meaningful to set focus to the currently pressed Add Subgroup, Add Rule or Remove Group buttons. The advantage that you see when it first clicks on a button with the mouse and then wants to continue with the keyboard. So I suggest changing the line

inputAddSubgroup.bind('click',function() {

      

to



inputAddSubgroup.bind('click',function(e) {
    $(e.target).focus();

      

To change the line

inputAddRule.bind('click',function() {

      

to



inputAddRule.bind('click',function(e) {
    $(e.target).focus();

      

and the line

inputDeleteGroup.bind('click',function() {

      

to



inputDeleteGroup.bind('click',function(e) {
    $(e.target).focus();

      

and the line

ruleDeleteInput.bind('click',function() {

      

to



ruleDeleteInput.bind('click',function(e) {
    $(e.target).focus();

      

+1


source







All Articles