Reputation: 1810
Has anyone found a fix for searching through international characters using chosen.js?
for example if I have a multi-select field with the following options: - A French Château - An English Chateau
And I search for "Cha"
Only the english will show up.
Upvotes: 4
Views: 2537
Reputation: 305
I don't know, if it is not too late for answering, but it could help someone else probably.
The point is to strip diacritics from entered string and from matched option string during comparison. My modification is working with jquery Chosen plugin in version 1.1.0, downloaded from github.
First you have to have a function to strip diacritics (i've added it after winnow_results())
// strip czech diacritics from string
AbstractChosen.prototype.strip_diacritics= function(string) {
var
translationTable= [
// input with diacritics - add your characters if necessary
"éěÉĚřŘťŤžŽúÚůŮüÜíÍóÓáÁšŠďĎýÝčČňŇäÄĺĹľĽŕŔöÖ",
// stripped output
"eeEErRtTzZuUuUuUiIoOaAsSdDyYcCnNaAlLlLrRoO",
],
output= '';
// scan through whole string
for (var i= 0; i < string.length; i++) {
var charPosition= translationTable[0].indexOf(string[i]);
output+= charPosition == -1 ? string[i] : translationTable[1][charPosition];
}
return output;
}
Then use it in appropriate places in winnow_results() function. Referencing chosen.jquery.js lines:
line #315
searchText = this.get_search_text();
// replace with
searchText = this.strip_diacritics(this.get_search_text());
line #339
option.search_match = this.search_string_match(option.search_text, regex);
// replace with
option.search_match = this.search_string_match(this.strip_diacritics(option.search_text), regex);
and finally line #345
startpos = option.search_text.search(zregex);
// replace with
startpos = this.strip_diacritics(option.search_text).search(zregex);
And you're done :-).
(I feel like writing some "savegame byte replacement" instruction for extra lives in old DOS game)
Whole modified file at pastebin.
Sept 29th, 2016: Modifications made in Chosen 1.6.2, tested ok.
Upvotes: 6
Reputation:
It doesn't look as though Chosen does this by default - there's no functionality in the code for this.
The source code is here. I've posted the search function below, which is responsible for checking the characters. There's nothing in this function that deals with close characters like that, so you'd either have to write it or request that feature from the Chosen team. This is because, at the core, accented characters and non-accented characters don't have the same ASCII (or Unicode) values. You'd have to have some type of lookup table, and parse that for each character to return "fuzzy" results.
Sorry I couldn't be of more help. I'm sure if you could find a way to modify this function, you could get this working. Again, you'd need lookup tables or something for the underlying code values. Best of luck.
Edit: You may not need lookup tables - perhaps the Regex functionality has a built-in way to do this. Alternatively, you may be able to simply match on anything close to the letter you're searching for.
Chosen.prototype.winnow_results = function() {
var found, option, part, parts, regex, regexAnchor, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len1, _ref;
this.no_results_clear();
results = 0;
searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
regexAnchor = this.search_contains ? "" : "^";
regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
_ref = this.results_data;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
option = _ref[_i];
if (!option.disabled && !option.empty) {
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 (this.enable_split_word_search && (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0)) {
parts = option.html.replace(/\[|\]/g, "").split(" ");
if (parts.length) {
for (_j = 0, _len1 = parts.length; _j < _len1; _j++) {
part = parts[_j];
if (regex.test(part)) {
found = true;
results += 1;
}
}
}
}
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;
}
result.html(text);
this.result_activate(result);
if (option.group_array_index != null) {
$("#" + this.results_data[option.group_array_index].dom_id).css('display', 'list-item');
}
} else {
if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
this.result_clear_highlight();
}
this.result_deactivate(result);
}
}
}
}
if (results < 1 && searchText.length) {
return this.no_results(searchText);
} else {
return this.winnow_results_set_highlight();
}
};
Upvotes: 0