自動計算と手動計算の混ぜ方

"価格"は"単価"と"数量"から求めてね! でも、 "価格”は直接入力することもあるからね! なケースの対処方法

by MKGaru

HTML

<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script src="http://mbest.github.io/knockout.punches/knockout.punches.min.js"></script>
<script src="https://rawgit.com/SteveSanderson/knockout-es5/master/dist/knockout-es5.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/sugar/1.4.1/sugar-full.development.min.js"></script>
<table>
    <thead>
        <tr><th>単価</th><th>数量</th><th>価格</th></tr>
    </thead>
    <tbody>
        <tr>
            <th>Input/Formatteed Value</th>
             <td><input type="text" data-bind="value:formattedUnitPrice"/></td>
            <td><input type="text" data-bind="value:formattedQuantity"/></td>
            <td><input type="text" data-bind="value:formattedPrice" /></td>
        </tr>
        <tr>
            <th>Raw Value</th>
            <td>{{unitPrice}}</td>
            <td>{{quantity}}</td>
            <td>{{price}}</td>
        </tr>
    </tbody>
</table>

CSS

tbody>tr *{
    text-align:right;
}

JavaScript

function App(){
    var app = this;
    
    app.unitPrice = null;
    app.quantity = null;
    app.price = null;
    ko.track(app);
    
    ko.getObservable(app,'unitPrice').subscribe(function(unitPrice){
        app.price = unitPrice * app.quantity;
    });
    ko.getObservable(app,'quantity').subscribe(function(quantity){
        app.price = app.unitPrice * quantity;
    });
    
    numberFormattedProperty(app,"unitPrice",{prefix:'¥'});
    numberFormattedProperty(app,"quantity",{suffix:'kg',place:2});
    numberFormattedProperty(app,"price",{prefix:'¥'});
}

ko.punches.enableAll();
ko.applyBindings(new App());








function numberFormattedProperty(model,prop,option){
    var _default = {
        prefix:'',
        suffix:'',
        place:0, 
        thousands:',',
        decimal:'.',
        round:'round' // round | ceil | floor  (四捨五入, 切上げ, 切り捨て)        
    }
    option = ko.utils.extend(_default,option);
    ko.defineProperty(model,"formatted"+prop.camelize(),{
        get:function(){
            if(ko.unwrap(model[prop])==null) return "";
            return option.prefix+ko.unwrap(model[prop]).format(option.place,option.thousands,option.decimal)+option.suffix;
        },
        set:function(value){
            if(value==""){
                model[prop]=null;
                return;
            }
            model[prop]=NaN; //force mutant event
            model[prop] = (+value.hankaku().replace(/[^0-9\.]/g, ''))[option.round](option.place);
        }
    });
}