Knockout Bindings for Bootstrap Toggle Buttons, Version 2
by Doug Hill
HTML
<script src="http:////cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.1/css/bootstrap.min.css">
<div class="btn-group" data-bind="radio: range">
<button type="button" class="btn" data-value="2w">2 Weeks</button>
<button type="button" class="btn" data-value="4w">4 Weeks</button>
<button type="button" class="btn" data-value="3m">3 Months</button>
<button type="button" class="btn" data-value="6m">6 Months</button>
<button type="button" class="btn" data-value="1y">1 Year</button>
</div>
<div class="btn-group">
<button type="button" class="btn" data-bind="radio: alignment, radioValue: 'left'">Left</button>
<button type="button" class="btn" data-bind="radio: alignment, radioValue: 'middle'">Middle</button>
<button type="button" class="btn" data-bind="radio: alignment, radioValue: 'right'">Right</button>
</div>
<div class="btn-group">
<button type="button" class="btn" data-bind="checkbox: important">Important</button>
<button type="button" class="btn" data-bind="checkbox: urgent">Urgent</button>
</div>
<div>
Range: <span data-bind="text: range"></span>,
Alignment: <span data-bind="text: alignment"></span>,
Important: <span data-bind="text: important"></span>,
Urgent: <span data-bind="text: urgent"></span>,
</div>
CSS
div { padding: 10px; }
.btn-group + .btn-group { margin-left: inherit; }
span { font-weight: bold; color: #a00;}
JavaScript
ko.bindingHandlers.radio = {
init: function(element, valueAccessor, allBindings, data, context) {
var $buttons, $element, observable;
observable = valueAccessor();
if (!ko.isWriteableObservable(observable)) {
throw "You must pass an observable or writeable computed";
}
$element = $(element);
if ($element.hasClass("btn")) {
$buttons = $element;
} else {
$buttons = $(".btn", $element);
}
elementBindings = allBindings();
$buttons.each(function() {
var $btn, btn, radioValue;
btn = this;
$btn = $(btn);
radioValue = elementBindings.radioValue || $btn.attr("data-value") || $btn.attr("value") || $btn.text();
$btn.on("click", function() {
observable(ko.utils.unwrapObservable(radioValue));
});
return ko.computed({
disposeWhenNodeIsRemoved: btn,
read: function() {
$btn.toggleClass("active", observable() === ko.utils.unwrapObservable(radioValue));
}
});
});
}
};
ko.bindingHandlers.checkbox = {
init: function(element, valueAccessor, allBindings, data, context) {
var $element, observable;
observable = valueAccessor();
if (!ko.isWriteableObservable(observable)) {
throw "You must pass an observable or writeable computed";
}
$element = $(element);
$element.on("click", function() {
observable(!observable());
});
ko.computed({
disposeWhenNodeIsRemoved: element,
read: function() {
$element.toggleClass("active", observable());
}
});
}
};
viewModel = {
range: ko.observable("4w"),
alignment: ko.observable("left"),
important: ko.observable(false),
urgent: ko.observable(true)
};
ko.applyBindings(viewModel);