淘汰赛:为数字组合2个自定义绑定 - 财务数据

时间:2013-04-16 10:41:48

标签: javascript knockout.js

美好的一天

我发现以下两个小提琴完全符合我的要求:

first Fiddle给出了十进制表示法。

second Fiddle为我提供数字数字分组。

我的问题:我如何将它们合并为一个这样我可以像这样使用它:

<b data-bind="commaDecimalFormatter: myNumber">This will output both demical notation and digital grouping</b>

=============================================== ================================================== ================================================== =================

小提琴1代码:

// Formatting Functions
function formatWithComma(x, precision, seperator) {
    var options = {
        precision: precision || 2,
        seperator: seperator || '.'
    }
    var formatted = parseFloat(x,10).toFixed( options.precision );
    var regex = new RegExp(
            '^(\\d+)[^\\d](\\d{' + options.precision + '})$');
    formatted = formatted.replace(
        regex, '$1' + options.seperator + '$2');
    return formatted;
}

function reverseFormat(x, precision, seperator) {
    var options = {
        precision: precision || 2,
        seperator: seperator || ','
    }
    var regex = new RegExp(
        '^(\\d+)[^\\d](\\d+)$');
    var formatted = x.replace(regex, '$1.$2');
    return parseFloat( formatted );
}
// END: Formatting Functions


// Custom Binding - place this in a seperate .js file and reference it in your html
ko.bindingHandlers.commaDecimalFormatter = {
    init: function(element, valueAccessor) {

        var observable = valueAccessor();

        var interceptor = ko.computed({
            read: function() {
                return formatWithComma( observable() );
            },
            write: function(newValue) {
                observable( reverseFormat(newValue) );
            }
        });

        if( element.tagName == 'INPUT' )
            ko.applyBindingsToNode( element , {
                value: interceptor
            } );
        else
            ko.applyBindingsToNode( element , {
                text: interceptor
            } );
    }
}

// this is your viewmodel
var vm = {
    myNumber: ko.observable(100000)
}

// when the DOM is ready, call ko.applyBindings with your viewmodel
$(function() {
    ko.applyBindings(vm);
});

FIDDLE 2代码:

(function(){
    var format = function(value) {
        toks = value.toFixed(2).replace('-', '').split('.');
        var display = '$' + $.map(toks[0].split('').reverse(), function(elm, i) {
            return [(i % 3 === 0 && i > 0 ? ',' : ''), elm];
        }).reverse().join('') + '.' + toks[1];

        return value < 0 ? '-' + display : display;
    };

ko.subscribable.fn.money = function() {
    var target = this;

    var writeTarget = function(value) {
        var stripped=value
            .replace(/[^0-9.-]/g, '');

        target(parseFloat(stripped));
    };

    var result = ko.computed({
        read: function() {
            return target();
        },
        write: writeTarget
    });

    result.formatted = ko.computed({
        read: function() {
            return format(target());
        },
        write: writeTarget
    });

    result.isNegative = ko.computed(function(){
        return target()<0;
    });

    return result;
};
})();

//Wire it up
$(function() {
    var viewModel = {
        Cash: ko.observable(1000000).money(),
    };


    viewModel.Total = ko.computed(function() {
        return this.Cash();
    }, viewModel).money();
    ko.applyBindings(viewModel);
});

2 个答案:

答案 0 :(得分:1)

我无法将这两个功能结合起来。请尝试以下操作,因为它可以满足您的需要:Decimal符号和Digit分组:

JS:

function formatPrice(price) {
        return price.reverse().replace(/((?:\d{2})\d)/g, '$1 ').reverse();
    }

    // Need to extend String prototype for convinience
    String.prototype.reverse = function() {
        return this.split('').reverse().join('');
    }

    $('.myNumber').each(function(){
        $(this).html(formatPrice($(this).html()));
    });

请参阅Fiddle

注意:您需要每次刷新浏览器以使jquery将输出值(只读)格式化为数字分组...当然,当您在编辑器屏幕(第一个字段)中输入新值并且您没有看到数字分组更新

答案 1 :(得分:0)

我想提供替代解决方案。您还可以创建一个自定义绑定处理程序,它可以执行您想要的操作(使用您最初提出的语法)。

ko.bindingHandlers. commaDecimalFormatter = {
  update: function(element, valueAccessor, allValuesAccessor) {

    // This gets the current value of the observable from your model
    var value = ko.utils.unwrapObservable(valueAccessor());

    // Manipulate `value` as desired using the bodies of the functions you mentioned
    // Note: You don't want to use a global function, so actually take the bodies 
    // and put it here. Plain old JS :)
    ...

   // Set the value on the element
   jQuery(element).text(value);
  }
};