Domanda

Is there anyway to make chosen look at more than just an options text for the search functionality?

for instance:

<select>
    <option data-keywords="circle,ball,sphere">Circle</option>
    <option data-keywords="rectangle,square">Rectangle</option>
</select>

It wouldn't have to do the match underlining on keywords, it would only do the result match underlining if it matched text like it does by default.

If its not native how would I add this in javascript if it has not already been done before.

È stato utile?

Soluzione

A fairly down-to-earth, quick solution can be applied as follows.

Please note

This solution requires/assumes:

  • Chosen Version 1.1.0
  • A data-keywords attribute for each option tag
  • Keywords separated by a comma within the data-keywords attribute

Ok, so let's get to it.

Open your jquery.chosen.js file.

(You will not be able to use the minified version).


1. Assure storage of data attribute in local options

Location => add_option()

Full Definition

SelectParser.prototype.add_option = function(option, group_position, group_disabled) {}

Edit

Look for this.parsed.push() and at the bottom of the definition, just below style, add this code:

keywords: ($(option).data().keywords!==undefined 
   ? $(option).data().keywords.split(',') 
   : false)

2. Make sure the keywords are parsed by the search function

Location => winnow_results()

Full Definition

AbstractChosen.prototype.winnow_results = function() {}

Edit

2.1 Add a new variable keywordMatch to top declaration:

var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;

Becomes:

var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref, keywordMatch;

2.2 Find this condition: if (!(option.group && !this.group_search)){} and after the second line (where option.search_match is set), add this code:

keywordMatch=(option.keywords && option.keywords.indexOf(searchText) > -1);
if(keywordMatch)
    option.search_match=true;

2.3 Find this assignment:

option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);

And replace it with this code:

option.search_text = keywordMatch ? text : (text.substr(0, startpos) + '<em>' + text.substr(startpos));

These modifications come in the form of a quick implementation. If you need more options (for instance that the keywords are not case-sensitive), you need to implement these parts yourself.

Let me know if there are problems or if i forgot anything.

Altri suggerimenti

Thanks SquareCat for your great solution! I wanted to have the ability to search using multiple keywords (including partial keywords) so I developed some crude code that does the job.

Adding onto SquareCats solution:

Instead of using:

keywordMatch=(option.keywords && option.keywords.indexOf(searchText) > -1);

Use this instead:

keywordMatch=this.keyword_string_match(option.keywords,searchText);

And add this function:

AbstractChosen.prototype.keyword_string_match = function(keyword_array, searchtextstring) {
  var value, searchlength, searchterm;
  var continuetonext = "";
  var searchstring = searchtextstring; 
  var wordmatchcounter = 0;
  if (searchstring !== ""){
    searchstring = searchstring.split(' ');
      for (searchterm = 0 ; searchterm < searchstring.length; searchterm++ ){
        if (continuetonext == "" || continuetonext == true){
          continuetonext = false;
          searchtext = searchstring[searchterm];
          for (var i = 0; i < keyword_array.length; ++i) {
              value = keyword_array[i];
              searchlength = searchtext.length;
              if (value.substring(0, searchlength) === searchtext) {
               continuetonext = true;
               wordmatchcounter++;     
              }else{
                continuetonext = false;
              };
          };
       };
      };
    if (wordmatchcounter == searchterm){return true}else{return false};
  }else{return false};
};

I believe something like that will work:

JavaScript

document.getElementById('filter-input').onkeyup = function () {
  filter(this.value, document.getElementById('select-input'));
};

function filter(value, input) {
  var children = input.children,
      found = false,
      keywords;
  children = Array.prototype.slice.call(children);
  children.forEach(function (c) {
    c.removeAttribute('selected');
  });
  children.forEach(function (c) {
    keywords = c.getAttribute('data-keywords').split(',');
    keywords.forEach(function (k) {
      if (k === value) {
        found = true;
        c.setAttribute('selected', true);
        return;
      }
    });
    if (found) return;
  });
}

DEMO

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top