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