Created
August 28, 2017 11:58
-
-
Save connected/96c526468c98a107fed7784c5a96886f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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