How can I mask an HTML input using javascript? - javascript

How can I mask a US phone using javascript on an HTML control.
I would like the input to force the text to be in the following format:
[(111)111-1111]
Here is what I have currently:
mask(str, textbox, loc, delim) {
var locs = loc.split(',');
for (var i = 0; i <= locs.length; i++) {
for (var k = 0; k <= str.length; k++)
{
if (k == locs[i]) {
if (str.substring(k, k + 1) != delim) {
str = str.substring(0,k) + delim + str.substring(k,str.length)
}
}
}
}
textbox.value = str
}

There are three common ways for handling phone number input of a guaranteed format:
1. Accept all numerical input anyway
The likelihood of users with obscure numbers but still living in the US is higher than ever. Accepting all kinds of numerical input alleviates the concern as the number will only be useless if they gave you either not enough numbers or the wrong ones.
2. Split it into three text boxes of fixed lengths
A lot of financial software does this. Not sure why, specifically, but it seems to be rather frequent there. A recommendation is to advance the cursor after keypress to the next box if they've typed the max limit on the textboxes. Also, this guarantees you will get the numbers in whatever format you're expecting, because you can just append the resulting post variables together.
Example of the HTML:
<input id="phonePart1" maxlength="3" name="phonePart1"/>
<input id="phonePart2" maxlength="3" name="phonePart2"/>
<input id="phonePart3" maxlength="4" name="phonePart3"/>
and a little jQuery snippet to merge the three in your format:
var phonePart1 = parseInt($("#phonePart1").val(), 10);
var phonePart2 = parseInt($("#phonePart2").val(), 10);
var phonePart3 = parseInt($("#phonePart3").val(), 10);
var phone = "(";
if (isNaN(phonePart1)||isNaN(phonePart2)||isNan(phonePart3)) {
// Incorrect format
} else {
phone = phone + phonePart1 + ")" + phonePart2 + "-" + phonePart3;
}
3. Use a regular expression to match the number format
You can use a combination of regular expressions to match multiple numbers, or explicitly the one you are asking about. This is probably the technique you're looking for.
This is the regular expression:
/\([0-9]{3}\)[0-9]{3}-[0-9]{4}/
You'd use it like this:
if (yourphonevariable.match(/\([0-9]{3}\)[0-9]{3}-[0-9]{4}/))
{
// it's valid
}
4. If you're looking to format the text itself with a mask...
Consider the jQuery plugin at http://digitalbush.com/projects/masked-input-plugin/. User #John Gietzen suggested this to me outside of this post, so feel free to give him kudos for it.

Related

Is there a way to stop the user from typing in a textbox after they enter a bad character?

I don't want to disable the input box, I'd like to either delete the bad character or allow the user to delete it.
So far I've tried to set the max length of the input to the length where the bad character was entered, but I was still able to type after that.
Here is a sample of the function I'm working on:
function validateCharacterName() {
var value = document.getElementById("characterName").value;
var message = document.getElementById("characterNameMessage");
var button = document.getElementById("confirmButton")
if (value.length <= 1) {
message.innerText = "Name must be two or more characters."
disableButton(button)
} else {
for (var counter = 0 ; counter < value.length; counter++) {
var character = value.charAt(counter);
if (isAlpha(character) && !isDigit(character)) {
message.innerText = "";
enableButton(button);
} else {
message.innerText = "Character '" + character + "' is invalid.";
disableButton(button);
}
}
}
}
The recommended way to ensure the entered text only contains expected characters is using the the pattern attribute. This works slightly different than you suggest, but will be more in line of what the user would expect, as it is a very common way how to do this. Here you can see this in action.
To be specific here is an example how you avoid the letter "a":
<input type="text" pattern="[^a]*" title="Please avoid the letter 'a'">
The pattern attribute uses regular expressions. This does need some getting used to, but is rather powerful. In this case the ^ insider the [] means "not". The a means "a" and the * means allow any number of appearances of the previous thing. In summary this means allow any number of any character not being an "a".
You might want to use a whitelist approach rather than a blacklist approach. For example to allow any Latin letters you could use:
<input type="text" pattern="[a-zA-Z]*" title="Please use letters only">

different value types in javascript alert?

