Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go Go Go Go Chosen (Chosen gets a speed boost) #1339

Merged
merged 31 commits into from
Jul 10, 2013
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2966118
Try building a giant html block and see how speed is affected.
pfiller Jun 3, 2013
75a2292
Merge branch 'master' into the-need-for-speed
pfiller Jun 17, 2013
1a3850c
Merge branch 'master' into the-need-for-speed
pfiller Jun 26, 2013
3750502
Make sure selected elements get flagged on build
pfiller Jun 26, 2013
d8b7ba7
Remove a bogus console call.
pfiller Jun 26, 2013
ff66c28
Merge branch 'master' into the-need-for-speed
pfiller Jun 26, 2013
99f5a1b
Remove a bunch of unused winnow code
pfiller Jun 26, 2013
79b2af6
Remove result_activate & result_deactivate functions
pfiller Jun 26, 2013
e662ca0
Always set the result highlight after results are winnowed.
pfiller Jul 2, 2013
665224a
Group results should be visible like any other search result.
pfiller Jul 2, 2013
675c17b
Clear search results area if no results are found.
pfiller Jul 2, 2013
a5ead6d
Rely on an option's search_match value instead of creating a
pfiller Jul 2, 2013
29f9337
After deselecting a multilpe option, winnow the results only if
pfiller Jul 2, 2013
2ff7390
Search multiple options even if they are selected.
pfiller Jul 2, 2013
d82d344
Move search text value conditional out of winnow_results
pfiller Jul 2, 2013
3d6173a
Always set selected text and classes in a method.
pfiller Jul 2, 2013
b5ce559
Move single single_deselect_control_build into
pfiller Jul 2, 2013
671147f
Move results_option_build function into AbstractChosen
pfiller Jul 2, 2013
0aef565
Add single_set_selected method outlined in
pfiller Jul 2, 2013
47b4078
Merge branch 'master' into the-need-for-speed
pfiller Jul 2, 2013
dc094da
Refactor results_option_build to return content instead of
pfiller Jul 2, 2013
7ae2325
Update results_build to use new content building function
pfiller Jul 2, 2013
2c68aa8
Add a get_search_text method to the Prototype version
pfiller Jul 2, 2013
1a7cd9e
Use an abstracted function for setting search results content.
pfiller Jul 2, 2013
542554e
Make update_results_content availabel in Prototype version
pfiller Jul 2, 2013
2bc288d
winnow_results is now framework independent. Move it to Abstract
pfiller Jul 2, 2013
89e584c
result_activate and result_deactivate are no longer needed
pfiller Jul 2, 2013
6821232
Always set result highlight after winnowing search results.
pfiller Jul 2, 2013
c35b81e
Only winnow results after deselct if results are showing.
pfiller Jul 2, 2013
95daa8a
Merge branch 'master' into the-need-for-speed
pfiller Jul 8, 2013
d741861
Triple quotes allow for string interpolation
pfiller Jul 10, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 19 additions & 82 deletions coffee/chosen.jquery.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -166,31 +166,20 @@ class Chosen extends AbstractChosen
if @is_multiple
@search_choices.find("li.search-choice").remove()
else if not @is_multiple
@selected_item.addClass("chzn-default").find("span").text(@default_text)
this.single_set_selected_text()
if @disable_search or @form_field.options.length <= @disable_search_threshold
@search_field[0].readOnly = true
@container.addClass "chzn-container-single-nosearch"
else
@search_field[0].readOnly = false
@container.removeClass "chzn-container-single-nosearch"

content = ''
for data in @results_data
if data.group
content += this.result_add_group data
else if !data.empty
content += this.result_add_option data
if data.selected and @is_multiple
this.choice_build data
else if data.selected and not @is_multiple
@selected_item.removeClass("chzn-default").find("span").text data.text
this.single_deselect_control_build() if @allow_single_deselect
this.update_results_content this.results_option_build({first:true})

this.search_field_disabled()
this.show_search_field_default()
this.search_field_scale()

@search_results.html content
@parsing = false

result_add_group: (group) ->
Expand Down Expand Up @@ -235,6 +224,9 @@ class Chosen extends AbstractChosen

this.winnow_results()

update_results_content: (content) ->
@search_results.html content

