Created
September 13, 2011 16:30
-
-
Save studgeek/1214258 to your computer and use it in GitHub Desktop.
knockout autocomplete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<input data-bind="jqAuto: { autoFocus: true }, jqAutoSource: myPeople, jqAutoValue: mySelectedGuid, jqAutoSourceLabel: 'displayName', jqAutoSourceInputValue: 'name', jqAutoSourceValue: 'guid'" /> | |
<hr/> | |
<div data-bind="text: mySelectedGuid() ? mySelectedGuid() : 'None selected'"></div> | |
<hr/> | |
For testing setting the model value elsewhere: | |
<select data-bind="options: myPeople, optionsCaption: 'select a person...', optionsText: 'displayName', optionsValue: 'guid', value: mySelectedGuid"></select> | |
<hr/> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//jqAuto -- main binding (should contain additional options to pass to autocomplete) | |
//jqAutoSource -- the array of choices | |
//jqAutoValue -- where to write the selected value | |
//jqAutoSourceLabel -- the property that should be displayed in the possible choices | |
//jqAutoSourceInputValue -- the property that should be displayed in the input box | |
//jqAutoSourceValue -- the property to use for the value | |
ko.bindingHandlers.jqAuto = { | |
init: function(element, valueAccessor, allBindingsAccessor, viewModel) { | |
var options = valueAccessor() || {}, | |
allBindings = allBindingsAccessor(), | |
unwrap = ko.utils.unwrapObservable, | |
modelValue = allBindings.jqAutoValue, | |
source = unwrap(allBindings.jqAutoSource), | |
valueProp = allBindings.jqAutoSourceValue, | |
inputValueProp = allBindings.jqAutoSourceInputValue || valueProp, | |
labelProp = allBindings.jqAutoSourceLabel || inputValueProp; | |
//function that is shared by both select and change event handlers | |
function writeValueToModel(valueToWrite) { | |
if (ko.isWriteableObservable(modelValue)) { | |
modelValue(valueToWrite ); | |
} else { //write to non-observable | |
if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers']['jqAutoValue']) | |
allBindings['_ko_property_writers']['jqAutoValue'](valueToWrite ); | |
} | |
} | |
//on a selection write the proper value to the model | |
options.select = function(event, ui) { | |
writeValueToModel(ui.item ? ui.item.actualValue : null); | |
}; | |
//on a change, make sure that it is a valid value or clear out the model value | |
options.change = function(event, ui) { | |
var currentValue = $(element).val(); | |
var matchingItem = ko.utils.arrayFirst(source, function(item) { | |
return unwrap(item[inputValueProp]) === currentValue; | |
}); | |
if (!matchingItem) { | |
writeValueToModel(null); | |
} | |
} | |
//handle the choices being updated in a DO, to decouple value updates from source (options) updates | |
var mappedSource = ko.dependentObservable(function() { | |
mapped = ko.utils.arrayMap(source, function(item) { | |
var result = {}; | |
result.label = labelProp ? unwrap(item[labelProp]) : unwrap(item).toString(); //show in pop-up choices | |
result.value = inputValueProp ? unwrap(item[inputValueProp]) : unwrap(item).toString(); //show in input box | |
result.actualValue = valueProp ? unwrap(item[valueProp]) : item; //store in model | |
return result; | |
}); | |
return mapped; | |
}); | |
//whenever the items that make up the source are updated, make sure that autocomplete knows it | |
mappedSource.subscribe(function(newValue) { | |
$(element).autocomplete("option", "source", newValue); | |
}); | |
options.source = mappedSource(); | |
//initialize autocomplete | |
$(element).autocomplete(options); | |
}, | |
update: function(element, valueAccessor, allBindingsAccessor, viewModel) { | |
//update value based on a model change | |
var allBindings = allBindingsAccessor(), | |
unwrap = ko.utils.unwrapObservable, | |
modelValue = unwrap(allBindings.jqAutoValue), | |
valueProp = allBindings.jqAutoSourceValue, | |
inputValueProp = allBindings.jqAutoSourceInputValue || valueProp; | |
//if we are writing a different property to the input than we are writing to the model, then locate the object | |
if (valueProp && inputValueProp !== valueProp) { | |
var source = unwrap(allBindings.jqAutoSource) || []; | |
var modelValue = ko.utils.arrayFirst(source, function(item) { | |
return unwrap(item[valueProp]) === modelValue; | |
}) || {}; | |
} | |
//update the element with the value that should be shown in the input | |
$(element).val(modelValue && inputValueProp !== valueProp ? unwrap(modelValue[inputValueProp]) : modelValue.toString()); | |
} | |
}; | |
function Person(guid, name, email) { | |
this.guid = ko.observable(guid); | |
this.name = ko.observable(name); | |
this.email = ko.observable(email); | |
this.displayName = ko.dependentObservable(function() { | |
return this.name() + " [" + this.email() + "]"; | |
}, this); | |
} | |
var viewModel = { | |
myPeople: ko.observableArray([ | |
new Person("5658ff20-f230-4176-97d1-0ac21abfdbdf", "Bob Smith", "bsmith@company.com"), | |
new Person("1d7b9b28-25b7-40de-bec1-0a5426228f5b", "Bonnie Johnson", "bjohnson@company.com"), | |
new Person("28605d66-d794-4a09-8452-0278abd690c6", "John Daniels", "jdaniels@company.com"), | |
new Person("7c4881ef-5530-45c9-96eb-5dceed6cd4c9", "Deborah Danielson", "ddanielson@company.com"), | |
new Person("ec361d63-38ae-4ecc-ab46-6c0ef19ed3ac", "John Daniels", "jxdaniels@company.com") | |
]), | |
mySelectedGuid: ko.observable("ec361d63-38ae-4ecc-ab46-6c0ef19ed3ac") | |
}; | |
ko.applyBindings(viewModel); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: jQuery UI autocomplete - original rniemeyer version | |
description: knockout autocomplete, see https://groups.google.com/d/topic/knockoutjs/ABhEeI7jLKA/discussion | |
authors: | |
- rniemeyer | |
resources: | |
- jsfiddle-defaults.user.js | |
- http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/base/jquery-ui.css | |
- http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js | |
- http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js | |
normalize_css: no |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Sensible defaults for jsFiddle. | |
// @author Mathias Bynens <http://mathiasbynens.be/> | |
// @link http://mths.be/bde | |
// @match http://jsfiddle.net/* | |
// ==/UserScript== | |
// Insert JS before </body> and don’t use any libraries by default | |
[].forEach.call(document.querySelectorAll('#js_wrap option[value="b"], #js_lib option[value="11"]'), function(el) { | |
el.selected = true; | |
}); | |
// Don’t use the “normalized” CSS (it’s more like a reset anyway) | |
document.getElementById('id_normalize_css').checked = false; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment