From 41232354ae0957a5fedc9f748daf1dd911f513f6 Mon Sep 17 00:00:00 2001 From: Stepan Date: Fri, 29 Aug 2014 13:41:14 +0600 Subject: [PATCH 1/5] Decimal dynamic and add static masked method 1. If decimalAfterDot = true, fractional number when the user presses a key and a dot or a comma, or integral number without a fraction. 2. Add static method masked. When you need only apply the mask to the tag. Without events. --- src/jquery.maskMoney.js | 610 +++++++++++++++++++++------------------- 1 file changed, 318 insertions(+), 292 deletions(-) diff --git a/src/jquery.maskMoney.js b/src/jquery.maskMoney.js index ec74807..8117540 100644 --- a/src/jquery.maskMoney.js +++ b/src/jquery.maskMoney.js @@ -18,6 +18,18 @@ return this; }, + masked : function(settings){ + var maskObj = maskClass.apply(this, [settings]), + $this = $(this); + + if ($this.is('input')) + $this.val(maskObj.maskValue($this.val())); + else + $this.text(maskObj.maskValue($this.text())); + + return $this; + }, + mask : function (value) { return this.each(function () { var $this = $(this), @@ -54,346 +66,360 @@ }, init : function (settings) { - settings = $.extend({ - prefix: "", - suffix: "", - affixesStay: true, - thousands: ",", - decimal: ".", - precision: 2, - allowZero: false, - allowNegative: false - }, settings); - return this.each(function () { - var $input = $(this), - onFocusValue; - - // data-* api - settings = $.extend(settings, $input.data()); - - function getInputSelection() { - var el = $input.get(0), - start = 0, - end = 0, - normalizedValue, - range, - textInputRange, - len, - endRange; - - if (typeof el.selectionStart === "number" && typeof el.selectionEnd === "number") { - start = el.selectionStart; - end = el.selectionEnd; - } else { - range = document.selection.createRange(); - - if (range && range.parentElement() === el) { - len = el.value.length; - normalizedValue = el.value.replace(/\r\n/g, "\n"); - - // Create a working TextRange that lives only in the input - textInputRange = el.createTextRange(); - textInputRange.moveToBookmark(range.getBookmark()); + var maskObj = maskClass.apply(this, [settings]), + $input = $(this); + + $input.unbind(".maskMoney"); + $input.bind("keypress.maskMoney", maskObj.keypressEvent); + $input.bind("keydown.maskMoney", maskObj.keydownEvent); + $input.bind("blur.maskMoney", maskObj.blurEvent); + $input.bind("focus.maskMoney", maskObj.focusEvent); + $input.bind("click.maskMoney", maskObj.clickEvent); + $input.bind("cut.maskMoney", maskObj.cutPasteEvent); + $input.bind("paste.maskMoney", maskObj.cutPasteEvent); + $input.bind("mask.maskMoney", maskObj.mask); + }); + } + }; - // Check if the start and end of the selection are at the very end - // of the input, since moveStart/moveEnd doesn't return what we want - // in those cases - endRange = el.createTextRange(); - endRange.collapse(false); + var maskClass = function(settings){ + var $input = $(this), + onFocusValue, + + settings = $.extend({ + prefix: "", + suffix: "", + affixesStay: true, + thousands: ",", + decimal: ".", + precision: 2, + allowZero: false, + allowNegative: false, + decimalAfterDot: false + }, settings, $input.data()); + + var handler = { + getInputSelection : function(){ + var el = $input.get(0), + start = 0, + end = 0, + normalizedValue, + range, + textInputRange, + len, + endRange; + + if (typeof el.selectionStart === "number" && typeof el.selectionEnd === "number") { + start = el.selectionStart; + end = el.selectionEnd; + } else { + range = document.selection.createRange(); + + if (range && range.parentElement() === el) { + len = el.value.length; + normalizedValue = el.value.replace(/\r\n/g, "\n"); + + // Create a working TextRange that lives only in the input + textInputRange = el.createTextRange(); + textInputRange.moveToBookmark(range.getBookmark()); + + // Check if the start and end of the selection are at the very end + // of the input, since moveStart/moveEnd doesn't return what we want + // in those cases + endRange = el.createTextRange(); + endRange.collapse(false); + + if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { + start = end = len; + } else { + start = -textInputRange.moveStart("character", -len); + start += normalizedValue.slice(0, start).split("\n").length - 1; - if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { - start = end = len; + if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { + end = len; } else { - start = -textInputRange.moveStart("character", -len); - start += normalizedValue.slice(0, start).split("\n").length - 1; - - if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { - end = len; - } else { - end = -textInputRange.moveEnd("character", -len); - end += normalizedValue.slice(0, end).split("\n").length - 1; - } + end = -textInputRange.moveEnd("character", -len); + end += normalizedValue.slice(0, end).split("\n").length - 1; } } } - - return { - start: start, - end: end - }; - } // getInputSelection - - function canInputMoreNumbers() { - var haventReachedMaxLength = !($input.val().length >= $input.attr("maxlength") && $input.attr("maxlength") >= 0), - selection = getInputSelection(), - start = selection.start, - end = selection.end, - haveNumberSelected = (selection.start !== selection.end && $input.val().substring(start, end).match(/\d/)) ? true : false, - startWithZero = ($input.val().substring(0, 1) === "0"); - return haventReachedMaxLength || haveNumberSelected || startWithZero; - } - - function setCursorPosition(pos) { - $input.each(function (index, elem) { - if (elem.setSelectionRange) { - elem.focus(); - elem.setSelectionRange(pos, pos); - } else if (elem.createTextRange) { - var range = elem.createTextRange(); - range.collapse(true); - range.moveEnd("character", pos); - range.moveStart("character", pos); - range.select(); - } - }); - } - - function setSymbol(value) { - var operator = ""; - if (value.indexOf("-") > -1) { - value = value.replace("-", ""); - operator = "-"; - } - return operator + settings.prefix + value + settings.suffix; } - function maskValue(value) { - var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "", - onlyNumbers = value.replace(/[^0-9]/g, ""), - integerPart = onlyNumbers.slice(0, onlyNumbers.length - settings.precision), - newValue, - decimalPart, - leadingZeros; - - // remove initial zeros - integerPart = integerPart.replace(/^0*/g, ""); - // put settings.thousands every 3 chars - integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, settings.thousands); - if (integerPart === "") { - integerPart = "0"; + return { + start: start, + end: end + }; + }, + + canInputMoreNumbers : function() { + var haventReachedMaxLength = !($input.val().length >= $input.attr("maxlength") && $input.attr("maxlength") >= 0), + selection = handler.getInputSelection(), + start = selection.start, + end = selection.end, + haveNumberSelected = (selection.start !== selection.end && $input.val().substring(start, end).match(/\d/)) ? true : false, + startWithZero = ($input.val().substring(0, 1) === "0"); + return haventReachedMaxLength || haveNumberSelected || startWithZero; + }, + + setCursorPosition : function(pos) { + $input.each(function (index, elem) { + if (elem.setSelectionRange) { + elem.focus(); + elem.setSelectionRange(pos, pos); + } else if (elem.createTextRange) { + var range = elem.createTextRange(); + range.collapse(true); + range.moveEnd("character", pos); + range.moveStart("character", pos); + range.select(); } - newValue = negative + integerPart; + }); + }, - if (settings.precision > 0) { - decimalPart = onlyNumbers.slice(onlyNumbers.length - settings.precision); - leadingZeros = new Array((settings.precision + 1) - decimalPart.length).join(0); - newValue += settings.decimal + leadingZeros + decimalPart; - } - return setSymbol(newValue); + setSymbol : function(value) { + var operator = ""; + if (value.indexOf("-") > -1) { + value = value.replace("-", ""); + operator = "-"; } - - function maskAndPosition(startPos) { - var originalLen = $input.val().length, - newLen; - $input.val(maskValue($input.val())); - newLen = $input.val().length; - startPos = startPos - (originalLen - newLen); - setCursorPosition(startPos); + return operator + settings.prefix + value + settings.suffix; + }, + + maskValue : function(value) { + var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "", + decimalAdd = handler.checkDecimalAfterDot(value), + onlyNumbers = value.replace(/[^0-9]/g, ""), + integerPart = decimalAdd || !settings.decimalAfterDot ? onlyNumbers.slice(0, onlyNumbers.length - settings.precision) : onlyNumbers, + newValue, + decimalPart, + leadingZeros; + + // remove initial zeros + integerPart = integerPart.replace(/^0*/g, ""); + // put settings.thousands every 3 chars + integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, settings.thousands); + if (integerPart === "") { + integerPart = "0"; } + newValue = negative + integerPart; - function mask() { - var value = $input.val(); - $input.val(maskValue(value)); + if (settings.precision > 0 && (decimalAdd || !settings.decimalAfterDot)) { + decimalPart = onlyNumbers.slice(onlyNumbers.length - settings.precision); + leadingZeros = new Array((settings.precision + 1) - decimalPart.length).join(0); + newValue += settings.decimal + leadingZeros + decimalPart; } - - function changeSign() { - var inputValue = $input.val(); - if (settings.allowNegative) { - if (inputValue !== "" && inputValue.charAt(0) === "-") { - return inputValue.replace("-", ""); - } else { - return "-" + inputValue; - } + + return handler.setSymbol(newValue); + }, + + maskAndPosition : function(startPos) { + var originalLen = $input.val().length, + newLen; + $input.val(handler.maskValue($input.val())); + newLen = $input.val().length; + startPos = startPos - (originalLen - newLen); + handler.setCursorPosition(startPos); + }, + + mask : function() { + var value = $input.val(); + $input.val(handler.maskValue(value)); + }, + + changeSign : function() { + var inputValue = $input.val(); + if (settings.allowNegative) { + if (inputValue !== "" && inputValue.charAt(0) === "-") { + return inputValue.replace("-", ""); } else { - return inputValue; + return "-" + inputValue; } + } else { + return inputValue; } + }, - function preventDefault(e) { - if (e.preventDefault) { //standard browsers - e.preventDefault(); - } else { // old internet explorer - e.returnValue = false; - } + preventDefault : function (e) { + if (e.preventDefault) { //standard browsers + e.preventDefault(); + } else { // old internet explorer + e.returnValue = false; } - - function keypressEvent(e) { - e = e || window.event; - var key = e.which || e.charCode || e.keyCode, - keyPressedChar, - selection, - startPos, - endPos, - value; - //added to handle an IE "special" event - if (key === undefined) { - return false; - } - - // any key except the numbers 0-9 - if (key < 48 || key > 57) { - // -(minus) key - if (key === 45) { - $input.val(changeSign()); - return false; - // +(plus) key - } else if (key === 43) { - $input.val($input.val().replace("-", "")); - return false; - // enter key or tab key - } else if (key === 13 || key === 9) { - return true; - } else if ($.browser.mozilla && (key === 37 || key === 39) && e.charCode === 0) { - // needed for left arrow key or right arrow key with firefox - // the charCode part is to avoid allowing "%"(e.charCode 0, e.keyCode 37) - return true; - } else { // any other key with keycode less than 48 and greater than 57 - preventDefault(e); - return true; - } - } else if (!canInputMoreNumbers()) { - return false; - } else { - preventDefault(e); - - keyPressedChar = String.fromCharCode(key); - selection = getInputSelection(); - startPos = selection.start; - endPos = selection.end; - value = $input.val(); - $input.val(value.substring(0, startPos) + keyPressedChar + value.substring(endPos, value.length)); - maskAndPosition(startPos + 1); - return false; - } + }, + + keypressEvent : function (e) { + e = e || window.event; + var key = e.which || e.charCode || e.keyCode, + keyPressedChar = String.fromCharCode(key), + needDecimalDot = handler.checkDecimalAfterDot(keyPressedChar), + selection, + startPos, + endPos, + value; + + //added to handle an IE "special" event + if (key === undefined) { + return false; } - function keydownEvent(e) { - e = e || window.event; - var key = e.which || e.charCode || e.keyCode, - selection, - startPos, - endPos, - value, - lastNumber; - //needed to handle an IE "special" event - if (key === undefined) { + // any key except the numbers 0-9 + if (!needDecimalDot && key < 48 || key > 57) { + // -(minus) key + if (key === 45) { + $input.val(handler.changeSign()); return false; + // +(plus) key + } else if (key === 43) { + $input.val($input.val().replace("-", "")); + return false; + // enter key or tab key + } else if (key === 13 || key === 9) { + return true; + } else if ($.browser.mozilla && (key === 37 || key === 39) && e.charCode === 0) { + // needed for left arrow key or right arrow key with firefox + // the charCode part is to avoid allowing "%"(e.charCode 0, e.keyCode 37) + return true; + } else { // any other key with keycode less than 48 and greater than 57 + handler.preventDefault(e); + return true; } + } else if (!needDecimalDot && !handler.canInputMoreNumbers()) { + return false; + } else { + handler.preventDefault(e); - selection = getInputSelection(); + selection = handler.getInputSelection(); startPos = selection.start; endPos = selection.end; + value = $input.val(); + $input.val(value.substring(0, startPos) + keyPressedChar + value.substring(endPos, value.length)); + handler.maskAndPosition(startPos + 1); + return false; + } + }, + + keydownEvent : function (e) { + e = e || window.event; + var key = e.which || e.charCode || e.keyCode, + selection, + startPos, + endPos, + value, + lastNumber; + //needed to handle an IE "special" event + if (key === undefined) { + return false; + } + + selection = handler.getInputSelection(); + startPos = selection.start; + endPos = selection.end; - if (key === 8 || key === 46 || key === 63272) { // backspace or delete key (with special case for safari) - preventDefault(e); - - value = $input.val(); - // not a selection - if (startPos === endPos) { - // backspace - if (key === 8) { - if (settings.suffix === "") { - startPos -= 1; - } else { - // needed to find the position of the last number to be erased - lastNumber = value.split("").reverse().join("").search(/\d/); - startPos = value.length - lastNumber - 1; - endPos = startPos + 1; - } - //delete + if (key === 8 || key === 46 || key === 63272) { // backspace or delete key (with special case for safari) + handler.preventDefault(e); + + value = $input.val(); + // not a selection + if (startPos === endPos) { + // backspace + if (key === 8) { + if (settings.suffix === "") { + startPos -= 1; } else { - endPos += 1; + // needed to find the position of the last number to be erased + lastNumber = value.split("").reverse().join("").search(/\d/); + startPos = value.length - lastNumber - 1; + endPos = startPos + 1; } + //delete + } else { + endPos += 1; } - - $input.val(value.substring(0, startPos) + value.substring(endPos, value.length)); - - maskAndPosition(startPos); - return false; - } else if (key === 9) { // tab key - return true; - } else { // any other key - return true; } - } - function focusEvent() { - onFocusValue = $input.val(); - mask(); - var input = $input.get(0), - textRange; - if (input.createTextRange) { - textRange = input.createTextRange(); - textRange.collapse(false); // set the cursor at the end of the input - textRange.select(); - } - } + $input.val(value.substring(0, startPos) + value.substring(endPos, value.length)); - function cutPasteEvent() { - setTimeout(function() { - mask(); - }, 0); + handler.maskAndPosition(startPos); + return false; + } else if (key === 9) { // tab key + return true; + } else { // any other key + return true; } - - function getDefaultMask() { - var n = parseFloat("0") / Math.pow(10, settings.precision); - return (n.toFixed(settings.precision)).replace(new RegExp("\\.", "g"), settings.decimal); + }, + + focusEvent : function () { + onFocusValue = $input.val(); + handler.mask(); + var input = $input.get(0), + textRange; + if (input.createTextRange) { + textRange = input.createTextRange(); + textRange.collapse(false); // set the cursor at the end of the input + textRange.select(); + } + }, + + cutPasteEvent : function () { + setTimeout(function() { + handler.mask(); + }, 0); + }, + + getDefaultMask : function () { + var n = parseFloat("0") / Math.pow(10, settings.precision); + return (n.toFixed(settings.precision)).replace(new RegExp("\\.", "g"), settings.decimal); + }, + + blurEvent : function (e) { + if ($.browser.msie) { + handler.keypressEvent(e); } - function blurEvent(e) { - if ($.browser.msie) { - keypressEvent(e); - } - - if ($input.val() === "" || $input.val() === setSymbol(getDefaultMask())) { - if (!settings.allowZero) { - $input.val(""); - } else if (!settings.affixesStay) { - $input.val(getDefaultMask()); - } else { - $input.val(setSymbol(getDefaultMask())); - } + if ($input.val() === "" || $input.val() === handler.setSymbol(handler.getDefaultMask())) { + if (!settings.allowZero) { + $input.val(""); + } else if (!settings.affixesStay) { + $input.val(handler.getDefaultMask()); } else { - if (!settings.affixesStay) { - var newValue = $input.val().replace(settings.prefix, "").replace(settings.suffix, ""); - $input.val(newValue); - } + $input.val(handler.setSymbol(handler.getDefaultMask())); } - if ($input.val() !== onFocusValue) { - $input.change(); + } else { + if (!settings.affixesStay) { + var newValue = $input.val().replace(settings.prefix, "").replace(settings.suffix, ""); + $input.val(newValue); } } - - function clickEvent() { - var input = $input.get(0), - length; - if (input.setSelectionRange) { - length = $input.val().length; - input.setSelectionRange(length, length); - } else { - $input.val($input.val()); - } + if ($input.val() !== onFocusValue) { + $input.change(); } + }, + + clickEvent : function () { + var input = $input.get(0), + length; + if (input.setSelectionRange) { + length = $input.val().length; + input.setSelectionRange(length, length); + } else { + $input.val($input.val()); + } + }, - $input.unbind(".maskMoney"); - $input.bind("keypress.maskMoney", keypressEvent); - $input.bind("keydown.maskMoney", keydownEvent); - $input.bind("blur.maskMoney", blurEvent); - $input.bind("focus.maskMoney", focusEvent); - $input.bind("click.maskMoney", clickEvent); - $input.bind("cut.maskMoney", cutPasteEvent); - $input.bind("paste.maskMoney", cutPasteEvent); - $input.bind("mask.maskMoney", mask); - }); - } + checkDecimalAfterDot : function (string){ + return settings.decimalAfterDot && new RegExp('[.,'+(!/[.,\s]/.test(settings.decimal) ? settings.decimal : '')+'](?:\\d+)?$').test(string); + } + }; + + return handler; }; - + $.fn.maskMoney = function (method) { if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === "object" || ! method) { - return methods.init.apply(this, arguments); + return methods.init.apply(this, arguments);S } else { $.error("Method " + method + " does not exist on jQuery.maskMoney"); } From 16e90a366cf31431a37f6dd3b999f7a0bafe8271 Mon Sep 17 00:00:00 2001 From: Stepan Date: Fri, 29 Aug 2014 13:59:51 +0600 Subject: [PATCH 2/5] travis CI correct --- src/jquery.maskMoney.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jquery.maskMoney.js b/src/jquery.maskMoney.js index 8117540..70c79b9 100644 --- a/src/jquery.maskMoney.js +++ b/src/jquery.maskMoney.js @@ -22,11 +22,11 @@ var maskObj = maskClass.apply(this, [settings]), $this = $(this); - if ($this.is('input')) + if ($this.is("input")){ $this.val(maskObj.maskValue($this.val())); - else + } else { $this.text(maskObj.maskValue($this.text())); - + } return $this; }, @@ -85,7 +85,7 @@ var maskClass = function(settings){ var $input = $(this), - onFocusValue, + onFocusValue; settings = $.extend({ prefix: "", @@ -408,7 +408,7 @@ }, checkDecimalAfterDot : function (string){ - return settings.decimalAfterDot && new RegExp('[.,'+(!/[.,\s]/.test(settings.decimal) ? settings.decimal : '')+'](?:\\d+)?$').test(string); + return settings.decimalAfterDot && new RegExp("[.,"+(!/[.,\s]/.test(settings.decimal) ? settings.decimal : "")+"](?:\\d+)?$").test(string); } }; @@ -419,7 +419,7 @@ if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === "object" || ! method) { - return methods.init.apply(this, arguments);S + return methods.init.apply(this, arguments); } else { $.error("Method " + method + " does not exist on jQuery.maskMoney"); } From 4782d6dbcdf9256988d071ac83d310d9ceb1bb08 Mon Sep 17 00:00:00 2001 From: Stepan Date: Wed, 3 Sep 2014 13:59:18 +0600 Subject: [PATCH 3/5] Apply mask for default value. --- src/jquery.maskMoney.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jquery.maskMoney.js b/src/jquery.maskMoney.js index 70c79b9..da910d0 100644 --- a/src/jquery.maskMoney.js +++ b/src/jquery.maskMoney.js @@ -412,6 +412,8 @@ } }; + $input.val(handler.maskValue($input.val())); + return handler; }; From ef201b63ab862d84894567039c6ab67c5076eced Mon Sep 17 00:00:00 2001 From: Stepan Date: Wed, 3 Sep 2014 14:08:15 +0600 Subject: [PATCH 4/5] fix --- src/jquery.maskMoney.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jquery.maskMoney.js b/src/jquery.maskMoney.js index da910d0..e7b75d3 100644 --- a/src/jquery.maskMoney.js +++ b/src/jquery.maskMoney.js @@ -412,7 +412,8 @@ } }; - $input.val(handler.maskValue($input.val())); + if ($input.val() !== '') + $input.val(handler.maskValue($input.val())); return handler; }; From 2bb3091c76c391e546a7a113ebaa650f5d1a88d6 Mon Sep 17 00:00:00 2001 From: Stepan Date: Mon, 8 Sep 2014 11:33:04 +0600 Subject: [PATCH 5/5] Update jquery.maskMoney.js correct Travis --- src/jquery.maskMoney.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jquery.maskMoney.js b/src/jquery.maskMoney.js index e7b75d3..7d9b42b 100644 --- a/src/jquery.maskMoney.js +++ b/src/jquery.maskMoney.js @@ -412,9 +412,9 @@ } }; - if ($input.val() !== '') + if ($input.val() !== ""){ $input.val(handler.maskValue($input.val())); - + } return handler; };