In strictly native JS, is there a way to display a string and variable in one alert window (or other window)? For now, let's ignore fancy things like jQuery, Vue, Node, etc.
var testNumber = prompt("Enter a number. Let us see how many even numbers
are therein.");
var countEvens = 0;
for (var i = 0; i <= testNumber; i++) {
if (i % 2 === 0){
countEvens++;
}
}
alert("There are " countEvens " even numbers in" testNumber);
Obviously you can. just ad + operator to concatenate. alert("There are " +countEvens +"even numbers in"+testNumber);
var testNumber = prompt("Enter a number. Let us see how many even numbers are therein.");
var countEvens = 0;
for (var i = 0; i <= testNumber; i++) {
if (i % 2 === 0){
countEvens++;
}
}
alert("There are " +countEvens +" even numbers in" +testNumber);
In strictly native JS, there is no alert or any other mechanism for showing output. JS depends on the host environment to provide that sort of API.
A web browser's alert method will pay attention only to the first argument, which it converts to a string if it isn't one already.
If you want to construct your string from multiple variables and literals you can use concatenation:
alert("There are " + countEvens + " even numbers in " + testNumber);
or template strings:
alert(`There are ${countEvens} even numbers in ${testNumber}`);

Validate particular range using regex

I want validate text box with particular range having format like :
1-99
I am using regex :
/^(?:100|[1-9]\d|\d)-(?:100|[1-9]\d|\d)$/
It works for me but little problem that is it accept this:
55-50
And it shouldn't, this is wrong.
how can I correct this?
As it has been told early regexp is not the method for validating ranges. The better way is to use if/else statements. But you are not restricted in usage of regexp for validating input string on the particular format.
F.i., if you'd like to enable the end user to enter the range in the format number1-number2, you could check the string for compliance to this format and check its parts for complaince to the condition number1 <= number2. If all these checks are done you could do something useful or decline, if checks are fail.
function validRange(rangeStr, min, max) {
var m = rangeStr.match(/^([0-9]+)-([0-9]+)$/);
if ( m && m[1] >= min && m[2] <= max && m[1] <= m[2] ) {
return true;
}
return false;
}
var s = '1-99';
var s = '55-50';
if ( validRange(s, 1, 99) ) {
// do something useful
}
The code above is just skeleton for the further improvements but it can be used now. But the code could be too complicated, if you or your customers will request to implement something more complex like ability to enter single number, lists of numbers (separated with comma, semicolons etc), mixed ranges or any combination of all of them.
Because you need to check validation between the both number you have to use logical operations to check if the forst number is less than second, so you couldn't use regex in this case instead use if/else statement :
var input = "55-50";
if(input.indexOf('-')){
var input_arr = input.split('-');
if(input_arr.length==2 && parseInt(input_arr[0])<parseInt(input_arr[1]))
alert("Accepted");
else
alert("Not accepted");
}

How to find total possible values from length and characters?

I'm totally not a Math whiz kid here, but have put together a function with the great help of StackOverflow (and a lot of trial and error) that generates a random serial number from a Formula, group of Letters/Numbers, and array (so as to not duplicate values).
So, my current formula is as follows:
$.extend({
generateSerial: function(formula, chrs, checks) {
var formula = formula && formula != "" ? formula : 'XXX-XXX-XXX-XXX-XXX', // Default Formula to use, should change to what's most commonly used!
chrs = chrs && chrs != "" ? chrs : "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", // Default characters to randomize, if not defined!
len = (formula.match(/X/g) || []).length,
indices = [],
rand;
// Get all "-" char indexes
for(var i=0; i < formula.length; i++) {
if (formula[i] === "-") indices.push(i);
}
do {
rand = Array(len).join().split(',').map(function() {
return chrs.charAt(Math.floor(Math.random() * chrs.length));
}).join('');
// Rebuild string!
if (indices && indices.length > 0)
{
for(var x=0; x < indices.length; x++)
rand = rand.insert(indices[x], '-');
}
} while (checks && $.inArray(rand, checks) !== -1);
return rand;
}
});
Ok, so, what I need to be able to do is to find total possible values and make sure that it is possible to generate a unique serial number before actually doing so.
For example:
var num = $.generateSerial('XX', 'AB', new Array('AB', 'BA', 'AA', 'BB'));
This will cause the code to do an infinite loop, since there are no more possibilties here, other than the ones being excluded from the extension. So this will cause browser to crash. What I need to be able to do here is to be able to get the number of possible unique values here and if it is greater than 0, continue, otherwise, don't continue, maybe an alert for an error would be fine.
Also, keep in mind, could also do this in a loop so as to not repeat serials already generated:
var currSerials = [];
for (var x = 0; x < 5; x++)
{
var output = $.generateSerial('XXX-XXX-XXX', '0123456789', currSerials);
currSerials.push(output);
}
But the important thing here, is how to get total possible unique values from within the generateSerial function itself? We have the length, characters, and exclusions array also in here (checks). This would seem more like a math question, and I'm not expert in Math. Could use some help here.
Thanks guys :)
Here is a jsFiddle of it working nicely because there are more possible choices than 16: http://jsfiddle.net/qpw66bwb/1/
And here is a jsFiddle of the problem I am facing: Just click the "Generate Serials" button to see the problem (it continuously loops, never finishes), it wants to create 16 serials, but 16 possible choices are not even possible with 2 characters and only using A and B characters: http://jsfiddle.net/qpw66bwb/2/
I need to catch the loop here and exit out of it, if it is not able to generate a random number somehow. But how?
The number of possible serials is len * chrs.length, assuming all the characters in chrs are different. The serial contains len characters to fill in randomly, and chrs.length is the number of possible characters in each position of that.

Javascript regex for GMail-style email address validation

