Skip to content

Instantly share code, notes, and snippets.

@stephenharris
Last active July 17, 2018 21:45
Show Gist options
  • Save stephenharris/69138960a45a48549c4d67f66b379c42 to your computer and use it in GitHub Desktop.
Save stephenharris/69138960a45a48549c4d67f66b379c42 to your computer and use it in GitHub Desktop.
Formats currency input and provides a method from extracting the amount (in fractional currency units - i.e. in cents/pennies) http://jsfiddle.net/7g26x0uL/155/
$.widget( "nmk.currencyField", {
// Default options.
options: {
decimalPlaces: 2,
decimalSeperator: ".",
thousandSeperator: ",",
},
_create: function() {
if(this.options.decimalSeperator === this.options.thousandSeperator){
this.options.thousandSeperator = null;
}
if(this.options.decimalPlaces === 0){
this.options.decimalSeperator = null;
}
this.element.on('keydown', $.proxy(function(evt){
var char = evt.key;
var value = $(evt.target).val();
if (
// ALlow delete, backspace, tab, escape, enter and workaround for Samsung
$.inArray(evt.which, [46, 8, 9, 27, 13, 229]) !== -1 ||
// Allow: Ctrl+A/V/X, Command+A/V/X
($.inArray(evt.which, [65, 86, 88]) && (evt.ctrlKey === true || evt.metaKey === true)) ||
// Allow: home, end, left, right, down, up
(evt.which >= 35 && evt.which <= 40) ||
// Allow thousand seperator
(this.options.thousandSeperator && char === this.options.thousandSeperator)) {
return;
}
if(char === this.options.decimalSeperator){
return value.indexOf(this.options.decimalSeperator) === -1;
}
// Abort if not a number
if ((evt.shiftKey || (evt.keyCode < 48 || evt.keyCode > 57)) && (evt.keyCode < 96 || evt.keyCode > 105)) {
evt.preventDefault();
}
// Ensure the maximum number of decimal places is not exceeded
var caratPos = evt.target.selectionStart;
var dotPos = value.indexOf(this.options.decimalSeperator);
var parts = value.split(this.options.decimalSeperator);
if( caratPos > dotPos && dotPos > -1 && (parts[1].length > this.options.decimalPlaces - 1)){
return false;
}
},this));
this.element.on('paste', $.proxy(function(event){
event.preventDefault();
var value = event.originalEvent.clipboardData.getData('text/plain');
this.element.val(this._formatAmount(this._parseAmount(value)));
},this));
this.element.on('blur', $.proxy(function(){
this.element.val(this.formattedAmount(this.getAmount()));
},this));
},
getAmount: function(){
return this._parseAmount(this.element.val());
},
formattedAmount: function(){
return this._formatAmount(this.getAmount());
},
_parseAmount: function(value){
if(!value){
return 0;
}
var numeric = value.replace(new RegExp('[^0-9'+this.options.decimalSeperator+']','g'), '');
var regex = new RegExp('^(\\d+(?:'+this.options.decimalSeperator+'\\d{0,'+this.options.decimalPlaces+'})?).*$','g');
var parts = numeric.replace(regex,"$1").split(this.options.decimalSeperator);
var integer = parseInt(parts[0],10) * Math.pow(10, this.options.decimalPlaces);
if(parts.length > 1){
integer += parseInt(this._pad(parts[1],this.options.decimalPlaces, 'right').slice(0, this.options.decimalPlaces),10);
}
return integer;
},
_formatAmount: function(amountInFractionalUnits){
var parts;
if(this.options.decimalPlaces){
var regex = new RegExp('^(\\d+)(\\d{'+this.options.decimalPlaces+'})$');
var parts = this._pad(amountInFractionalUnits, this.options.decimalPlaces + 1, 'left')
.replace(regex,"$1"+this.options.decimalSeperator+"$2")
.split(this.options.decimalSeperator);
} else {
parts = [amountInFractionalUnits];
}
var rgx = /(\d+)(\d{3})/;
while (rgx.test(parts[0])) {
parts[0] = parts[0].replace(rgx, '$1' + this.options.thousandSeperator + '$2');
}
return this.options.decimalSeperator && parts.length > 1 ? parts[0] + this.options.decimalSeperator + parts[1] : parts[0];
},
_pad: function(string, length, type){
var n = length - (""+string).length;
if(n > 0) {
var padding = (new Array(n+1).join("0"));
string = type === 'left' ? padding + string : string + padding;
}
return string+"";
}
});
<input data-thousand="," data-decimal="." data-decimalplaces="2" id="input" type="text"/>
<p id="render"></p>
<p id="render2"></p>
$('#input').currencyField({
decimalPlaces: $('#input').data('decimalplaces'),
decimalSeperator: $('#input').data('decimalseperator'),
thousandSeperator: $('#input').data('thousandseperator')
});
$('#input').on('change blur', function(event){
$('#render').text($(this).currencyField('getAmount'));
$('#render2').text($(this).currencyField('formattedAmount'));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment