1

Answer in how to enable enter in jqgrid advanced search window describes how to enable enter and other keys in jqgrid advanced search dialog.

After clicking Add group, Add subgrup, Delete rule or Delete group button in advanced search dialog Enter and other keys are still ignored. How set focus to added element or after delete remaining element to enable Enter and other keys?

Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378

1 Answers1

1

The current version of the Advanced Searching dialog (see definition of jqFilter in the grid.filter.js) recreate all controls of the dialog on change of someone. See the code of reDraw which looks

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);
    }
};

How one can see the first line $("table.group:first",this).remove(); delete the content of all filter. The current focus will be lost and one have the problems which you described.

I suggest to fix the code of reDraw using document.activeElement element which was introduced in Internet Explorer originally (at least in IE4) and which is supported now in all web browsers because it's part of HTML5 standard (see here). The element which has focus originally will be destroyed and one will unable to set focus on it later. So I suggest to save the element name of the element and it's classes (like input.add-group or input.add-rule.ui-add) and to find the position of the element on the searching dialog. Later, after the dialog element will be recreated we'll set focus on the element with the same index.

I suggest to change the code of 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();
        }
    }
};

Like one can see on the next demo the focus in the Searching Dialog stay unchanged after pressing on the "Add subgroup" or "Add rule" buttons. I set it on the "Add rule" buttons of the previous row group in case of pressing "Delete group".

One more demo use jQuery UI style of the buttons and the texts in the buttons (see the answer). After clicking on the "Delete" (rule or group) button I tried to set the focus to the previous "Add Rule" button because setting of the focus on another "Delete" (rule or group) button I find dangerous.

Additionally in the demo I use

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

because it seems me meaningful to set initial focus on the last input field at the dialog opening.

UPDATED: I find additionally meaningful to set focus on the current clicked buttons "Add subgroup", "Add rule" or "Delete group". The advantage one sees in the case it one first click some button with the mouse and then want to continue the work with keyboard. So I suggest to change 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();
Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • I tried those changes with afterRedraw code from other answer which applies jQuieryUI button() to dialog buttons. In this case button does not receive focus and keyboard keys are still ignored after clicking in button – Andrus Apr 08 '12 at 21:01
  • @Andrus: I updated the code one more time (see above). The new demo is [here](http://www.ok-soft-gmbh.com/jqGrid/SearchOnEnter3.htm). – Oleg Apr 08 '12 at 23:52
  • Thak you, it works. I tried with body vertical scrollbar disabled. After clicking to Add buttons button several times dialog height increases out of screen (vertical scrollbar does not appear in dialog). Also after clicking to Add rule button in IE9 if mouse is hovered over Add role button, dialog height increases on every hover. I think we fixed this for edit form (I provided then testcase for this in other question). – Andrus Apr 09 '12 at 07:08