Skip to content

"Fuzzy" word search #858

@YANOUSHek

Description

@YANOUSHek

Hi,

I'm a fellow developer who recently found chosen and I'm amazed by you solution. I did run into a couple problems with the filtering text which I managed to work out and change a couple lines in your code. I don't know if this is something that might interest you and you'd like to have it merged with your code. Let me describe the problem and show you a diff of my changes.

The problem I had was searching for more than word. For example, if you go to your demo site, insert the text "bosnia herz" into the country select and you'll see that nothing matches because you're searching for the exact string I've typed. Also you can't type words in wrong order or just parts of the words ("uni sta").

I'd really like the option to have such a "fuzzy" filter and I've managed to change the jquery version of chosen to just do that. The diff:

diff --git a/chosen/chosen.jquery.js b/chosen/chosen.jquery.js
index 3e559e2..3799d41 100644
--- a/chosen/chosen.jquery.js
+++ b/chosen/chosen.jquery.js
@@ -792,6 +792,7 @@ Copyright (c) 2011 by Harvest
       this.no_results_clear();
       results = 0;
       searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
+      var words = searchText.toLowerCase().split(' ');
       regexAnchor = this.search_contains ? "" : "^";
       regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
       zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
@@ -802,32 +803,20 @@ Copyright (c) 2011 by Harvest
           if (option.group) {
             $('#' + option.dom_id).css('display', 'none');
           } else if (!(this.is_multiple && option.selected)) {
-            found = false;
             result_id = option.dom_id;
             result = $("#" + result_id);
-            if (regex.test(option.html)) {
-              found = true;
-              results += 1;
-            } else if (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0) {
-              parts = option.html.replace(/\[|\]/g, "").split(" ");
-              if (parts.length) {
-                for (_j = 0, _len2 = parts.length; _j < _len2; _j++) {
-                  part = parts[_j];
-                  if (regex.test(part)) {
-                    found = true;
-                    results += 1;
-                  }
-                }
+            found = true;
+            for (var i_word = 0; i_word < words.length; ++i_word) {
+              if (option.html.toLowerCase().indexOf(words[i_word]) < 0) {
+                found = false;
+                break;
               }
             }
             if (found) {
-              if (searchText.length) {
-                startpos = option.html.search(zregex);
-                text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
-                text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
-              } else {
-                text = option.html;
-              }
+              results += 1;
+            }
+            if (found) {
+              text = option.html;
               result.html(text);
               this.result_activate(result);
               if (option.group_array_index != null) {

This was just me hacking at the jQuery version to have it running on my site. I've lost the option to highlight the text that matched the filter but I didn't really care about that.

If this is something that might interest you I'll make a fork and submit a pull request. I'll even bring back the <em> highlights.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions