Permalink
Browse files

adding autocomplete binding

  • Loading branch information...
1 parent 9799d9c commit ea9ba3caf24fd2a4af7dbc5e4a13c012cba3108c @dnagir committed Dec 29, 2011
@@ -0,0 +1,60 @@
+#= require pakunok/jquery-ui/pack/autocomplete
+
+$ = jQuery
+
+getFieldKey = (obj, label) ->
+ key = [label, 'name', 'label', 'value'].find (key) -> obj[key]?
+
+getLabel = (obj, label) ->
+ key = getFieldKey obj, label
+ return obj unless key
+ ko.utils.unwrapObservable obj[key]
+
+
+getTerm = (obj, label) ->
+ item = obj.item or obj
+ key = getFieldKey item, label
+ return item unless key
+
+ value = ko.utils.unwrapObservable item[key]
+ value or item
+
+
+filter = (source, term, label) ->
+ matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" )
+ source.filter (obj) -> matcher.test getTerm(obj, label)
+
+
+ko.bindingHandlers.autocomplete =
+ init: (element, valueAccessor, allBindingsAccessor, viewModel) ->
+ binding = valueAccessor()
+
+ options =
+ delay: binding.delay
+ minLength: binding.minLength
+
+ options.select = (e, ui) ->
+ debugger
+ binding.select(ui.item.item) if binding.select
+
+ options.source = (request, response) ->
+ src = ko.utils.unwrapObservable binding.source
+ response filter(src, request.term, binding.label)
+
+ options.minLength = 2 unless options.minLength?
+
+ ac = $(element).autocomplete(options).data 'autocomplete'
+ ac._normalize = (items) ->
+ items.map (it) ->
+ label: getLabel(it, binding.label)
+ value: getTerm(it, binding.label)
+ item: it # This gives acces to the actual object
+
+ ac._renderItem = (ul, item) ->
+ txt = getTerm item, binding.label
+ $( "<li></li>" )
+ .data("item.autocomplete", item)
+ .append( $("<a></a>").text txt )
+ .appendTo(ul)
+
+
@@ -0,0 +1,63 @@
+#= require knockout/bindings/autocomplete
+
+describe "autocomplete", ->
+
+ prepare = (source, label='') ->
+ current = ko.observable 'nothing selected'
+ setFixtures """
+ <input
+ id="ac"
+ data-bind="autocomplete: {source: source, select: current, label: '#{label}', delay: 0, minLength: 0}"
+ />
+ """
+ data = {source: source, current: current}
+ ko.applyBindings data, $("#ac")[0]
+ data
+
+
+ search = (what) -> $("#ac").autocomplete 'search', what
+ menu = -> $(".ui-autocomplete.ui-menu")
+ itemsText = -> menu().find('li a').map( -> $(@).text() ).toArray().join ','
+ select = (label) ->
+ item = menu().children('li').filter(-> $(@).text() == label).first()
+ menu().data('menu').activate $.Event('click'), item
+ item.children().click()
+
+
+
+ it "should show menu from array", ->
+ prepare ['1', '22', '222', '3']
+ search '2'
+ expect( itemsText() ).toBe '22,222'
+
+ it "should select an observable", ->
+ data = prepare ['22']
+ search '2'
+ select '22'
+ expect( data.current() ).toBe '22'
+
+ it "should show names for objects", ->
+ prepare [{name: '11', id: 1}, {name: '22', id: 2}], 'name'
+ search '1'
+ expect( itemsText() ).toBe '11'
+
+ it "should show names for observable objects", ->
+ prepare [
+ {name: ko.observable('11'), id: 1}
+ {name: ko.observable('22'), id: 2}],
+ 'name'
+ search '1'
+ expect( itemsText() ).toBe '11'
+
+ it "should select object when source is array of objects", ->
+ obj = {name: '22'}
+ data = prepare [{name: '11'}, obj], 'name'
+ search '2'
+ select '22'
+ expect( data.current() ).toBe obj
+
+
+ describe "setting selected element", ->
+ it "with array", -> expect('todo').toBe 'done'
+ it "with observable array", -> expect('todo').toBe 'done'
+ it "with jQuery AJAX object", -> expect('todo').toBe 'done'

0 comments on commit ea9ba3c

Please sign in to comment.