bootstrap-switch-ko

Knockout binding handler example for bootstrap-switch. Handles updates from the view model as well as updates from the view.

by jwstott

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/1.3/bootstrapSwitch.min.js"></script>
<div>
    <input type="checkbox" data-bind="checked: on" />
</div>
<div> <span data-bind="text: on() ? 'on' : 'off'"></span>

</div>
<div class="switch switch-large" data-bind="bootstrapSwitchOn: {init:false,checked:on, enabled:enabled}">
    <input type="checkbox" />
</div>

CSS

/* ============================================================
 * bootstrapSwitch v1.2 by Larentis Mattia @spiritualGuru
 * http://www.larentis.eu/switch/
 * ============================================================
 * Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 * ============================================================ */
 .has-switch {
    display: inline-block;
    cursor: pointer;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
    border: 1px solid;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
    position: relative;
    text-align: left;
    overflow: hidden;
    line-height: 8px;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    min-width: 100px;
}
.has-switch.switch-mini {
    min-width: 72px;
}
.has-switch.switch-small {
    min-width: 80px;
}
.has-switch.switch-large {
    min-width: 120px;
}
.has-switch.deactivate {
    opacity: 0.5;
    filter: alpha(opacity=50);
    cursor: default !important;
}
.has-switch.deactivate label, .has-switch.deactivate span {
    cursor: default !important;
}
.has-switch > div {
    display: inline-block;
    width: 150%;
    position: relative;
    top: 0;
}
.has-switch > div.switch-animate {
    -webkit-transition: left 0.5s;
    -moz-transition: left 0.5s;
    -o-transition: left 0.5s;
    transition: left 0.5s;
}
.has-switch > div.switch-off {
    left: -50%;
}
.has-switch > div.switch-on {
    left: 0%;
}
.has-switch input[type=checkbox] {
    display: none;
}
.has-switch span, .has-switch label {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    cursor: pointer;
    position: relative;
    display: inline-block;
    height: 100%;
    padding-bottom: 4px;
    padding-top: 4px;
    font-size: 14px;
    line-height: 20px;
}
.has-switch span.switch-mini,...

JavaScript

/**
 * Knockout binding handler for bootstrapSwitch indicating the status
 * of the switch (on/off): https://github.com/nostalgiaz/bootstrap-switch
 */
ko.bindingHandlers.bootstrapSwitchOn = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var $elem, 
            options = ko.utils.unwrapObservable(valueAccessor());
        init = defValue(options.init, false);
        if (init) {
            $(element).bootstrapSwitch();
        }
        $(element).bootstrapSwitch('setState', defValue(options.checked, true)); // Set intial state
        $(element).bootstrapSwitch('setActive', defValue(options.enabled, true)); // Set intial state
        $(element).on('switch-change', function (e, data) {
            valueAccessor().checked(data.value);
        }); // Update the model when changed.
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var vStatus = $(element).bootstrapSwitch('status'),
            vActive = $(element).bootstrapSwitch('isActive'),
            options = ko.utils.unwrapObservable(valueAccessor()),
            checked = defValue(options.checked, true),
            enabled = defValue(options.enabled, true);

        if (vStatus != checked) {
            $(element).bootstrapSwitch('setState', checked);
        }
        if (vActive != enabled) {
            $(element).bootstrapSwitch('setActive', enabled);
        }
    }
};

function defValue(source, dftValue) {
    return (typeof source !== 'undefined' ? ko.utils.unwrapObservable(source) : dftValue);
}
var vm = {
    on: ko.observable(true),
    enabled: ko.observable(true)
}
var sub = vm.on.subscribe(function (newValue) {
    console.log(newValue);
});
ko.applyBindings(vm);