learn.knockoutjs.com - Creating custom bindings
http://learn.knockoutjs.com/#/?tutorial=custombindings
by olli
HTML
<script src="http://learn.knockoutjs.com/Scripts/Lib/jquery.tmpl.js"></script>
<script src="http://learn.knockoutjs.com/Scripts/Lib/jquery.address.js"></script>
<script src="http://learn.knockoutjs.com/Scripts/Lib/knockout-1.3.0.latest.js"></script>
<link rel="stylesheet" href="http://learn.knockoutjs.com/Content/App/coderunner.css">
<link rel="stylesheet" href="http://learn.knockoutjs.com/Content/TutorialSpecific/custombindings.css">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/start/jquery-ui.css">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0rc2/jquery.mobile-1.0rc2.min.css">
<script src="http://code.jquery.com/mobile/1.0rc2/jquery.mobile-1.0rc2.min.js"></script>
<body>
<div data-role="page" id="mypage">
<div data-role="header">
<h1>
Tutorial 4
</h1>
</div>
<div data-role="content">
<h3 data-bind="text: question"></h3>
<p class="content-textbox">Please distribute <span data-bind="text: pointsBudget"></span> points between the following options.</p>
<div data-bind="template: { name: 'answerTemplate', foreach: answers }"></div>
<script type="text/html" id="answerTemplate">
<div class="content-colored-textbox">
${ text }<br/>
<span data-bind="starRating: points"></span>
</div>
</script>
<h3 data-bind="fadeVisible: pointsUsed() > pointsBudget">You've used too many points! Please remove some.</h3>
<p class="content-textbox">You've got <b data-bind="text: pointsBudget - pointsUsed()"></b> points left to use.</p>
<button data-bind="jqmButton: { enable: pointsUsed() <= pointsBudget }, click: save">Finished</button>
</div>
</div>
</body>
CSS
.content-textbox {
background: none repeat scroll 0 0 #F9F9F9;
box-shadow: 0 0 3px #CCCCCC;
line-height: 1.2em;
margin-bottom: 15px;
margin-top: 10px;
padding: 8px;
}
.content-colored-textbox {
background: none repeat scroll 0 0 #FFFFCC;
box-shadow: 0 0 3px #CCCCCC;
line-height: 1.2em;
margin-bottom: 15px;
margin-top: 10px;
padding: 8px;
}
JavaScript
(function() { // Wrap in function to prevent accidental globals
$('#mypage').live('pageinit', function() {
// ----------------------------------------------------------------------------
// Reusable bindings - ideally kept in a separate file
ko.bindingHandlers.fadeVisible = {
init: function(element, valueAccessor) {
// Start visible/invisible according to initial value
var shouldDisplay = valueAccessor();
$(element).toggle(shouldDisplay);
},
update: function(element, valueAccessor) {
// On update, fade in/out
var shouldDisplay = valueAccessor();
shouldDisplay ? $(element).fadeIn() : $(element).fadeOut();
}
};
ko.bindingHandlers.jqmButton = {
/*
init: function(element) {
$(element).button();
},*/
update: function(element, valueAccessor) {
var currentValue = valueAccessor();
$(element).button((currentValue.enable === true) ? "enable" : "disable");
}
};
ko.bindingHandlers.starRating = {
init: function(element, valueAccessor) {
$(element).addClass("starRating");
for (var i = 0; i < 5; i++)
$("<span>").appendTo(element);
// Handle mouse events on the stars
$("span", element).each(function(index) {
$(this).hover(
function() {
$(this).prevAll().add(this).addClass("hoverChosen")
}, function() {
$(this).prevAll().add(this).removeClass("hoverChosen")
}).click(function() {
var observable = valueAccessor(); // Get the associated observable
observable(index + 1); // Write the new rating to it
});
...