results_hide: ->
if @results_showing
this.result_clear_highlight()
Expand Down Expand Up @@ -311,8 +303,7 @@ class Chosen extends AbstractChosen
results_reset: ->
@form_field.options[0].selected = true
@selected_option_count = null
@selected_item.find("span").text @default_text
@selected_item.addClass("chzn-default") if not @is_multiple
this.single_set_selected_text()
this.show_search_field_default()
this.results_reset_cleanup()
@form_field_jq.trigger "change"
Expand All @@ -338,7 +329,6 @@ class Chosen extends AbstractChosen
else
@search_results.find(".result-selected").removeClass "result-selected"
@result_single_selected = high
@selected_item.removeClass("chzn-default")

high.addClass "result-selected"

Expand All @@ -352,8 +342,7 @@ class Chosen extends AbstractChosen
if @is_multiple
this.choice_build item
else
@selected_item.find("span").first().text item.text
this.single_deselect_control_build() if @allow_single_deselect
this.single_set_selected_text(item.text)

this.results_hide() unless (evt.metaKey or evt.ctrlKey) and @is_multiple

Expand All @@ -363,16 +352,14 @@ class Chosen extends AbstractChosen
@current_selectedIndex = @form_field.selectedIndex
this.search_field_scale()

result_activate: (el, option) ->
if option.disabled
el.addClass("disabled-result")
else if @is_multiple and option.selected
el.addClass("result-selected")
single_set_selected_text: (text=@default_text) ->
if text is @default_text
@selected_item.addClass("chzn-default")
else
el.addClass("active-result")
this.single_deselect_control_build()
@selected_item.removeClass("chzn-default")

result_deactivate: (el) ->
el.removeClass("active-result result-selected disabled-result")
@selected_item.find("span").text(text)

result_deselect: (pos) ->
result_data = @results_data[pos]
Expand All @@ -387,7 +374,7 @@ class Chosen extends AbstractChosen
result.removeClass("result-selected").addClass("active-result").show()

this.result_clear_highlight()
this.winnow_results()
this.winnow_results() if @results_showing

@form_field_jq.trigger "change", {deselected: @form_field.options[result_data.options_index].value}
this.search_field_scale()
Expand All @@ -401,65 +388,15 @@ class Chosen extends AbstractChosen
@selected_item.find("span").first().after "<abbr class=\"search-choice-close\"></abbr>" unless @selected_item.find("abbr").length
@selected_item.addClass("chzn-single-with-deselect")

winnow_results: ->
this.no_results_clear()

results = 0

searchText = if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html()
regexAnchor = if @search_contains then "" else "^"
regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')

for option in @results_data
if not option.empty
if option.group
$('#' + option.dom_id).css('display', 'none')
else
found = false
result_id = option.dom_id
result = $("#" + result_id)

