Primefaces SelectOneMenu selects an item by pressing a hotkey with CTRL

I have forms in JSF with some keyboard shortcuts, for example CTRL+S triggers submit to save the data.

The problem is that when a key combination is pressed in a field <p:selectOneMenu>, the first item starting with S (as the example) is selected and then the form is submitted.

You can reproduce this behavior by accessing the showcase , selecting the first field and pressing CTRL+OR . In Chrome, at least, it will select the first option and then open the "Open File" Dialog (Open ).

My intention is for the component to ignore the typed letter if a special key is pressed.

I tested the html component SELECT and the jQuery UI combo and the same behavior does not occur. By the way, PrimeFaces uses a different wrapper for a input field.

I tried to add a return false both in the onkeydown attribute event as in the onkeyup as per the User Guide. Nothing done.

I still tried to add keyboard events by jQuery with preventDefault() and return false. Nothing.

Well, before you download PrimeFaces font and start banging, does anyone have any idea how to get around this situation?


Update

More details about the component.

Opening the showcase Page , I clicked on the first component and left the SELECT open.

I pressed F12 to open the console and typed document.activeElement. The result was a input:

<input id="j_idt18:j_idt22_focus" name="j_idt18:j_idt22_focus" type="text" readonly="readonly">

I understand that this is the field that actually gets the value and receives the events. It should have an event handler that selects the item when you press a letter, but it certainly lacked a treatment for the case of special keys like CTRL and SHIFT.

Author: utluiz, 2014-05-16

1 answers

I got around the problem by retrieving a later version of the PrimeFaces library from the SVN repository. Some Javascript functions were fixed.

I extracted the fixed functions and added a Javascript file to overwrite the incorrect ones of the version with problems.

The code is:

/**
 * Fix for selectOneMenu when key is pressed along with CTRL
 */
PrimeFaces.widget.SelectOneMenu = PrimeFaces.widget.SelectOneMenu.extend({

    bindKeyEvents: function() {
        var $this = this;

        this.focusInput.on('keydown.ui-selectonemenu', function(e) {
            var keyCode = $.ui.keyCode,
            key = e.which;

            switch(key) {
                case keyCode.UP:
                case keyCode.LEFT:
                    $this.highlightPrev(e);
                break;

                case keyCode.DOWN:
                case keyCode.RIGHT:
                    $this.highlightNext(e);
                break;

                case keyCode.ENTER:
                case keyCode.NUMPAD_ENTER:
                    $this.handleEnterKey(e);
                break;

                case keyCode.TAB:
                    $this.handleTabKey();
                break;

                case keyCode.ESCAPE:
                    $this.handleEscapeKey(e);
                break;
            }
        })
        .on('keyup.ui-selectonemenu', function(e) {
            var keyCode = $.ui.keyCode,
            key = e.which;
            switch(key) {
                case keyCode.UP:
                case keyCode.LEFT:
                case keyCode.DOWN:
                case keyCode.RIGHT:
                case keyCode.ENTER:
                case keyCode.NUMPAD_ENTER:
                case keyCode.TAB:
                case keyCode.ESCAPE:
                break;

                default:
                    var text = $(this).val(),
                    matchedOptions = null;

                    clearTimeout($this.searchTimer);

                    matchedOptions = $this.options.filter(function() {
                        return $(this).text().toLowerCase().indexOf(text.toLowerCase()) === 0;
                    });

                    if(matchedOptions.length) {
                        var highlightItem = $this.items.eq(matchedOptions.index());
                        if($this.panel.is(':hidden')) {
                            $this.selectItem(highlightItem);
                        }
                        else {
                            $this.highlightItem(highlightItem);
                            PrimeFaces.scrollInView($this.itemsWrapper, highlightItem);
                        }
                    }

                    $this.searchTimer = setTimeout(function(){
                        $this.focusInput.val('');
                    }, 1000);

                break;
            }
        });
    }
});
 5
Author: utluiz, 2014-07-22 16:29:33