(($, window, document) ->
$this = undefined
# default settings
_settings =
default: 'cool!'
_remover = $("")
_adder = $("")
# This is your public API (no leading underscore, see?)
# All public methods must return $this so your plugin is chainable.
methods =
init: (options) ->
$this = $(@)
# The settings object is available under its name: _settings. Let's
# expand it with any custom options the user provided.
$.extend _settings, (options or {})
# Do anything that actually inits your plugin, if needed, right now!
# An important thing to keep in mind, is that jQuery plugins should be
# built so that one can apply them to more than one element, like so:
#
# $('.matching-elements, #another-one').foobar()
#
#This code sets up all the "Add" and "Remove" buttons for the autocomplete fields.
#For each autocomplete set on the page, add the "Add" and "Remove" buttons
$this.each (index, el) ->
$('.autocomplete-groups').each (index, el) ->
_internals.autocompleteGroups(el)
#Make sure these buttons have unique id's
_adder.id = "adder_" + index
_remover.id = "remover_" + index
#Add the "Remove" button
$('.field-wrapper:not(:last-child) .field-controls', this).append(_remover.clone())
#Add the "Add" button
$('.field-controls:last', this).append(_adder.clone())
#Bind the buttons to onClick events
$(el).on 'click', 'button.add', (e) ->
_internals.addToList(this)
$(el).on 'click', 'button.remove', (e) ->
_internals.removeFromList(this)
return $this
# This method is often overlooked.
destroy: ->
# Do anything to clean it up (nullify references, unbind events…).
return $this
_internals =
addToList: (el) ->
$activeControls = $(el).closest('.field-controls')
$listing = $activeControls.closest('.listing')
$('.add', $activeControls).remove()
$removeControl = _remover.clone()
$activeControls.prepend($removeControl)
_internals.newRow($listing, el)
false
newRow: ($listing, el) ->
$listing.append _internals.newListItem($('li', $listing).size(), $listing, el)
_internals.autocompleteGroups($('.autocomplete-groups:last', $listing))
removeFromList: (el) ->
$currentGroup = $(el).closest('li')
$listing = $currentGroup.closest('.listing')
$currentGroup.hide()
# set the destroy flag
$('input:not([value])', $currentGroup).val('true')
false
newListItem: (index, el) ->
## We have multiple places in a view where we need these autocomplete fields
## (Work edit view for example), so we don't want to use the first #entry-template.
## Using .closest isn't working, but this seems to for now.
source = $(el).parent().children().html()
template = Handlebars.compile(source)
template({index: index})
addExistingGroup: ($listItem, value, label) ->
source = $listItem.parent().prev().html()
template = Handlebars.compile(source)
$list = $listItem.closest('ul')
$('input[required]', $list).removeAttr('required')
$listItem.replaceWith template({index: $('li', $list).index($listItem), value: value, label: label})
_internals.newRow($list)
autocompleteGroups: (el) ->
$targetElement = $(el)
$targetElement.autocomplete
source: (request, response) ->
$targetElement.data('url')
$.getJSON $targetElement.data('url'), { q: request.term + "*" }, ( data, status, xhr ) ->
matches = []
$.each data.response.docs, (idx, val) ->
matches.push {label: val['desc_metadata__title_tesim'][0], value: val['id']}
response( matches )
minLength: 2
focus: ( event, ui ) ->
$targetElement.val(ui.item.label)
event.preventDefault()
select: ( event, ui ) ->
_internals.addExistingGroup($targetElement.closest('li'), ui.item.value, ui.item.label)
$targetElement.val('')
event.preventDefault()
$.fn.linkGroups = (method) ->
if methods[method]
methods[method].apply this, Array::slice.call(arguments, 1)
else if typeof method is "object" or not method
methods.init.apply this, arguments
else
$.error "Method " + method + " does not exist on jquery.linkGroups"
) jQuery, window, document