.directive('currencyMask', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elem, attrs, controller) {
elem.bind('blur', function() {
elem.val(formatNumberWithCommasAndDecimal(scope.$eval(attrs.ngModel), true));
});
controller.$parsers.push(function(value) {
if (value) {
value = formatNumberWithCommasAndDecimal(value, false);
controller.$setViewValue(value);
controller.$render();
}
return value;
});
controller.$formatters.push(function(value) {
if (value) value = formatNumberWithCommasAndDecimal(value, true);
return value;
});
}
};
});
function formatNumberWithCommasAndDecimal(value, addExtraZero) {
if (!value) return;
if (addExtraZero == undefined) addExtraZero = false;
value = value.toString();
value = value.replace(/,/g, '').replace(/[^1-9][^0-9\.]/g, '');
// parse[0] are digits. parse[1] is decimal
var parts = value.split('.');
if (parts.length > 2) {
// if user puts in more dots, merge them again but remove other dots except first one found,
// then split again
dummy = '';
for (i=0; i<parts.length; i++) {
dummy += parts[i];
if (i == 1) dummy += '.';
}
parts = dummy.split('.');
}
// if there are trailing 0s at the beginning, convert to float to remove them
// then convert back to string
parts[0] = parseFloat(parts[0]) + '';
// parse by thousand adding comma
var rev = parts[0].split("").reverse().join("");
var dum = '';
for (var i=0; i<rev.length; i++) {
if (i > 0 && i % 3 == 0) {
dum += ',';
}
dum += rev.charAt(i);
}
if (dum.length > 0) parts[0] = dum.split("").reverse().join("");
if (parts[1] && parts[1].length > 2) {
parts[1] = parts[1].substring(0, 2);
}
// if no decimal found but dot is present
if (addExtraZero) {
if (parts[1]) {
if (parts[1] == '') parts[1] = '00';
else if (parts[1].length == 1) parts[1] += '0';
}
else {
if (parts[0].length > 0) parts[0] += '.00';
}
}
return parts.join('.');
}