jQuery UI autocomplete with a Knockout binding handler
(Posted)
by w1ndig0
HTML
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/ui-lightness/jquery-ui.css">
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>
<button data-bind="click: updateDataSource">Update Data Source</button>
<label for="name-search">Search language:</label>
<input type="text" id="name-search" data-bind="value: langName,
ko_autocomplete: { minLength : 0, source: languages, select: addLang }" />
<div style="margin-top:1em">The observable array contains the following elements:
<ul data-bind="foreach: selectedLangs">
<li data-bind="text: $data" />
</ul>
</div>
JavaScript
ko.bindingHandlers.ko_autocomplete = {
init: function (element, params) {
//We make a shallow copy of the object because we will change it
var conf = $.extend({}, params());
// This fixes the problem of showing the value instead of the label when pressing up or down
if (!conf.focus) {
//There is no focus callback defined so we will add one
conf.focus = function (event, ui) {
$(element).val(ui.item.label);
return false;
}
}
// Use this to check if the autocomplete is already initialize
var isAutoComplete = $(element).is(':data(autocomplete)');
// Use an observable instead of a fixed array
var source = conf.source; // <- assuming an observable here
conf.source = source(); // get the actual content
$(element).autocomplete(conf);
if (!isAutoComplete) {
//watch for modifications
var subscription = source.subscribe(function (newValue) {
$(element).autocomplete("option", "source", newValue);
});
//handle disposal
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
subscription.dispose();
$(element).autocomplete("destroy");
});
}
},
update: function (element, params) {
$(element).autocomplete("option", "source", params.source);
return false;
}
}
$(function () {
var availableTags = [{
label: "ActionScript",
value: 1
}, {
label: "AppleScript",
value: 2
}, {
label: "Asp",
value: 3
}, {
label: "BASIC",
value: 4
}, {
label: "C",
value: 5
}, {
label: "C++",
value: 6
...