Bootstrap 3 radio buttons with Knockout 3

Default radio buttons with Knockout bindings and checkedValue binding, removed data-toggle="buttons" and added in CSS to hide the circle part of the input type="radio"

by John Farrar

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<div class="btn-group">
    <label class="btn btn-primary" data-bind="css: { 'active': rSelect() === 'cyan' }">
        <input type="radio" name="rSelect" id="rSelect1" data-bind="checked: rSelect, checkedValue: 'cyan'">Cyan
    </label>
    <label class="btn btn-primary" data-bind="css: { 'active': rSelect() === 'yellow' }">
        <input type="radio" name="rSelect" id="rSelect2" data-bind="checked: rSelect, checkedValue: 'yellow'">Yellow
    </label>
   <label class="btn btn-primary" data-bind="css: { 'active': rSelect() === 'magenta' }">
        <input type="radio" name="rSelect" id="rSelect3" data-bind="checked: rSelect, checkedValue: 'magenta'">Magenta
    </label>
</div>
<p>
    The Knockout view model value is: <span data-bind="text: rSelect"></span>
</p>

<div class="btn-group">
    <label class="btn btn-primary" data-bind="css: { 'active': cbSelected('red') }">
        <input type="checkbox" data-toggle="checkbox" name="cbSelect" data-value="red" data-bind="checkedButtons: cbSelect">Red
    </label>
    <label class="btn btn-primary" data-bind="css: { 'active': cbSelected('green') }">
        <input type="checkbox" data-toggle="checkbox" name="cbSelect" data-value="green" data-bind="checkedButtons: cbSelect">Green
    </label>
   <label class="btn btn-primary" data-bind="css: { 'active': cbSelected('blue')  }">
        <input type="checkbox" data-toggle="checkbox" name="cbSelect" data-value="blue" data-bind="checkedButtons: cbSelect">Blue
    </label>
</div>
<p>
    The Knockout view model value is: <span data-bind="text: cbSelect"></span>
</p>

<div class="btn-group">
    <label class="btn btn-primary"...

CSS

body {
    padding: 15px;
}

label.btn > input[type='radio'],label.btn > input[type='checkbox']
{
    display: none;
}

JavaScript

ko.bindingHandlers['checkedButtons'] = {
    'init': function (element, valueAccessor, allBindingsAccessor) {
        var type = element.getAttribute('data-toggle') || 'radio';
        var updateHandler = function () {
            var valueToWrite;
            var isActive = !!~element.className.indexOf('active');
            var dataValue = element.getAttribute('data-value');
            if (type == "checkbox") {
                valueToWrite = !isActive;
            } else if (type == "radio" && !isActive) {
                valueToWrite = dataValue;
            } else {
                return; // "checkedButtons" binding only responds to checkbox and radio data-toggle attribute
            }

            var modelValue = valueAccessor();
            if ((type == "checkbox") && (ko.utils.unwrapObservable(modelValue) instanceof Array)) {
                // For checkboxes bound to an array, we add/remove the checkbox value to that array
                // This works for both observable and non-observable arrays
                var existingEntryIndex = ko.utils.arrayIndexOf(ko.utils.unwrapObservable(modelValue), dataValue);
                if (!isActive && (existingEntryIndex < 0))
                    modelValue.push(dataValue);
                else if (isActive && (existingEntryIndex >= 0))
                    modelValue.splice(existingEntryIndex, 1);
            } else {
                if (modelValue() !== valueToWrite) {
                    modelValue(valueToWrite);
                }
            }
        };
        
        ko.utils.registerEventHandler(element, "click", updateHandler);
    },
    'update': function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        var type = element.getAttribute('data-toggle') || 'radio';

        if (type == "checkbox") {
            if (value instanceof Array) {
                // When bound to an array, the checkbox being checked represents its value being present in that...