Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<p:selectOneMenu caseSensitive="true"> doesn't seem to have any effect

I have following select one menu. but case sensitive is not working in it. when I press small a or capital A, it always shows small a (whichever occurs first).

        <p:selectOneMenu id="tempSelect" caseSensitive="true">
                        <f:selectItem itemLabel="0" itemValue="0"/>
                        <f:selectItem itemLabel="a" itemValue="a"/>
                        <f:selectItem itemLabel="A" itemValue="A"/>
                        <f:selectItem itemLabel="b" itemValue="b"/>
        </p:selectOneMenu>

My primefaces version is 5.2.

When the select box is in focus. I press alphabet letter "a" or I press capital alphabet letter "A" , in both cases it only shows "a" in the box (because it occurs first in the list). This is actual behaviour.

My expected behaviour is that when I press "a" it puts "a" and when I press "A" it puts "A" in the box.

What should I do for this?

like image 346
Imran Khurram Avatar asked Sep 09 '15 10:09

Imran Khurram


2 Answers

The Primefaces 5.2 documentation (page 430) says about CaseSensitive option:

Defines if filtering would be case sensitive.

So this option only applies if you use filter="true", and only for the values you type in the filter box.

When you focus on SelectOneMenu control and enter a value, the search will always be case insensitive, as you can see in the source code of Primefaces (line 848). Note that the texts are placed in LowerCase before the comparison.

return $(this).text().toLowerCase().indexOf(text.toLowerCase()) === 0;

One way (not very elegant) you solve this problem is overriding the Primefaces function responsible for this filter. Remember that, in this case, others SelectOneMenu controls in the same page will be case sensitive too.

So the line 848 would become like this:

return $(this).text().indexOf(text) === 0;

Another detail that should probably be considered (if you really want to overwrite the function) is that on line 842 of source code, Primefaces discards all entries that have the Shift key.

metaKey = e.metaKey||e.ctrlKey||e.shiftKey;

Therefore, this line should also be changed like bellow to facilitate entry of capital letters:

metaKey = e.metaKey||e.ctrlKey;

So, considering these two changes, and the final version of Primefaces 5.2 (minified), the solution is to just add the following code somewhere after the SelectOneMenu.

<script>
    PrimeFaces.widget.SelectOneMenu.prototype.bindKeyEvents = function() {
        var a = this;
        this.focusInput.on("keydown.ui-selectonemenu", function(d) {
            var c = $.ui.keyCode, b = d.which;
            switch (b) {
            case c.UP:
            case c.LEFT:
                a.highlightPrev(d);
                break;
            case c.DOWN:
            case c.RIGHT:
                a.highlightNext(d);
                break;
            case c.ENTER:
            case c.NUMPAD_ENTER:
                a.handleEnterKey(d);
                break;
            case c.TAB:
                a.handleTabKey();
                break;
            case c.ESCAPE:
                a.handleEscapeKey(d);
                break
            }
        }).on(
                "keyup.ui-selectonemenu",
                function(g) {
                    var f = $.ui.keyCode, d = g.which;
                    switch (d) {
                    case f.UP:
                    case f.LEFT:
                    case f.DOWN:
                    case f.RIGHT:
                    case f.ENTER:
                    case f.NUMPAD_ENTER:
                    case f.TAB:
                    case f.ESCAPE:
                    case f.SPACE:
                    case f.HOME:
                    case f.PAGE_DOWN:
                    case f.PAGE_UP:
                    case f.END:
                    case f.DELETE:
                    case 16:
                    case 17:
                    case 18:
                    case 224:
                        break;
                    default:
                        var i = $(this).val(), c = null, h = g.metaKey
                                || g.ctrlKey;
                        if (!h) {
                            clearTimeout(a.searchTimer);
                            c = a.options.filter(function() {
                                return $(this).text()
                                        .indexOf(i) === 0
                            });
                            if (c.length) {
                                var b = a.items.eq(c.index());
                                if (a.panel.is(":hidden")) {
                                    a.selectItem(b)
                                } else {
                                    a.highlightItem(b);
                                    PrimeFaces.scrollInView(
                                            a.itemsWrapper, b)
                                }
                            }
                            a.searchTimer = setTimeout(function() {
                                a.focusInput.val("")
                            }, 1000)
                        }
                        break
                    }
                })
    }
</script>

To test, remember that there is a timer of 1 second between each keystroke to clear the cache of letters that have been entered and start a new word.

like image 70
Marcelo Barros Avatar answered Oct 02 '22 19:10

Marcelo Barros


Although is not the perfect solution you can use this workaround. Use a filter. In this way you need one more "click" but it works.

<p:selectOneMenu id="tempSelect" caseSensitive="true" filter="true" filterMatchMode="startsWith"> <f:selectItem itemLabel="0" itemValue="0"/> <f:selectItem itemLabel="a" itemValue="a"/> <f:selectItem itemLabel="A" itemValue="A"/> <f:selectItem itemLabel="b" itemValue="b"/> </p:selectOneMenu>

like image 38
Julio Avatar answered Oct 02 '22 18:10

Julio