Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/multibyte-characters'
Browse files Browse the repository at this point in the history
  • Loading branch information
adunkman committed Sep 5, 2017
2 parents 538a832 + fb6e071 commit 497c427
Show file tree
Hide file tree
Showing 3 changed files with 356 additions and 2 deletions.
6 changes: 4 additions & 2 deletions coffee/lib/abstract-chosen.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
173 changes: 173 additions & 0 deletions spec/jquery/searching.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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 <span>&amp;amp;</span>")

it "matches in non-ascii languages like Chinese when selecting a single item", ->
div = $("<div>").html("""
<select>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")

it "matches in non-ascii languages like Chinese when selecting a single item with search_contains", ->
div = $("<div>").html("""
<select>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")
expect(div.find(".active-result")[1].innerHTML).toBe("十<em>一</em>")

it "matches in non-ascii languages like Chinese when selecting multiple items", ->
div = $("<div>").html("""
<select multiple>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")

it "matches in non-ascii languages like Chinese when selecting multiple items with search_contains", ->
div = $("<div>").html("""
<select multiple>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")
expect(div.find(".active-result")[1].innerHTML).toBe("十<em>一</em>")

it "highlights results correctly when multiple words are present", ->
div = $("<div>").html("""
<select>
<option value="oh hello">oh hello</option>
</select>
""")

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 <em>h</em>ello")

describe "respects word boundaries when not using search_contains", ->
div = $("<div>").html("""
<select>
<option value="(lparen">(lparen</option>
<option value="&lt;langle">&lt;langle</option>
<option value="[lbrace">[lbrace</option>
<option value="{lcurly">{lcurly</option>
<option value="¡upsidedownbang">¡upsidedownbang</option>
<option value="¿upsidedownqmark">¿upsidedownqmark</option>
<option value=".period">.period</option>
<option value="-dash">-dash</option>
<option value='"leftquote'>"leftquote</option>
<option value="'leftsinglequote">'leftsinglequote</option>
<option value="“angledleftquote">“angledleftquote</option>
<option value="‘angledleftsinglequote">‘angledleftsinglequote</option>
<option value="«guillemet">«guillemet</option>
</select>
""")

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)
179 changes: 179 additions & 0 deletions spec/proto/searching.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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 <span>&amp;amp;</span>")

it "matches in non-ascii languages like Chinese when selecting a single item", ->
div = new Element("div")
div.update("""
<select>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")

it "matches in non-ascii languages like Chinese when selecting a single item with search_contains", ->
div = new Element("div")
div.update("""
<select>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")
expect(div.select(".active-result")[1].innerHTML).toBe("十<em>一</em>")

it "matches in non-ascii languages like Chinese when selecting multiple items", ->
div = new Element("div")
div.update("""
<select multiple>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")

it "matches in non-ascii languages like Chinese when selecting multiple items with search_contains", ->
div = new Element("div")
div.update("""
<select multiple>
<option value="一">一</option>
<option value="二">二</option>
<option value="三">三</option>
<option value="四">四</option>
<option value="五">五</option>
<option value="六">六</option>
<option value="七">七</option>
<option value="八">八</option>
<option value="九">九</option>
<option value="十">十</option>
<option value="十一">十一</option>
<option value="十二">十二</option>
</select>
""")

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("<em>一</em>")
expect(div.select(".active-result")[1].innerHTML).toBe("十<em>一</em>")

it "highlights results correctly when multiple words are present", ->
div = new Element("div")
div.update("""
<select>
<option value="oh hello">oh hello</option>
</select>
""")

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 <em>h</em>ello")

describe "respects word boundaries when not using search_contains", ->
div = new Element("div")
div.update("""
<select>
<option value="(lparen">(lparen</option>
<option value="&lt;langle">&lt;langle</option>
<option value="[lbrace">[lbrace</option>
<option value="{lcurly">{lcurly</option>
<option value="¡upsidedownbang">¡upsidedownbang</option>
<option value="¿upsidedownqmark">¿upsidedownqmark</option>
<option value=".period">.period</option>
<option value="-dash">-dash</option>
<option value='"leftquote'>"leftquote</option>
<option value="'leftsinglequote">'leftsinglequote</option>
<option value="“angledleftquote">“angledleftquote</option>
<option value="‘angledleftsinglequote">‘angledleftsinglequote</option>
<option value="«guillemet">«guillemet</option>
</select>
""")

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)

0 comments on commit 497c427

Please # to comment.