selectize.js icon indicating copy to clipboard operation
selectize.js copied to clipboard

possibility to search test (with diacritics) as **starts with**

Open hidegh opened this issue 10 years ago • 9 comments

https://github.com/brianreavis/sifter.js/issues/15

searching inside text is cool, but if you have to narrow down the possibilities, sometimes it's necessary to match only items, where item starts with the search text...

also it'd be nice, if only that part of the items would be highlighted inside the combo.

hidegh avatar Dec 05 '14 08:12 hidegh

first i had to replace special chars to an 'ascii' (latin) equivalent

        (function() {

            var DIACRITICS = {
                'a': '[aÀÁÂÃÄÅàáâãäå]',
                'c': '[cÇçćĆčČ]',
                'd': '[dđĐďĎ]',
                'e': '[eÈÉÊËèéêëěĚ]',
                'i': '[iÌÍÎÏìíîï]',
                'n': '[nÑñňŇ]',
                'o': '[oÒÓÔÕÕÖØòóôõöø]',
                'r': '[rřŘ]',
                's': '[sŠš]',
                't': '[tťŤ]',
                'u': '[uÙÚÛÜùúûüůŮ]',
                'y': '[yŸÿýÝ]',
                'z': '[zŽž]'
            };

            var escape_regex = function(str) {
                return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
            };

            String.prototype.replaceDiacritics = function(remove) {
                if (remove === undefined)
                    remove = true;

                if (remove === true) {

                    var regex = escape_regex(this);

                    $.each(DIACRITICS, function(key, value) {
                        regex = regex.replace(new RegExp(value, 'g'), key);
                    });

                    return regex.toString();
                }

                return this;
            };

        }());

i wanted to preserve the original scoring, but even so i had to ensure scoring is not 0 in case when we had a match...so that +1 is mandatory...

                score: function(search) {

                    var score = this.getScoreFunction(search);
                    var modifiedSearchText = search.replaceDiacritics().toUpperCase();

                    return function(item) {

                        var modifiedItemText = item.value.replaceDiacritics().toUpperCase();
                        var indexOf = modifiedItemText.indexOf(modifiedSearchText);

                        if (indexOf == 0) {
                            var itemScore = score(item);
                            return 1 + itemScore;
                        }

                        return 0;
                    };
                }


hidegh avatar Dec 05 '14 14:12 hidegh

To add: the only drawback is that highlighting isn't correct. @brianreavis adviced to "just adjust tokenize to not split on spaces and add a ^ to the beginning of the regexp that it produces."

but that would not allow us to have 2 selectize.js component, one that matches starts and other one that matches anything (contains).

so the only real solution is to have a match parameter inside selectize (this could be some regex) that is later passed to sifter.js (as a parameter). this would be quiet flexibe and possibly even highlighting would work with it :smile:

please if anyone finds this improvement usefull, give a +1 vote to it. thanx.

hidegh avatar Dec 10 '14 08:12 hidegh

I'd really need that starts with search, so I give :100: :+1:

sophiedeziel avatar Jul 14 '15 14:07 sophiedeziel

+1 !

falkenhawk avatar Nov 19 '15 16:11 falkenhawk

+1 !

davidrevoledo avatar Apr 28 '17 12:04 davidrevoledo

+1

kashpatel avatar Mar 28 '18 18:03 kashpatel

+1 !

RagazziMoscow avatar May 12 '18 12:05 RagazziMoscow

It looks like sifter v0.6.0 has implemented the option respect_word_boundaries, see https://github.com/brianreavis/sifter.js/pull/51. This is effectively the same as a "starts with" search. Now all that's left to do is for someone to add an option to selectize that sets respect_word_boundaries to true. For now, you could (temporarily) modify the prototype of selectize like so:

var getSearchOptions = Selectize.prototype.getSearchOptions;
Selectize.prototype.getSearchOptions = function () {
	var options = getSearchOptions.apply(this, arguments);
	options.respect_word_boundaries = true;
	return options;
};

This sets respect_word_boundaries to true every time selectize calls sifter internally. Alternatively, you could modify the prototype of sifter itself to make respect_word_boundaries true.

RudeySH avatar May 22 '20 15:05 RudeySH

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

github-actions[bot] avatar Jan 07 '21 02:01 github-actions[bot]