Skip to content

Instantly share code, notes, and snippets.

@connected
Created August 28, 2017 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save connected/96c526468c98a107fed7784c5a96886f to your computer and use it in GitHub Desktop.
Save connected/96c526468c98a107fed7784c5a96886f to your computer and use it in GitHub Desktop.
/**
* jQuery moneyMask plugin
* This plugin depends on https://github.com/acdvorak/jquery.caret
*/
$.fn.moneyMask = function (options) {
/**
* @class MoneyMask
* @author Andrew Silin
*/
function MoneyMask($input, options) {
/**
* @type {MoneyMask} Self reference
*/
var _self;
/**
* Instance key/value settings object
* @type {Object}
*/
this.settings = {
regex: /^\d*[\.\,]?\d{0,2}$/,
ctrlKeys: [0, 8, 36, 35, 37, 39],
defaultValue: '0.00',
debug: false
};
/**
* jQuery wrapped input element
* @type {jQuery}
*/
this.$input;
/**
* @type {Boolean}
*/
this.pasted = false;
/**
* @type {Boolean}
*/
this.pristine = true;
/**
* Constructor.
*
* @param {jQuery} jQuery wrapped input element
* @param {Object} Options key/value object
*/
function _constructor($input, options) {
_self.$input = $input;
_self.$input
.on('keydown', _self.keyDownHandler)
.on('paste', _self.pasteHandler)
.on('input', _self.inputHandler)
.on('blur', _self.blurHandler)
.on('keypress', _self.keyPressHandler);
}
/**
* Blur event handler.
*
* @param {jQuery.Event}
*/
this.blurHandler = function (e) {
_self.log('BLUR', e.target.value);
if (!_self.isPristine()) {
_self.setInputValue(_self.format(parseFloat(e.target.value)));
}
};
/**
* Input event handler.
*
* @param {jQuery.Event}
*/
this.inputHandler = function (e) {
_self.log('INPUT', e.target.value);
if (_self.isPasted()) {
_self.setInputValue(_self.format(_self.sanitize(e.target.value)));
_self.setPasted(false);
}
};
/**
* Paste event handler.
*
* @param {jQuery.Event}
*/
this.pasteHandler = function (e) {
_self.log('PASTE');
_self.setPasted(true);
};
/**
* Keydown handler.
*
* @param {jQuery.Event}
*/
this.keyDownHandler = function (e) {
_self.log('KEYDOWN', e.keyCode, e.key);
// Detect FireFox paste action
if(e.ctrlKey && e.keyCode == 86) {
_self.setPasted(true);
}
};
/**
* Keypress event handler.
*
* @param {jQuery.Event}
*/
this.keyPressHandler = function (e) {
_self.log('KEYPRESS', e.keyCode, e.key);
if (_self.settings.ctrlKeys.indexOf(e.which) > -1 || e.metaKey) {
return void 0;
}
e.preventDefault();
var range = _self.fetchInputRange();
var valuestart = e.target.value.substring(0, range.start);
var valueend = e.target.value.substring(range.end);
var value = valuestart + e.key + valueend;
if (value === '0') {
return void (_self.setInputValue(value + '.'));
}
if (value === '.') {
return void _self.setInputValue('0.');
}
if (_self.settings.regex.test(value)) {
_self.setInputValue(_self.normalize(value));
_self.moveInputCarret(range.start + 1);
}
};
/**
* Normalize input value (type as you go replacements)
*
* @param {String}
* @return {String}
*/
this.normalize = function (value) {
return value.replace(',', '.');
};
/**
* Sanitize input value.
* Usually this is a value pasted into the input.
*
* @param {String}
* @return {String}
*/
this.sanitize = function (value) {
return parseFloat(value.replace(/[^\d\.]*/g, ''));
};
/**
* Format decimal value.
*
* @param {Number}
* @return {String}
*/
this.format = function (value) {
return (isNaN(value))? _self.settings.defaultValue : value.toFixed(2);
};
/**
* Check whether something had been pasted into input.
*
* @return {Boolean}
*/
this.isPasted = function () {
return _self.pasted;
};
/**
* Set whether something had been pasted into input.
*
* @param {Boolean}
* @return {MoneyMask} MoneyMask instance
*/
this.setPasted = function (pasted) {
_self.pasted = pasted;
return _self;
};
/**
* Check whether input value has ever been modified.
*
* @return {Boolean}
*/
this.isPristine = function () {
return _self.pristine;
}
/**
* Set whether input value has ever been modified.
*
* @param {Boolean}
* @return {MoneyMask} MoneyMask instance
*/
this.setPristine = function (pristine) {
_self.pristine = pristine;
return _self;
};
/**
* Set input value.
*
* @return {MoneyMask} MoneyMask instance
*/
this.setInputValue = function (value) {
_self.setPristine(false);
_self.$input.val(value);
return _self;
};
/**
* Get input selected text range object.
* @see https://github.com/acdvorak/jquery.caret
*
* Example:
* {
* end: 3,
* length: 4,
* start: 3,
* text: "1.23"
* }
*
* @return {MoneyMask} MoneyMask instance
*/
this.fetchInputRange = function () {
return _self.$input.range();
};
/**
* Move input caret to the specified position.
*
* @param {Number} position
* @return {MoneyMask} MoneyMask instance
*/
this.moveInputCarret = function (position) {
_self.$input.caret(position);
return _self;
};
/**
* Log something to console.
* This method output is controlled by this.settings.debug property.
*
* @param {...[*]}
* @return {MoneyMask} MoneyMask instance
*/
this.log = function (...args) {
if (_self.settings.debug) {
console.log(...args);
}
return _self;
};
_self = this;
_constructor($input, options);
}
return $.each(this, function () {
return new MoneyMask($(this));
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment