diff --git a/coffee/lib/abstract-chosen.coffee b/coffee/lib/abstract-chosen.coffee index 4bc24dc7bda..b42391f0104 100644 --- a/coffee/lib/abstract-chosen.coffee +++ b/coffee/lib/abstract-chosen.coffee @@ -217,13 +217,15 @@ class AbstractChosen this.winnow_results_set_highlight() get_search_regex: (escaped_search_string) -> - regex_string = if @search_contains then escaped_search_string else "\\b#{escaped_search_string}\\w*\\b" + regex_string = if @search_contains then escaped_search_string else "(^|\\s|\\b)#{escaped_search_string}[^\\s]*" regex_string = "^#{regex_string}" unless @enable_split_word_search or @search_contains regex_flag = if @case_sensitive_search then "" else "i" new RegExp(regex_string, regex_flag) search_string_match: (search_string, regex) -> - regex.exec(search_string) + match = regex.exec(search_string) + match.index += 1 if !@search_contains && match?[1] # make up for lack of lookbehind operator in regex + match choices_count: -> return @selected_option_count if @selected_option_count? diff --git a/spec/jquery/searching.spec.coffee b/spec/jquery/searching.spec.coffee index 8a138d354f1..7368ad8378b 100644 --- a/spec/jquery/searching.spec.coffee +++ b/spec/jquery/searching.spec.coffee @@ -91,3 +91,176 @@ describe "Searching", -> expect(div.find(".no-results").length).toBe(1) expect(div.find(".no-results").first().html().trim()).toBe("No results match &") + + it "matches in non-ascii languages like Chinese when selecting a single item", -> + div = $("
").html(""" + + """) + + div.find("select").chosen() + div.find(".chosen-container").trigger("mousedown") # open the drop + + expect(div.find(".active-result").length).toBe(12) + + search_field = div.find(".chosen-search-input").first() + search_field.val("一") + search_field.trigger("keyup") + + expect(div.find(".active-result").length).toBe(1) + expect(div.find(".active-result")[0].innerHTML).toBe("") + + it "matches in non-ascii languages like Chinese when selecting a single item with search_contains", -> + div = $("
").html(""" + + """) + + div.find("select").chosen({search_contains: true}) + div.find(".chosen-container").trigger("mousedown") # open the drop + + expect(div.find(".active-result").length).toBe(12) + + search_field = div.find(".chosen-search-input").first() + search_field.val("一") + search_field.trigger("keyup") + + expect(div.find(".active-result").length).toBe(2) + expect(div.find(".active-result")[0].innerHTML).toBe("") + expect(div.find(".active-result")[1].innerHTML).toBe("十") + + it "matches in non-ascii languages like Chinese when selecting multiple items", -> + div = $("
").html(""" + + """) + + div.find("select").chosen() + div.find(".chosen-container").trigger("mousedown") # open the drop + + expect(div.find(".active-result").length).toBe(12) + + search_field = div.find(".chosen-search-input") + search_field.val("一") + search_field.trigger("keyup") + + expect(div.find(".active-result").length).toBe(1) + expect(div.find(".active-result")[0].innerHTML).toBe("") + + it "matches in non-ascii languages like Chinese when selecting multiple items with search_contains", -> + div = $("
").html(""" + + """) + + div.find("select").chosen({search_contains: true}) + div.find(".chosen-container").trigger("mousedown") # open the drop + + expect(div.find(".active-result").length).toBe(12) + + search_field = div.find(".chosen-search-input") + search_field.val("一") + search_field.trigger("keyup") + + expect(div.find(".active-result").length).toBe(2) + expect(div.find(".active-result")[0].innerHTML).toBe("") + expect(div.find(".active-result")[1].innerHTML).toBe("十") + + it "highlights results correctly when multiple words are present", -> + div = $("
").html(""" + + """) + + div.find("select").chosen() + div.find(".chosen-container").trigger("mousedown") # open the drop + + expect(div.find(".active-result").length).toBe(1) + + search_field = div.find(".chosen-search-input") + search_field.val("h") + search_field.trigger("keyup") + + expect(div.find(".active-result").length).toBe(1) + expect(div.find(".active-result")[0].innerHTML).toBe("oh hello") + + describe "respects word boundaries when not using search_contains", -> + div = $("
").html(""" + + """) + + div.find("select").chosen() + div.find(".chosen-container").trigger("mousedown") # open the drop + + search_field = div.find(".chosen-search-input") + + div.find("option").each () -> + boundary_thing = this.value.slice(1) + it "correctly finds words that start after a(n) #{boundary_thing}", -> + search_field.val(boundary_thing) + search_field.trigger("keyup") + expect(div.find(".active-result").length).toBe(1) + expect(div.find(".active-result")[0].innerText.slice(1)).toBe(boundary_thing) diff --git a/spec/proto/searching.spec.coffee b/spec/proto/searching.spec.coffee index 497ebb0692b..7e20741aac2 100644 --- a/spec/proto/searching.spec.coffee +++ b/spec/proto/searching.spec.coffee @@ -96,3 +96,182 @@ describe "Searching", -> expect(div.select(".no-results").length).toBe(1) expect(div.down(".no-results").innerHTML.trim()).toBe("No results match &") + + it "matches in non-ascii languages like Chinese when selecting a single item", -> + div = new Element("div") + div.update(""" + + """) + + new Chosen(div.down("select")) + simulant.fire(div.down(".chosen-container"), "mousedown") # open the drop + + expect(div.select(".active-result").length).toBe(12) + + search_field = div.down(".chosen-search-input") + search_field.value = "一" + simulant.fire(search_field, "keyup") + + expect(div.select(".active-result").length).toBe(1) + expect(div.select(".active-result")[0].innerHTML).toBe("") + + it "matches in non-ascii languages like Chinese when selecting a single item with search_contains", -> + div = new Element("div") + div.update(""" + + """) + + new Chosen(div.down("select"), {search_contains: true}) + simulant.fire(div.down(".chosen-container"), "mousedown") # open the drop + + expect(div.select(".active-result").length).toBe(12) + + search_field = div.down(".chosen-search-input") + search_field.value = "一" + simulant.fire(search_field, "keyup") + + expect(div.select(".active-result").length).toBe(2) + expect(div.select(".active-result")[0].innerHTML).toBe("") + expect(div.select(".active-result")[1].innerHTML).toBe("十") + + it "matches in non-ascii languages like Chinese when selecting multiple items", -> + div = new Element("div") + div.update(""" + + """) + + new Chosen(div.down("select")) + simulant.fire(div.down(".chosen-container"), "mousedown") # open the drop + + expect(div.select(".active-result").length).toBe(12) + + search_field = div.down(".chosen-search-input") + search_field.value = "一" + simulant.fire(search_field, "keyup") + + expect(div.select(".active-result").length).toBe(1) + expect(div.select(".active-result")[0].innerHTML).toBe("") + + it "matches in non-ascii languages like Chinese when selecting multiple items with search_contains", -> + div = new Element("div") + div.update(""" + + """) + + new Chosen(div.down("select"), {search_contains: true}) + simulant.fire(div.down(".chosen-container"), "mousedown") # open the drop + + expect(div.select(".active-result").length).toBe(12) + + search_field = div.down(".chosen-search-input") + search_field.value = "一" + simulant.fire(search_field, "keyup") + + expect(div.select(".active-result").length).toBe(2) + expect(div.select(".active-result")[0].innerHTML).toBe("") + expect(div.select(".active-result")[1].innerHTML).toBe("十") + + it "highlights results correctly when multiple words are present", -> + div = new Element("div") + div.update(""" + + """) + + new Chosen(div.down("select")) + simulant.fire(div.down(".chosen-container"), "mousedown") # open the drop + + expect(div.select(".active-result").length).toBe(1) + + search_field = div.down(".chosen-search-input") + search_field.value = "h" + simulant.fire(search_field, "keyup") + + expect(div.select(".active-result").length).toBe(1) + expect(div.select(".active-result")[0].innerHTML).toBe("oh hello") + + describe "respects word boundaries when not using search_contains", -> + div = new Element("div") + div.update(""" + + """) + + new Chosen(div.down("select")) + simulant.fire(div.down(".chosen-container"), "mousedown") # open the drop + + search_field = div.down(".chosen-search-input") + + div.select("option").forEach (option) -> + boundary_thing = option.value.slice(1) + it "correctly finds words that start after a(n) #{boundary_thing}", -> + search_field.value = boundary_thing + simulant.fire(search_field, "keyup") + expect(div.select(".active-result").length).toBe(1) + expect(div.select(".active-result")[0].innerText.slice(1)).toBe(boundary_thing)