4

I use PrimeFaces SelectOneMenu advanced. Filter is wrong working when I input the i and ı character.
For example http://www.primefaces.org/showcase/ui/input/oneMenu.xhtml demo advanced one menu I search arI and arİ strings and it finds Aristo element.

In my application, my menu contains Isparta element. I input Isp and İsp and filter finds Isparta.

How can I solve this problem?

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
Gökhan Memiş
  • 196
  • 1
  • 8

3 Answers3

2

I resolve this problem with autocomplete component. Primefaces autocomplete component with dropdown="true" property works like one menu and this component don't have Turkish character problem.

Gökhan Memiş
  • 196
  • 1
  • 8
1

Reported to PrimeFaces Team: https://github.com/primefaces/primefaces/issues/9629

Fixed for 13.0.0 but MonkeyPatch provided here:

if (PrimeFaces.widget.SelectOneMenu) {

    PrimeFaces.widget.SelectOneMenu.prototype.normalize = function(string, lowercase) {
        if (!string) return string;
        var result = string.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
        return lowercase ? result.toLowerCase() : result;
    }

    PrimeFaces.widget.SelectOneMenu.prototype.filter = function(value) {
        this.cfg.initialHeight = this.cfg.initialHeight || this.itemsWrapper.height();
        var filterValue = this.normalize(PrimeFaces.trim(value), !this.cfg.caseSensitive);

        if (filterValue === '') {
            this.items.filter(':hidden').show();
            this.itemsContainer.children('.ui-selectonemenu-item-group').show();
        } else {
            var hide = [];
            var show = [];

            for (var i = 0; i < this.options.length; i++) {
                var option = this.options.eq(i),
                    itemLabel = this.normalize(option.text(), !this.cfg.caseSensitive),
                    item = this.items.eq(i);

                if (item.hasClass('ui-noselection-option')) {
                    hide.push(item);
                } else {
                    if (this.filterMatcher(itemLabel, filterValue)) {
                        show.push(item);
                    } else if (!item.is('.ui-selectonemenu-item-group-children')) {
                        hide.push(item);
                    } else {
                        itemLabel = this.normalize(option.parent().attr('label'), !this.cfg.caseSensitive);
                        if (this.filterMatcher(itemLabel, filterValue)) {
                            show.push(item);
                        } else {
                            hide.push(item);
                        }
                    }
                }
            }

            $.each(hide, function(i, o) {
                o.hide();
            });
            $.each(show, function(i, o) {
                o.show();
            });
            hide = [];
            show = [];

            //Toggle groups
            var groups = this.itemsContainer.children('.ui-selectonemenu-item-group');
            for (var g = 0; g < groups.length; g++) {
                var group = groups.eq(g);

                if (g === (groups.length - 1)) {
                    if (group.nextAll().filter('.ui-selectonemenu-item-group-children:visible').length === 0)
                        hide.push(group);
                    else
                        show.push(group);
                } else {
                    if (group.nextUntil('.ui-selectonemenu-item-group').filter('.ui-selectonemenu-item-group-children:visible').length === 0)
                        hide.push(group);
                    else
                        show.push(group);
                }
            }

            $.each(hide, function(i, o) {
                o.hide();
            });
            $.each(show, function(i, o) {
                o.show();
            });
        }

        var firstVisibleItem = this.items.filter(':visible:not(.ui-state-disabled):first');
        if (firstVisibleItem.length) {
            this.highlightItem(firstVisibleItem);
            PrimeFaces.scrollInView(this.itemsWrapper, firstVisibleItem);
        }

        if (this.itemsContainer.height() < this.cfg.initialHeight) {
            this.itemsWrapper.css('height', 'auto');
        } else {
            this.itemsWrapper.height(this.cfg.initialHeight);
        }

        this.alignPanel();
    }
};
Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
Melloware
  • 10,435
  • 2
  • 32
  • 62
0

From PrimeFaces 13 normalization can be applied on both the item label and the filter value by setting the filterNormalize attribute to true. You can do the same in older versions using a filterFunction. For example:

<script>
function searchable(string) {
    return !string ? '' : string.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
}

function customFilter(itemLabel, filterValue) {
    return searchable(itemLabel).includes(searchable(filterValue));
}
</script>

<p:selectOneMenu filter="true" filterMatchMode="custom" filterFunction="customFilter"
                 .../>

See also:

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102