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

Tweaks #55

Merged
merged 5 commits into from
Mar 10, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 6 additions & 9 deletions lib/ajax-chosen.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 5 additions & 6 deletions lib/ajax-chosen.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 27 additions & 27 deletions src/ajax-chosen.coffee
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
do ($ = jQuery) ->

$.fn.ajaxChosen = (settings = {}, callback = {}, chosenOptions = ->) ->
$.fn.ajaxChosen = (settings = {}, callback, chosenOptions = {}) ->
defaultOptions =
minTermLength: 3
afterTypeDelay: 500
Expand All @@ -10,17 +10,17 @@ do ($ = jQuery) ->

# This will come in handy later.
select = @

chosenXhr = null

# Merge options with defaults
options = $.extend {}, defaultOptions, $(select).data(), settings

# Load chosen. To make things clear, I have taken the liberty
# of using the .chzn-autoselect class to specify input elements
# we want to use with ajax autocomplete.
@chosen(if chosenOptions then chosenOptions else {})

@each ->
# Now that chosen is loaded normally, we can bootstrap it with
# our ajax autocomplete code.
Expand All @@ -29,7 +29,7 @@ do ($ = jQuery) ->
.bind 'keyup', ->
# This code will be executed every time the user types a letter
# into the input form that chosen has created

# Retrieve the current value of the input form
untrimmed_val = $(@).val()
val = $.trim $(@).val()
Expand All @@ -38,61 +38,61 @@ do ($ = jQuery) ->
# if they need to keep typing or if we are looking for their data
msg = if val.length < options.minTermLength then options.keepTypingMsg else options.lookingForMsg + " '#{val}'"
select.next('.chzn-container').find('.no-results').text(msg)

# If input text has not changed ... do nothing
return false if val is $(@).data('prevVal')

# Set the current search term so we don't execute the ajax call if
# the user hits a key that isn't an input letter/number/symbol
$(@).data('prevVal', val)

# At this point, we have a new term/query ... the old timer
# is no longer valid. Clear it.

# We delay searches by a small amount so that we don't flood the
# server with ajax requests.
clearTimeout(@timer) if @timer

# Some simple validation so we don't make excess ajax calls. I am
# assuming you don't want to perform a search with less than 3
# characters.
return false if val.length < options.minTermLength

# This is a useful reference for later
field = $(@)

# Default term key is `term`. Specify alternative in options.options.jsonTermKey
options.data = {} if not options.data?
options.data = {} unless options.data?
options.data[options.jsonTermKey] = val
options.data = options.dataCallback(options.data) if options.dataCallback?
options.data = options.dataCallback(options.data) if options.dataCallback?

# If the user provided an ajax success callback, store it so we can
# call it after our bootstrapping is finished.
success = options.success

# Create our own callback that will be executed when the ajax call is
# finished.
options.success = (data) ->
# Exit if the data we're given is invalid
return if not data?
return unless data?

# Go through all of the <option> elements in the <select> and remove
# ones that have not been selected by the user. For those selected
# by the user, add them to a list to filter from the results later.
selected_values = []
select.find('option').each ->
select.find('option').each ->
if not $(@).is(":selected")
$(@).remove()
else
selected_values.push $(@).val() + "-" + $(@).text()
select.find('optgroup:empty').each ->
$(@).remove()


# Send the ajax results to the user callback so we can get an object of
# value => text pairs to inject as <option> elements.
items = callback data
items = if callback? then callback(data, field) else data


nbItems = 0

Expand Down Expand Up @@ -142,7 +142,7 @@ do ($ = jQuery) ->
select.data().chosen.no_results field.val()

# Finally, call the user supplied callback (if it exists)
success(data) if success?
settings.success(data) if settings.success?

# For some reason, the contents of the input field get removed once you
# call trigger above. Often, this can be very annoying (and can make some
Expand All @@ -151,19 +151,19 @@ do ($ = jQuery) ->
field.val(untrimmed_val)

# Because non-ajax Chosen isn't constantly re-building results, when it
# DOES rebuild results (during liszt:updated above, it clears the input
# search field before scaling it. This causes the input field width to be
# at it's minimum, which is about 25px.
# DOES rebuild results (during liszt:updated above, it clears the input
# search field before scaling it. This causes the input field width to be
# at it's minimum, which is about 25px.

# The proper way to fix this would be create a new method in chosen for
# rebuilding results without clearing the input field. Or to call
# rebuilding results without clearing the input field. Or to call
# Chosen.search_field_scale() after resetting the value above. This isn't
# possible with the current state of Chosen. The quick fix is to simply reset
# the width of the field after we reset the value of the input text.
# field.css('width','auto')

# Execute the ajax call to search for autocomplete data with a timer
@timer = setTimeout ->
@timer = setTimeout ->
chosenXhr.abort() if chosenXhr
chosenXhr = $.ajax(options)
, options.afterTypeDelay