StackOverflow_23779574: angularjs-how-to-apply-currency-filter-on-textbox-as-i-type

Illustration of answer to http://stackoverflow.com/questions/23779574/angularjs-how-to-apply-currency-filter-on-textbox-as-i-type.

by Sreekesh S K

HTML

<script src="http://code.angularjs.org/1.2.16/angular.min.js"></script>
<div ng-controller="myCtrl">
    Amount: <input type="text" ng-model="aNumber" real-time-currency />
    <br />
    Value: {{aNumber}}
</div>

JavaScript

var app = angular.module('myApp', []);
app.controller('myCtrl', function () {});

app.directive('realTimeCurrency', function ($filter, $locale) {
    var decimalSep = $locale.NUMBER_FORMATS.DECIMAL_SEP;
    var toNumberRegex = new RegExp('[^0-9\\' + decimalSep + ']', 'g');
    var trailingZerosRegex = new RegExp('\\' + decimalSep + '0+$');
    var filterFunc = function (value) {
    var newVal = $filter('currency')(value,'');

        return newVal.split('.00')[0];
    };

    function getCaretPosition(input){
        if (!input) return 0;
        if (input.selectionStart !== undefined) {
            return input.selectionStart;
        } else if (document.selection) {
            // Curse you IE
            input.focus();
            var selection = document.selection.createRange();
            selection.moveStart('character', input.value ? -input.value.length : 0);
            return selection.text.length;
        }
        return 0;
    }
    function toNumber(currencyStr) {
        return parseInt(currencyStr.replace(toNumberRegex, ''), 10);
    }

    return {
        restrict: 'A',
        require: 'ngModel',
        link: function postLink(scope, elem, attrs, modelCtrl) {    
            modelCtrl.$formatters.push(filterFunc);
            modelCtrl.$parsers.push(function (newViewValue) {
                var oldModelValue = modelCtrl.$modelValue;
                var newModelValue = toNumber(newViewValue);
                modelCtrl.$viewValue = filterFunc(newModelValue);
                var pos = getCaretPosition(elem[0]);
                elem.val(modelCtrl.$viewValue);
                var newPos = pos + modelCtrl.$viewValue.length -
                                   newViewValue.length;
                if ((oldModelValue === undefined) || isNaN(oldModelValue)) {
                    newPos -= 3;
                }
               
                return newModelValue;
            });
        }
    };
});