I need a regular expression that will accept well-formed emails in several formats (see below) that will be input in a comma-separated list. I have the basic email address
validation regex,
^[\w\d._%+-]+#(?:[\w\d-]+\.)+(\w{2,})(,|$)
which can handle test cases A and B, but not the others. I also tried
^(\<)?[\w\d._%+-]+#(?:[\w\d-]+\.)+(\w{2,})(\>)?(,|$)
which was able to handle A, B, and C, but only validated the first email address in each of test cases D and E. I haven't even gotten to testing a regex for format 3.
tl;dr Need a regex that will validate email addresses 1, 2, and 3.
Good website to test your regular expressions: Online Javascript Regex Tester
Data
Test Cases
A. nora#example.com
B. nora#example.com, fred#example.com
C. <nora#example.com>, fred#example.com
D. <nora#example.com>, <fred#example.com>
E. fred#example.com, <nora#example.com>
Email Address Formats
1. xyz#example.com
2. <xyz#example.com>
3. "xyz"<xyz#example.com>
EDIT
I flagged this as a possible duplicate of:
Validate email address in JavaScript?
which, in turn, seems to be a duplicate of:
Using a regular expression to validate an email address
both of which contain much discussion on the validity of regex as email validation. However, the top-voted regexes provided don't seem to do quite what I want so I don't consider this answered yet.
None of the links or answers provided was the best answer for this question. Here's what solved it:
/*
* regex checks: must start with the beginning of a word or a left caret
* must end with either the end of a word or a right caret
* can handle example.example.com as possible domain
* email username can have + - _ and .
* not case sensitive
*/
var EMAIL_REGEX = /(\<|^)[\w\d._%+-]+#(?:[\w\d-]+\.)+(\w{2,})(\>|$)/i;
var emails = emailList.trim().split(',');
var validEmails = [];
var invalidEmails = [];
for (var i = 0; i < emails.length; i++) {
var current = emails[i].trim();
if(current !== "") {
//if something matching the regex can be found in the string
if(current.search(EMAIL_REGEX) !== -1) {
//check if it has either a front or back bracket
if(current.indexOf("<") > -1 || current.indexOf(">") > -1) {
//if it has both, find the email address in the string
if(current.indexOf("<") > -1 && current.indexOf(">") > -1) {
current = current.substr(current.indexOf("<")+1, current.indexOf(">")-current.indexOf("<") -1);
}
}
}
if(EMAIL_REGEX.test(current)) {
validEmails.push(current);
} else {
invalidEmails.push(current);
}
}
}
It would be simpler to first split the comma-separated list into an array, and validate each member of the array individually. That would make the regex easier to write (and read and maintain), and also give you the ability to provide specific feedback to the user who entered the list ("the 3rd email address is invalid").
So assuming you did that with a split
var bits = csv.split(',');
Iterate through the bits array
for (var i = 0; i < bits.length; ++i) {
if (!validateEmail(bits[i])) {
alert("Email #" + (i+1) + " is bogus");
}
}
Then for the regex, something like this will capture 2 and 3
(\"[a-z0-9\s]+\"\s+)?\<[\w\d._%+-]+#(?:[\w\d-]+\.)+(\w{2,})\>
And you can use the simpler one to capture simple email addresses without the < or the name in quotes in front of it.
A single regex will not necessarily run any faster than two if tests, especially if you short-circuit the or by putting the more likely one first. It's also harder to read and maintain. Lastly it's extra tricky because you need a lookahead: the final > is only ok if the string ahead of the email address includes a < right before the first character of the email.
So my $0.02 = not worth it. Just do two regexes.
This validateEmail function will check for the basic syntax of an email address (xyz#example.com).
The included ifs will check for the alternate formatting (<xyz#example.com>, 'xyz' <xyz#example.com>) and only validate the actual email portion.
Items with only < or > are deemed invalid for poor formatting (Nope#example.com>), same with any emails lacking the basic structure required (invalidExample.com).
var emailList = "abc#example.com,<lmn#example.com>,'xyz' <xyz#example.com>,invalidExample.com,Nope#example.com>,'Still93e-=48%5922=2 Good' <xyz#example.com>";
var emails = emailList.split(",");
//Loop through the array of emails
for (var i = 0; i < emails.length; i++) {
var isValid = 1;
var cur = emails[i];
// If it has a < or a >,
if( cur.indexOf("<") > -1 || cur.indexOf(">") > -1 ){
// Set it invalid
isValid = 0;
// But if it has both < and >
if( cur.indexOf("<") > -1 && cur.indexOf(">") > -1 ){
//Set it valid and set the cur email to the content between < and >
isValid = 1;
cur = cur.substr(cur.indexOf("<")+1, ( cur.indexOf(">") - cur.indexOf("<") - 1 ));
}
}
//Run the validate function
if ( !validateEmail(cur) )
isValid = 0;
// Output your results. valid = 1, not valid = 0
alert("Orig: "+emails[i] +"\nStripped: "+cur+"\nIs Valid: "+isValid);
}
function validateEmail(curEmail){
var emailValid = /.*\#.*\..*$/g;
return (curEmail.test(emailValid));
}
jsFiddle
Will something like this help?
I have tested 2. and 3., and it detects both the patterns.
var isEmail_re = /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\#[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/;
function isEmail (s) {
return String(s).search (isEmail_re) != -1;
}
alert(isEmail ('"xyz"<xyz#example.com>'));
http://jsfiddle.net/epinapala/BfKrR/

Categories