I have the following code to mask all but the the last 4 digits of a field, but when a user enters an alphanumeric in last 4 digits then it gives Null exception. Example input: 1a1a1a1a
How could I accept characters as well?
var mask = val.match(/^(.*?)(\d{4})$/);
return (mask[1] ? mask[1].replace(/\d/g, '*') : '') + (mask[2] ? mask[2] : '')
The return line is giving an error: Error: '1' is null or not an object
You don't need to use regex for this. Just use string length functions.
Here's a jQuery solution:
$(function() {
var contents = "";
$("#masking").blur(function() {
contents = $(this).val();
$(this).val(mask(contents));
});
$("#masking").focus(function() {
if (contents.length > 0) {
$(this).val(contents);
}
});
});
function mask(unmaskedValue) {
if (unmaskedValue.length > 1) {
var masked = "";
var remain = 0;
if (unmaskedValue.length <= 4) {
masked += "*";
remain = unmaskedValue.length - 1;
} else {
for (i = 0; i < unmaskedValue.length - 4; i++) {
masked += "*";
}
remain = 4;
}
masked += unmaskedValue.substring(unmaskedValue.length - remain, unmaskedValue.length);
return masked;
} else
return "";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Type:</label>
<input id="masking" type="text">
Related
I have already a code that format it to the correct number format but the problem is
1.The position of the number input after the first and second hyphen don't have correct position. Sample. When i Input 12345 after the first (-) it will be 123465 The position got swap.
2. The user cannot add in the middle of the number if it already reach the maximum number which. What is happening right now is if i click on the middle of the text box i can add numbers and all the last parts are replaced.
JSFIDDLE CODE
HTML + JS
Telephone: <input type="text" value="____-___-___" data-mask="____-___-___"/><br/>
Array.prototype.forEach.call(document.body.querySelectorAll("*[data-mask]"), applyDataMask);
function applyDataMask(field) {
var mask = field.dataset.mask.split('');
// For now, this just strips everything that's not a number
function stripMask(maskedData) {
function isDigit(char) {
return /\d/.test(char);
}
return maskedData.split('').filter(isDigit);
}
// Replace `_` characters with characters from `data`
function applyMask(data) {
return mask.map(function(char) {
if (char != '_') return char;
if (data.length == 0) return char;
return data.shift();
}).join('')
}
function reapplyMask(data) {
return applyMask(stripMask(data));
}
function changed() {
var oldStart = field.selectionStart;
var oldEnd = field.selectionEnd;
field.value = reapplyMask(field.value);
field.selectionStart = oldStart;
field.selectionEnd = oldEnd;
}
field.addEventListener('click', changed)
field.addEventListener('keyup', changed)
}
HTML:
<input id="txtPhone" data-mask="(___) ___-____" type="text" />
Javascript:
Array.prototype.forEach.call(document.body.querySelectorAll("*[data-mask]"), applyDataMask);
function applyDataMask(field) {
var mask = field.dataset.mask.split('');
// For now, this just strips everything that's not a number
function stripMask(maskedData) {
function isDigit(char) {
return /\d/.test(char);
}
return maskedData.split('').filter(isDigit);
}
// Replace `_` characters with characters from `data`
function applyMask(data) {
return mask.map(function (char) {
if (char != '_') return char;
if (data.length == 0) return char;
return data.shift();
}).join('')
}
function reapplyMask(data) {
return applyMask(stripMask(data));
}
function changed(e) {
var i = field.value.indexOf('_');
if (e.keyCode == undefined) {
i = 0;
}
field.value = reapplyMask(field.value);
field.selectionStart = i;
field.selectionEnd = i;
}
field.addEventListener('click', changed)
field.addEventListener('keyup', changed);
}
I am trying to validate user input in a text input field.
I have written a javascript function for the same purpose which fires on onkeyup event.
The goal is to only allow user input if it's a numeric value less than 100 and with at most 1 decimal place.
The function is working fine but if a enter an invalid character ,say 'a', it will flash in the input box before being removed.
What I want is that if the entered character violates the defined condition it should not appear in the input box (as it is flashing right now for a split second).
Here's my code:
function validatePercent(event) {
var txt = $("#tds_input").val();
// alert(event.source);
if (!parseInt(txt)) {
$("#tds_input").val('');
}
if (isNaN(txt / 1)) {
txt = txt.substr(0, txt.length - 1);
$("#tds_input").val(txt);
}
if (txt > 100) {
//alert(2);
txt = txt.toString();
txt = txt.substr(0, txt.length - 1);
$("#tds_input").val(txt);
}
txt = txt.toString();
if (txt.indexOf('.') > -1) {
if (txt.substr(txt.indexOf('.') + 1, txt.length).length > 1) {
txt = txt.substr(0, txt.length - 1);
$("#tds_input").val(txt);
}
}
}
Using type=number (and not text) can help
function validatePercent(event)
{
var txt=$("#tds_input").val();
if(!parseInt(txt))
{
$("#tds_input").val('');
}
if(isNaN(txt/1))
{
txt=txt.substr(0,txt.length-1);
$("#tds_input").val(txt);
}
if(txt>100)
{
txt=txt.toString();
txt=txt.substr(0,txt.length-1);
$("#tds_input").val(txt);
}
txt=txt.toString();
if(txt.indexOf('.')>-1)
{
if(txt.substr(txt.indexOf('.')+1,txt.length).length>1){
txt=txt.substr(0,txt.length-1);
$("#tds_input").val(txt);
}
}
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" id = "tds_input" onkeyup="validatePercent()">
UPDATED
You could store the value of the when the focus is in the input.
When the user enters a valid percentage (integer only), replace the value stored. When inputs is incorrect, just replace with the old value.
var decimalSeparator = 1.1.toLocaleString().replace(/\d/g, ''),
pattern1 = "^(\\d{1,3})?([",
pattern2 = "]?\\d{1})?$",
regex = new RegExp(pattern1+decimalSeparator+pattern2),
resetContent = function () {
$('#tds_input').val($('#tds_input').data('val'));
},
matchRegex = function (value) {
return value.match(regex);
};
$('#tds_input').bind('focusin', (e) => {
$('#tds_input').data('val', $('#tds_input').val());
});
// handle input (keys, paste)
$('#tds_input').bind('input', (e) => {
let txtValue = $('#tds_input').val();
// input is empty
if (txtValue === "") {
$('#tds_input').data('val', "");
return;
}
// value does not match regex
if (!matchRegex(txtValue)) {
// maybe it ends with the decimal character?
if (txtValue[txtValue.length - 1] === "." && txtValue !== "100.") {
// simulate the user enters a decimal next
if (matchRegex(txtValue + "1")) {
$('#tds_input').data('val', txtValue);
return;
}
}
resetContent();
return;
}
// check between 0 and 100
let value = parseFloat(txtValue);
if (value >= 0 && value <= 100) {
// store new valid number
$('#tds_input').data('val', value);
// put the value as an integer in the input
$('#tds_input').val(value);
return;
} else resetContent();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="tds_input"/>
In jqxwidget
http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxnumberinput/index.htm
by default the comma’s are already in place and separated by underscore.
what i want is to have the field empty and as soon as user starts typing the comma should come as and when similarly to F2 cell render-er.
so when typed 100 is should show 100
when typed 10000 ,it should show 10,000
also i have angular in my app as we are using jqxwidget in conjucation with so any angular way is also fine
one plugin i have found does the job but when focus out not when typing
https://www.npmjs.com/package/angular-numeric-directive
Hey I have solved this before by creating a directive that applies a filter to your HTML input. Here is a jsfiddle example
This is the directive. It both formats the user's input and keeps the cursor where the user is typing. My one issue with this is the logic behind where the cursor should be pointed.
fessmodule.directive('format', ['$filter', function ($filter) {
return {
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!ctrl) return;
var parts = attrs.format.split(':');
attrs.foramtType = parts[0];
attrs.pass = parts[1];
ctrl.$formatters.unshift(function (a) {
return $filter(attrs.foramtType)(ctrl.$modelValue, attrs.pass)
});
ctrl.$parsers.unshift(function (viewValue) {
var cursorPointer = elem.context.selectionStart;
var plainNumber = viewValue.replace(/[^\d|\-+|\.+]/g, '');
elem.val($filter(attrs.foramtType)(plainNumber, attrs.pass));
elem.context.setSelectionRange(cursorPointer, cursorPointer);
return plainNumber;
});
}
};
And the HTML to activate it
<input type="text" ng-model="test" format="number:2" />
Angular already provides pretty basic formatting filters
like
html : {{val | number:0}}
script: $scope.val = 1234.56789;
ref:
https://docs.angularjs.org/api/ng/filter/number
https://docs.angularjs.org/api/ng/filter/currency
https://scotch.io/tutorials/all-about-the-built-in-angularjs-filters
Demo
<input value="100000000" id="testInput" />
Simply apply this .formatInput(numberOfCharactersForSeparator, Separator ); to your input
$(document).ready(function()
{
$("#testInput").formatInput(3,"," );
});
using this plugin that i just made :p
$.fn.formatInput = (function(afterHowManyCharacter,commaType)
{
if(afterHowManyCharacter && commaType != ".")
{
var str = $(this).val();
var comma = commaType != undefined ? commaType : "," ;
var strMod ;
if($(this).val().indexOf(".") == -1)
strMod = replaceAll(comma,"",$(this).val());
else
{
strMod = replaceAll(comma,"",$(this).val());
strMod = strMod.substring(0,strMod.indexOf("."));
}
if($(this).val().indexOf(".") != -1)
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+ $(this).val().substring($(this).val().indexOf(".")));
else
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));
var nowPos = 0;
$(this).on("keyup",function(e)
{
nowPos = doGetCaretPosition($(this)[0]);
var codePressed = e.which ;
if(" 8 37 38 39 40 46 17".indexOf(" "+codePressed) == -1 && !e.ctrlKey)
{
if($(this).val().length >afterHowManyCharacter)
{
strMod ;
if($(this).val().indexOf(".") == -1)
strMod = replaceAll(comma,"",$(this).val());
else
{
strMod = replaceAll(comma,"",$(this).val());
strMod = strMod.substring(0,strMod.indexOf("."));
}
if($(this).val().indexOf(".") != -1)
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma )+ $(this).val().substring($(this).val().indexOf(".")));
else
$(this).val(splitByLength(strMod,afterHowManyCharacter).join( comma ));
if((strMod.length-1)%afterHowManyCharacter == 0)
{
setCursor($(this)[0],nowPos+1);
}
else
{
setCursor($(this)[0],nowPos);
}
}
}
});
}
else if( commaType == ".")
{
console.log("You can't use . as Separator");
}
function splitByLength(str,maxLength)
{
var reg = new RegExp(".{1,"+maxLength+"}","g"); ;
return reverseStringInArray(str.split("").reverse().join("").match(reg).reverse());
}
function replaceAll(find, replace, str) {
return str.replace(new RegExp(find, 'g'), replace);
}
function reverseStringInArray(arr)
{
$.each(arr,function(i,val)
{
arr[i] = arr[i].split("").reverse().join("");
});
return arr ;
}
// Author of setCursor is nemisj
function setCursor(node,pos)
{
node = (typeof node == "string" || node instanceof String) ? document.getElementById(node) : node;
if(!node){
return false;
}else if(node.createTextRange){
var textRange = node.createTextRange();
textRange.collapse(true);
textRange.moveEnd(pos);
textRange.moveStart(pos);
textRange.select();
return true;
}else if(node.setSelectionRange){
node.setSelectionRange(pos,pos);
return true;
}
return false;
}
// Author of setCursor is bezmax
function doGetCaretPosition (oField) {
// Initialize
var iCaretPos = 0;
// IE Support
if (document.selection) {
// Set focus on the element
oField.focus ();
// To get cursor position, get empty selection range
var oSel = document.selection.createRange ();
// Move selection start to 0 position
oSel.moveStart ('character', -oField.value.length);
// The caret position is selection length
iCaretPos = oSel.text.length;
}
// Firefox support
else if (oField.selectionStart || oField.selectionStart == '0')
iCaretPos = oField.selectionStart;
// Return results
return (iCaretPos);
}
});
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('app',[]);
app.controller('myCtrl',function($scope){
$scope.name = "1232.33";
$scope.changeFormat = function(value){
$scope.name = Number(value).toLocaleString('en');
}
});
</script>
<body>
<div ng-app="app" ng-controller="myCtrl">
<p>Input something in the input box:</p>
<p>Number: <input type="text" ng-model="name" placeholder="Enter name here" ng-blur="changeFormat(name)"></p>
<h1>Formatted value {{name}}</h1>
</div>
</body>
</html>
Here is a hackish solution. The idea is to watch for changes in the input text and format the input accordingly.
HTML
<div ng-controller="so">
<input ng-model="salary"></input>
</div>
Javascript
app.controller('so', function($scope) {
$scope.salary = '12567';
$scope.$watch('salary', function(){
// strip out all the commas and dots
var temp = $scope.salary;
if (!temp) return; // ignore empty input box
var lastChar = temp[temp.length-1];
if (lastChar === ',' || lastChar === '.') // skip it/allow commas
return;
var a = temp.replace(/,/g,''); //remove all commas
//console.log(a);
if (isNaN(a))
$scope.salary = temp.substring(0, temp.length-1); // last char was not right
else {
var n = parseInt(a, 10); // the integer part
var f = ''; // decimal part
if (a.indexOf('.') >= 0) // decimal present{
if (lastChar === '0') // 0's after decimal point are OK
return;
f = ('' + parseFloat(a)).substr(a.indexOf('.'));
}
var formatted_salary = '';
var count = 0;
var ns = '' + n; // string of integer part
for (var i=ns.length-1; i>=0; i--) {
if (count%3===0 && count>0)
formatted_salary = ',' + formatted_salary;
formatted_salary = ns[i] + formatted_salary;
count += 1;
}
formatted_salary = formatted_salary + (f ? f : '');
$scope.salary = formatted_salary;
}
})
})
Here is the JSFiddle
It gracefully handles things like
won't allow any characters other than numbers , and .
multiple commas and dots formatted correctly
PS:- you might want to handle the proper positioning of the caret yourself using text range. I haven't included that here.
100 => 100
1000 =>1,000
10000 => 10,000
100000 => 100,000
...
10000000 => 10,000,000
10000000.540 => 10,000,000.540
I use ng-change event to make this example
// on-change event
$scope.ngchanged = function (val) {
$scope.iputval = numberWithCommas(val);
};
function numberWithCommas(n) {
while (n.toString().indexOf(",") != -1)
{
n = n.replace(",", "");
}
var parts = n.toString().split(".");
return parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
}
Use it
<input type="text" ng-model="iputval" ng-change="ngchanged(iputval)" />
Updated add demo and code by following link
Full code and demo >> here
Please check out ng-number-input
I think it accomplishes the task easily.
https://www.npmjs.com/package/ng-number-input
I made it for my project and I thought I'd share it with the community.
Source code available on git hub and link is available in npm page.
Is there a way to limit the number of letters and numbers allowed to type in to an input field? I would like to only allow 3 letters and 2 numbers to be typed in, in whatever order.
Is this possible using the jQuery Mask Plugin? Or not?
See my jsFiddle here: http://jsfiddle.net/0akoL2x2/
html:
<input type="text" class="preview" size="30" placeholder="Preview text" class="text-input" maxlength="5" autofocus />
jquery:
jQuery('.personalisation').mask("XXXZZ", {
translation: {
'X': {pattern: /[A-Za-z0-9]/},
'Z': {pattern: /[A-Za-z0-9]/},
}
How about using a data attribute? Let's call it data-temp:
<input type="text" class="alnum" maxlength="5" data-temp="">
Use $(document).on('input'... to monitor all changes (even dynamic elements), and revert back immediately if the new value exceeds the maximum. Otherwise, let it happen, and update data-temp to this new value.
$(document).on('input', '.alnum', function(){
var txt = $(this).val();
if(
txt.replace(/[^0-9]/g,"").length > 2 ||
txt.replace(/[^A-Za-z]/g,"").length > 3 ||
txt.replace(/[a-zA-Z0-9]/g,"").length != 0
){
$(this).val( $(this).data('temp') );
return;
}
$(this).data('temp', txt);
});
JSFiddle demo
Here is a fiddle that works:
http://jsfiddle.net/igorshmigor/k2ss62gg/3/
The JS code looks like this:
var numberCountLimit = 2;
var letterCountLimit = 3;
$(document).ready(function() {
$('.preview').keypress(function(key) {
if (key.charCode == 0){
return true;
}
var current = $(this).val();
var filtered = current.replace(/[^a-z0-9]/gmi,'');
$(this).val(filtered);
var digits = filtered.replace(/[^0-9]/gmi,'');
var alpha = filtered.replace(/[^a-z]/gmi,'');
var digitCount = digits.length;
var alphaCount = alpha.length;
var isNumber = false;
var isAlpha = false;
if (key.charCode > 47 && key.charCode < 58){
isNumber = true;
if (digitCount >= numberCountLimit){
return false; // too many digits
}
}
if (key.charCode > 64 && key.charCode < 123){
isAlpha = true;
if (alphaCount >= letterCountLimit){
return false; // too many letters
}
}
if (!isAlpha && !isNumber){
return false;
}
});
});
P.S.: I don't think this can be done with just the jQuery Mask Plugin.
Give your text box an ID.
$("#box").mask('XXXZZ', {'translation': {
X: {pattern: /[A-Za-z0-9]/},
Z: {pattern: /[A-Za-z0-9]/}
}
});
JSFiddle
How about this, you hook the keypress and check the number/letter counters and if it exceeds you will just ignore the keypress (by returning false)
var numberCount = 0;
var numberCountLimit = 2;
var letterCount = 0;
var letterCountLimit = 3;
$(document).ready(function() {
$('.personalisation').keypress(function(key) {
var currentText = $(this).val();
numberCount = 0;
letterCount = 0;
for (var i = 0, len = currentText.length; i < len; i++) {
if(currentText.charCodeAt(i) < 48 || currentText.charCodeAt(i) > 57) {
//Is number
if((numberCount+1) > numberCountLimit) {
return false;
}
numberCount++;
} else {
//Is letter
if((letterCount+1) > letterCountLimit) {
return false;
}
letterCount++;
}
}
return true;
});
}
I have this input tag where you put the total of your receipt :
<input type="text" name="currency" id="currency" class="text-input" onBlur="this.value=formatCurrency(this.value);" />
The Javascript is as follows:
<script type="text/javascript">
function formatCurrency(num) {
num = num.toString().replace(/\$|\,/g,'');
if(isNaN(num)) {
num = "0";
}
sign = (num == (num = Math.abs(num)));
num = Math.floor(num*100+0.50000000001);
cents = num % 100;
num = Math.floor(num/100).toString();
if(cents < 10) {
cents = "0" + cents;
}
for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++) {
num = num.substring(0,num.length-(4*i+3))+','+num.substring(num.length-(4*i+3));
}
return (((sign)?'':'-') + '$' + num + '.' + cents);
}
</script>
Users can only enter receipts more than $10.00 bucks, how can I set that on my script? Also they need to know they can not enter currency less than $10.
From what I can gather from your question I think you are looking for something like this. Basically if we have a valid entry such as $100.00 we continue, return true etc, else if we have something that looks like an int or float we can reformat this and recurse the function, else hint user for of vaild entry
var foo = document.getElementById('foo');
foo.addEventListener('blur', function(e) {
var val = e.target.value;
var err = document.getElementById('err');
var errMsg = 'please enter a value $10.00 or greater';
var patt = /^\$\d+\.\d{2}$/;
var amount = parseInt(val.replace(/\$|\./g, ''));
if (val !== '') {
if (patt.test(val)) {
if (amount < 1000) {
err.textContent = errMsg;
} else {
document.getElementById('suc')
.textContent = 'processing request';
}
} else if (typeof amount == 'number' && !/[a-z]/g.test(val)) {
if (/\.\d{2}/.test(val)) {
e.target.value = '$' + (amount / 100);
} else {
e.target.value = '$' + amount + '.00';
}
arguments.callee(e);
} else {
err.textContent = errMsg;
}
}
});
here is a demo
You can apply a validation function when submitting the form to test if the value is below a threshold, such as:
function validate()
{
value = document.getElementById('currency');
if (value <= 10.00)
{
return false
} else
{
return true;
}
}
You could also apply this to the onblur event, but my preference is to present validation errors when the form is submitted.
It looks like you're trying to parse a string, convert it nicely into dollars and cents, and reject it if it's less than 10. There's a much nicer way to do that:
function formatCurrency(num) {
// Remove the dollar sign
num = num.replace("$", "");
// Change the string to a float, and limit to 2 decimal places
num = parseFloat(num);
Math.round(num * 100) / 100;
// If its less than 10, reject it
if(num < 10) {
alert("Too small!");
return false;
}
// Return a nice string
return "$" + num;
}
At the end, are you trying to return -$99.94 if the number is negative?