Knockout with extended functions

by homer2

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css">
<script src="https://raw.github.com/SteveSanderson/knockout/master/build/output/knockout-latest.debug.js"></script>
value: <input type="text" data-bind="value: number" /><br/>
valueNumeric: <input type="text" data-bind="valueNumeric: number" /><br/>
valuePercent: <input type="text" data-bind="valuePercent: number" /><br/>
textPercent: <span data-bind="textPercent: number" ></span><br/>
textMoney: <span data-bind="textMoney: number" ></span><br/>

<div data-bind="text: ko.toJSON($root)"></div>

CSS

.header {
    font-size: 16px;
    font-family: sans-serif;
    font-weight: bold;
    margin-bottom: 20px;
}

JavaScript

Number.prototype.formatMoney = function (c) {
            var d = ".", t = ",", n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "," : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
            return "$" + s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
        };

//custom binding to make sure we save a number back to the data
ko.bindingHandlers.valueNumeric = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var underlyingObservable = valueAccessor();
        var interceptor = ko.computed({
            read: underlyingObservable,
            write: function (newValue) {
                var parsedValue = parseFloat(newValue.replace(/[^\d.]/g, ''));
                underlyingObservable(isNaN(parsedValue) ? newValue : parsedValue);
            }
        });
        ko.bindingHandlers.value.init(element, function () { return interceptor }, allBindingsAccessor);
    },
    update: ko.bindingHandlers.value.update
};

//custom binding to make sure we save a number back to the data
ko.bindingHandlers.valuePercent = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var underlyingObservable = valueAccessor();
        var interceptor = ko.computed({
            read: function(){ return null;} ,
            write: function (newValue) {
                var parsedValue = parseFloat(newValue.replace(/[^\d.]/g, '')) / 100;
                underlyingObservable(isNaN(parsedValue) ? newValue : parsedValue);
            }
        });
        ko.bindingHandlers.value.init(element, function () { return interceptor }, allBindingsAccessor);
    },
    update: ko.bindingHandlers.value.update
};


//custom binding to format a number as money, instead on defining it on each object as a Computed...