if regex.test option.html
found = true
results += 1
else if @enable_split_word_search and (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
text = option.html

result.html(text)
this.result_activate result, option

$("#" + @results_data[option.group_array_index].dom_id).css('display', 'list-item') if option.group_array_index?
else
this.result_clear_highlight() if @result_highlight and result_id is @result_highlight.attr 'id'
this.result_deactivate result

if results < 1 and searchText.length
this.no_results searchText
else
this.winnow_results_set_highlight()
get_search_text: ->
if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html()

winnow_results_set_highlight: ->
if not @result_highlight

selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()
selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()

this.result_do_highlight do_high if do_high?
this.result_do_highlight do_high if do_high?

no_results: (terms) ->
no_results_html = $('<li class="no-results">' + @results_none_found + ' "<span></span>"</li>')
Expand Down
108 changes: 21 additions & 87 deletions coffee/chosen.proto.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -154,31 +154,20 @@ class Chosen extends AbstractChosen
if @is_multiple
@search_choices.select("li.search-choice").invoke("remove")
else if not @is_multiple
@selected_item.addClassName("chzn-default").down("span").update(@default_text)
this.single_set_selected_text()
if @disable_search or @form_field.options.length <= @disable_search_threshold
@search_field.readOnly = true
@container.addClassName "chzn-container-single-nosearch"
else
@search_field.readOnly = false
@container.removeClassName "chzn-container-single-nosearch"

content = ''
for data in @results_data
if data.group
content += this.result_add_group data
else if !data.empty
content += this.result_add_option data
if data.selected and @is_multiple
this.choice_build data
else if data.selected and not @is_multiple
@selected_item.removeClassName("chzn-default").down("span").update( data.html )
this.single_deselect_control_build() if @allow_single_deselect
this.update_results_content this.results_option_build({first:true})

this.search_field_disabled()
this.show_search_field_default()
this.search_field_scale()

@search_results.update content
@parsing = false

result_add_group: (group) ->
Expand Down Expand Up @@ -222,6 +211,9 @@ class Chosen extends AbstractChosen

this.winnow_results()

update_results_content: (content) ->
@search_results.update content

results_hide: ->
if @results_showing
this.result_clear_highlight()
Expand Down Expand Up @@ -298,8 +290,7 @@ class Chosen extends AbstractChosen
results_reset: ->
@form_field.options[0].selected = true
@selected_option_count = null
@selected_item.down("span").update(@default_text)
@selected_item.addClassName("chzn-default") if not @is_multiple
this.single_set_selected_text()
this.show_search_field_default()
this.results_reset_cleanup()
@form_field.simulate("change") if typeof Event.simulate is 'function'
Expand All @@ -323,7 +314,6 @@ class Chosen extends AbstractChosen
high.removeClassName("active-result")
else
@search_results.descendants(".result-selected").invoke "removeClassName", "result-selected"
@selected_item.removeClassName("chzn-default")
@result_single_selected = high

high.addClassName("result-selected")
Expand All @@ -338,8 +328,7 @@ class Chosen extends AbstractChosen
if @is_multiple
this.choice_build item
else
@selected_item.down("span").update(item.html)
this.single_deselect_control_build() if @allow_single_deselect
this.single_set_selected_text(item.text)

this.results_hide() unless (evt.metaKey or evt.ctrlKey) and @is_multiple

Expand All @@ -350,18 +339,14 @@ class Chosen extends AbstractChosen

this.search_field_scale()

result_activate: (el, option) ->
if option.disabled
el.addClassName("disabled-result")
else if @is_multiple and option.selected
el.addClassName("result-selected")
single_set_selected_text: (text=@default_text) ->
if text is @default_text
@selected_item.addClassName("chzn-default")
else
el.addClassName("active-result")
this.single_deselect_control_build()
@selected_item.removeClassName("chzn-default")

result_deactivate: (el) ->
el.removeClassName("active-result")
el.removeClassName("result-selected")
el.removeClassName("disabled-result")
@selected_item.down("span").update(text)

result_deselect: (pos) ->
result_data = @results_data[pos]
Expand All @@ -376,7 +361,7 @@ class Chosen extends AbstractChosen
result.removeClassName("result-selected").addClassName("active-result").show()

this.result_clear_highlight()
this.winnow_results()
this.winnow_results() if @results_showing

@form_field.simulate("change") if typeof Event.simulate is 'function'
this.search_field_scale()
Expand All @@ -389,68 +374,17 @@ class Chosen extends AbstractChosen
@selected_item.down("span").insert { after: "<abbr class=\"search-choice-close\"></abbr>" } unless @selected_item.down("abbr")
@selected_item.addClassName("chzn-single-with-deselect")

winnow_results: ->
this.no_results_clear()

results = 0

searchText = if @search_field.value is @default_text then "" else @search_field.value.strip().escapeHTML()
regexAnchor = if @search_contains then "" else "^"
regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')

for option in @results_data
if not option.empty
if option.group
$(option.dom_id).hide()
else
found = false
result_id = option.dom_id

if regex.test option.html
found = true
results += 1
else if @enable_split_word_search and (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
text = option.html

$(result_id).update text if $(result_id).innerHTML != text

this.result_activate $(result_id), option

$(@results_data[option.group_array_index].dom_id).setStyle({display: 'list-item'}) if option.group_array_index?
else
this.result_clear_highlight() if $(result_id) is @result_highlight
this.result_deactivate $(result_id)

if results < 1 and searchText.length
this.no_results(searchText)
else
this.winnow_results_set_highlight()
get_search_text: ->
if @search_field.value is @default_text then "" else @search_field.value.strip().escapeHTML()

winnow_results_set_highlight: ->
if not @result_highlight

if not @is_multiple
do_high = @search_results.down(".result-selected.active-result")
if not @is_multiple
do_high = @search_results.down(".result-selected.active-result")

if not do_high?
do_high = @search_results.down(".active-result")
if not do_high?
do_high = @search_results.down(".active-result")

this.result_do_highlight do_high if do_high?
this.result_do_highlight do_high if do_high?

no_results: (terms) ->
@search_results.insert @no_results_temp.evaluate( terms: terms )
Expand Down
Loading