Add optgroup searching

search_improvements
Patrick Filler 2012-02-24 15:09:12 -05:00
parent 6a5d61b061
commit 3cae992311
7 changed files with 151 additions and 106 deletions

View File

@ -197,6 +197,30 @@ Copyright (c) 2011 by Harvest
} }
}; };
AbstractChosen.prototype.winnow_search_match = function(regex, optionText) {
var found, part, parts, _i, _len;
found = false;
if (regex.test(optionText)) {
found = true;
} else if (optionText.indexOf(" ") >= 0 || optionText.indexOf("[") === 0) {
parts = optionText.replace(/\[|\]/g, "").split(" ");
if (parts.length) {
for (_i = 0, _len = parts.length; _i < _len; _i++) {
part = parts[_i];
if (regex.test(part)) found = true;
}
}
}
return found;
};
AbstractChosen.prototype.winnow_search_highlight_match = function(regex, optionText, searchTextLength) {
var startpos, text;
startpos = optionText.search(regex);
text = optionText.substr(0, startpos + searchTextLength) + '</em>' + optionText.substr(startpos + searchTextLength);
return text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
};
AbstractChosen.prototype.keyup_checker = function(evt) { AbstractChosen.prototype.keyup_checker = function(evt) {
var stroke, _ref; var stroke, _ref;
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
@ -725,42 +749,26 @@ Copyright (c) 2011 by Harvest
}; };
Chosen.prototype.winnow_results = function() { Chosen.prototype.winnow_results = function() {
var found, option, part, parts, regex, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len2, _ref; var found, option, result, result_id, results, text, _i, _len, _ref;
this.no_results_clear(); this.no_results_clear();
results = 0; results = 0;
searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html(); this.searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); this.regex = new RegExp('^' + this.searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); this.zregex = new RegExp(this.searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
_ref = this.results_data; _ref = this.results_data;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
option = _ref[_i]; option = _ref[_i];
if (!option.disabled && !option.empty) { if (!option.disabled && !option.empty) {
if (option.group) { if (option.group) {
$('#' + option.dom_id).css('display', 'none'); if (this.winnow_option_group(option)) results += 1;
} else if (!(this.is_multiple && option.selected)) { } else if (!(this.is_multiple && option.selected)) {
found = false; found = this.winnow_search_match(this.regex, option.html);
if (found) results += 1;
result_id = option.dom_id; result_id = option.dom_id;
result = $("#" + result_id); result = $("#" + result_id);
if (regex.test(option.html)) { if (found || ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match)) {
found = true; if (this.searchText.length && found) {
results += 1; text = this.winnow_search_highlight_match(this.zregex, option.html, this.searchText.length);
} 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;
}
}
}
}
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 { } else {
text = option.html; text = option.html;
} }
@ -778,13 +786,22 @@ Copyright (c) 2011 by Harvest
} }
} }
} }
if (results < 1 && searchText.length) { if (results < 1 && this.searchText.length) {
return this.no_results(searchText); return this.no_results(this.searchText);
} else { } else {
return this.winnow_results_set_highlight(); return this.winnow_results_set_highlight();
} }
}; };
Chosen.prototype.winnow_option_group = function(group) {
var text;
$('#' + group.dom_id).css('display', 'none');
group.search_match = this.winnow_search_match(this.regex, group.label);
text = this.searchText.length && group.search_match ? this.winnow_search_highlight_match(this.zregex, group.label, this.searchText.length) : group.label;
$("#" + group.dom_id).html(text);
return group.search_match;
};
Chosen.prototype.winnow_results_clear = function() { Chosen.prototype.winnow_results_clear = function() {
var li, lis, _i, _len, _results; var li, lis, _i, _len, _results;
this.search_field.val(""); this.search_field.val("");

File diff suppressed because one or more lines are too long

View File

@ -197,6 +197,30 @@ Copyright (c) 2011 by Harvest
} }
}; };
AbstractChosen.prototype.winnow_search_match = function(regex, optionText) {
var found, part, parts, _i, _len;
found = false;
if (regex.test(optionText)) {
found = true;
} else if (optionText.indexOf(" ") >= 0 || optionText.indexOf("[") === 0) {
parts = optionText.replace(/\[|\]/g, "").split(" ");
if (parts.length) {
for (_i = 0, _len = parts.length; _i < _len; _i++) {
part = parts[_i];
if (regex.test(part)) found = true;
}
}
}
return found;
};
AbstractChosen.prototype.winnow_search_highlight_match = function(regex, optionText, searchTextLength) {
var startpos, text;
startpos = optionText.search(regex);
text = optionText.substr(0, startpos + searchTextLength) + '</em>' + optionText.substr(startpos + searchTextLength);
return text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
};
AbstractChosen.prototype.keyup_checker = function(evt) { AbstractChosen.prototype.keyup_checker = function(evt) {
var stroke, _ref; var stroke, _ref;
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
@ -726,41 +750,25 @@ Copyright (c) 2011 by Harvest
}; };
Chosen.prototype.winnow_results = function() { Chosen.prototype.winnow_results = function() {
var found, option, part, parts, regex, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len2, _ref; var found, option, result_id, results, text, _i, _len, _ref;
this.no_results_clear(); this.no_results_clear();
results = 0; results = 0;
searchText = this.search_field.value === this.default_text ? "" : this.search_field.value.strip().escapeHTML(); this.searchText = this.search_field.value === this.default_text ? "" : this.search_field.value.strip().escapeHTML();
regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); this.regex = new RegExp('^' + this.searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); this.zregex = new RegExp(this.searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
_ref = this.results_data; _ref = this.results_data;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
option = _ref[_i]; option = _ref[_i];
if (!option.disabled && !option.empty) { if (!option.disabled && !option.empty) {
if (option.group) { if (option.group) {
$(option.dom_id).hide(); if (this.winnow_option_group(option)) results += 1;
} else if (!(this.is_multiple && option.selected)) { } else if (!(this.is_multiple && option.selected)) {
found = false; found = this.winnow_search_match(this.regex, option.html);
if (found) results += 1;
result_id = option.dom_id; result_id = option.dom_id;
if (regex.test(option.html)) { if (found || ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match)) {
found = true; if (this.searchText.length && found) {
results += 1; text = this.winnow_search_highlight_match(this.zregex, option.html, this.searchText.length);
} 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;
}
}
}
}
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 { } else {
text = option.html; text = option.html;
} }
@ -780,13 +788,21 @@ Copyright (c) 2011 by Harvest
} }
} }
} }
if (results < 1 && searchText.length) { if (results < 1 && this.searchText.length) {
return this.no_results(searchText); return this.no_results(this.searchText);
} else { } else {
return this.winnow_results_set_highlight(); return this.winnow_results_set_highlight();
} }
}; };
Chosen.prototype.winnow_option_group = function(group) {
var text;
$("" + group.dom_id).hide();
group.search_match = this.winnow_search_match(this.regex, group.label);
text = this.searchText.length && group.search_match ? this.winnow_search_highlight_match(this.zregex, group.label, this.searchText.length) : group.label;
return $("" + group.dom_id).update(text);
};
Chosen.prototype.winnow_results_clear = function() { Chosen.prototype.winnow_results_clear = function() {
var li, lis, _i, _len, _results; var li, lis, _i, _len, _results;
this.search_field.clear(); this.search_field.clear();

File diff suppressed because one or more lines are too long

View File

@ -382,36 +382,24 @@ class Chosen extends AbstractChosen
results = 0 results = 0
searchText = if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html() @searchText = if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html()
regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i') @regex = new RegExp('^' + @searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i') @zregex = new RegExp(@searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
for option in @results_data for option in @results_data
if not option.disabled and not option.empty if not option.disabled and not option.empty
if option.group if option.group
$('#' + option.dom_id).css('display', 'none') results += 1 if this.winnow_option_group(option)
else if not (@is_multiple and option.selected) else if not (@is_multiple and option.selected)
found = false found = this.winnow_search_match(@regex, option.html)
results += 1 if found
result_id = option.dom_id result_id = option.dom_id
result = $("#" + result_id) result = $("#" + result_id)
if regex.test option.html
found = true
results += 1
else if option.html.indexOf(" ") >= 0 or option.html.indexOf("[") == 0
#TODO: replace this substitution of /\[\]/ with a list of characters to skip.
parts = option.html.replace(/\[|\]/g, "").split(" ")
if parts.length
for part in parts
if regex.test part
found = true
results += 1
if found if found or (option.group_array_index? && @results_data[option.group_array_index].search_match)
if searchText.length if @searchText.length and found
startpos = option.html.search zregex text = this.winnow_search_highlight_match(@zregex, option.html, @searchText.length)
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 else
text = option.html text = option.html
@ -423,10 +411,20 @@ class Chosen extends AbstractChosen
this.result_clear_highlight() if @result_highlight and result_id is @result_highlight.attr 'id' this.result_clear_highlight() if @result_highlight and result_id is @result_highlight.attr 'id'
this.result_deactivate result this.result_deactivate result
if results < 1 and searchText.length if results < 1 and @searchText.length
this.no_results searchText this.no_results @searchText
else else
this.winnow_results_set_highlight() this.winnow_results_set_highlight()
winnow_option_group: (group) ->
$('#' + group.dom_id).css('display', 'none')
group.search_match = this.winnow_search_match(@regex, group.label)
text = if @searchText.length and group.search_match then this.winnow_search_highlight_match(@zregex, group.label, @searchText.length) else group.label
$("##{group.dom_id}").html(text)
return group.search_match
winnow_results_clear: -> winnow_results_clear: ->
@search_field.val "" @search_field.val ""

View File

@ -373,35 +373,23 @@ class Chosen extends AbstractChosen
results = 0 results = 0
searchText = if @search_field.value is @default_text then "" else @search_field.value.strip().escapeHTML() @searchText = if @search_field.value is @default_text then "" else @search_field.value.strip().escapeHTML()
regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i') @regex = new RegExp('^' + @searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i') @zregex = new RegExp(@searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
for option in @results_data for option in @results_data
if not option.disabled and not option.empty if not option.disabled and not option.empty
if option.group if option.group
$(option.dom_id).hide() results += 1 if this.winnow_option_group(option)
else if not (@is_multiple and option.selected) else if not (@is_multiple and option.selected)
found = false found = this.winnow_search_match(@regex, option.html)
results += 1 if found
result_id = option.dom_id result_id = option.dom_id
if regex.test option.html if found or (option.group_array_index? && @results_data[option.group_array_index].search_match)
found = true if @searchText.length and found
results += 1 text = this.winnow_search_highlight_match(@zregex, option.html, @searchText.length)
else if option.html.indexOf(" ") >= 0 or option.html.indexOf("[") == 0
#TODO: replace this substitution of /\[\]/ with a list of characters to skip.
parts = option.html.replace(/\[|\]/g, "").split(" ")
if parts.length
for part in parts
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 else
text = option.html text = option.html
@ -414,11 +402,19 @@ class Chosen extends AbstractChosen
this.result_clear_highlight() if $(result_id) is @result_highlight this.result_clear_highlight() if $(result_id) is @result_highlight
this.result_deactivate $(result_id) this.result_deactivate $(result_id)
if results < 1 and searchText.length if results < 1 and @searchText.length
this.no_results(searchText) this.no_results(@searchText)
else else
this.winnow_results_set_highlight() this.winnow_results_set_highlight()
winnow_option_group: (group) ->
$("#{group.dom_id}").hide()
group.search_match = this.winnow_search_match(@regex, group.label)
text = if @searchText.length and group.search_match then this.winnow_search_highlight_match(@zregex, group.label, @searchText.length) else group.label
$("#{group.dom_id}").update(text)
winnow_results_clear: -> winnow_results_clear: ->
@search_field.clear() @search_field.clear()
lis = @search_results.select("li") lis = @search_results.select("li")

View File

@ -75,6 +75,24 @@ class AbstractChosen
else else
this.results_show() this.results_show()
winnow_search_match: (regex, optionText) ->
found = false
if regex.test optionText
found = true
else if optionText.indexOf(" ") >= 0 or optionText.indexOf("[") == 0
#TODO: replace this substitution of /\[\]/ with a list of characters to skip.
parts = optionText.replace(/\[|\]/g, "").split(" ")
if parts.length
for part in parts
if regex.test part
found = true
return found
winnow_search_highlight_match: (regex, optionText, searchTextLength) ->
startpos = optionText.search regex
text = optionText.substr(0, startpos + searchTextLength) + '</em>' + optionText.substr(startpos + searchTextLength)
text = text.substr(0, startpos) + '<em>' + text.substr(startpos)
keyup_checker: (evt) -> keyup_checker: (evt) ->
stroke = evt.which ? evt.keyCode stroke = evt.which ? evt.keyCode
this.search_field_scale() this.search_field_scale()