In JavaScript, I need validate phone numbers without using regular expressions (must be with string manipulation). The phone numbers have to be in one of the following formats:
123-456-7890
1234567890
(123)4567890
(123)456-7890
Then I must also provide an alert if the phone number isn't in one of the formats listed above.
I have only been able to manage to get #2 working, which looks something like this:
function len(gth)
{
if (gth.value.length != 10)
{
alert("Telephone numbers MUST be 10 digits!");
}
}
which down in the HTML it would call up to the function:
<p>Phone: <input id = "phone" onblur="len(this)" name = "Phone" size = "20" type = "text" maxlength = "10"> </p>
Since you need a solution without regex, I believe this should work.
const phones = [
'123-456-7890',
'1234567890',
'(123)4567890',
'(123)456-7890',
'+61(123) 456-7890',
'12345',
'))))01/34$89.77(99'
]
function len(gth) {
if (gth.substring(3, 4) == '-' && gth.substring(7, 8) == '-') // 123-456-7890
gth = gth.replace('-', '').replace('-', '');
else if (gth.substring(0, 1) == '(' && gth.substring(4, 5) == ')' && gth.substring(8, 9) == '-') // (123)456-7890
gth = gth.replace('(', '').replace(')', '').replace('-', '');
else if (gth.substring(0, 1) == '(' && gth.substring(4, 5) == ')') // (123)4567890
gth = gth.replace('(', '').replace(')', '');
if (!isNaN(gth) && gth.length == 10) {
return true;
}
alert("Telephone numbers:" + gth + " MUST be 10 digits!");
}
phones.forEach(len)
I would replace the numbers with something like x, then check against predefined patterns:
function check(num) {
let pattern = '';
for (let i = 0; i < num.length; i++) {
pattern += num[i] >= '0' && num[i] <= '9' ? 'x' : num[i];
}
return ['xxx-xxx-xxxx', 'xxxxxxxxxx', '(xxx)xxxxxxx', '(xxx)xxx-xxxx']
.indexOf(pattern) >= 0;
}
For extra credit, find the bug in the above program.
However, you don't really need to do any of this. You should be able to use the pattern attribute on the input element. That will also provide a better user experience. For instance, you can style the input element using the :invalid pseudo-class, by putting a red border around it for example, to give the user real-time feedback that their input is not valid. Yes, that takes a regular expression--what was your reason for not wanting to use a regular expression again?
You can make it manually be:
Checking string size if it is the expected or not
split the string to char array then parse them as integers inside a try block if numberFormatException is thrown it should be a bracket ( ) or -
Basic example of extracting the input data to Array
function test() {
var phnTest = document.getElementById('phone').value;
var strArray = [];
strArray = phnTest.split('');
document.getElementById('p').innerHTML = strArray;
}
<form action="demo_form.asp">
Phone <input id="phone" type="text" name="phone"><br>
<input type="button" value='Submit' onclick="test()">
</form>
<p id='p'></p>
This is dependent on how the data is structured, if you need to search a body of text and so on, but basics would be...
If it's a simple pull from an <input>, grab the data...
Take the input data, and generate an array with each character. You could then test, say strArray[3], for a dash or a dot. If not present, it can continue along to check for seven numbers in a row and so on.
This is going to be extremely consuming and require a number of conditionals to be checked. I assume the "without RegEx" is a requirement for a project or such, if not, recommend learning and using RegEx.
Hope this gets you going.
This is my attempt. The key is creating an array from the string then filtering out any non numerical characters. It would be easier to use regular expression though. just
number.replace(/(\D+)/g, '')
const numbers = [
'123-456-7890',
'1234567890',
'(123)4567890',
'(123)456-7890',
'+61(123) 456-7890',
'12345',
'))))01/34$89.77(99'
]
// validate a phone number
function validate(number) {
const digits = clean(number)
console.log({
number,
digits,
length: digits.length,
pass: digits.length === 10
})
}
// remove any non digits from the number
function clean(number) {
return Array.from(number).filter(char => {
return !isNaN(char) && char !== ' '
}).join('')
}
numbers.forEach(validate)
Related
I have been working on a simple JS calculator using an OOP approach. I am struggling to create a fix that prevents the input of extra decimals. For example, a user can input 3.2.1.5. Ideally, this calculator would display the entire expression on the digital calculator screen before solving it and returning the result. With this in mind, simply preventing a user from adding a second decimal would prevent them from adding(or whatever operator they may choose) multiple decimals together. I have considered using .split() and .join() on operators in the input, but it is beginning to get convoluted as there are multiple operators to consider. Ideally, I want to avoid regex.
const keys = document.querySelector('.calc-buttons');
keys.addEventListener('click', event => {
const {target} = event
const {value} = target
if(!target.matches('button')){
return
}else{
calculator.parseInput(value)
//console.log(value)
}
})
const calculator = {
displayText: '0',
prevTotal: null,
parseInput(value){
//have any of the special buttons(AC, decimal, =) been clicked?
switch(value){
case '=':
//calculate answer
this.calcAnswer(this.displayText)
break
case 'AC':
//clear screen & stored values
this.clearAll()
break
case '.':
//create decimal
if(this.displayText == 0){
//pass'0.'
this.addText('0.')
}else{
//add value to text string
this.addText(value)
}
break
default:
//add value to text string
this.addText(value)
break
}
},
addText(value){
if(this.displayText == '0'){
this.displayText = ''
}else if(this.prevTotal !== null){
this.displayText = this.prevTotal
this.prevTotal = null
}
//check if previous input is a number
if(isNaN(+(value)) && isNaN(+(this.displayText))){
if(isNaN(this.displayText.slice(-1))){
return
}
}else if(value == '.' && this.displayText.slice(-1) == '.'){
return
}
this.displayText += value
//output display text to screen
this.outputText(this.displayText)
},
outputText(text){
document.querySelector('.screen').value = text
},
calcAnswer(equation){
let result = Function("return " + equation)()
this.outputText(result)
//console.log(equation)
//console.log(result)
this.prevTotal = result
},
clearAll(){
this.displayText = '0',
this.prevTotal = null
this.outputText(this.displayText)
}
}
Functions are based on StepUp's answer (which is wrong AFAIK; it should be .length > 2 but I can't comment yet)
const hasManySymbols = (str, symbol) => {
const firstIndex = str.indexOf(symbol) // find the first occurrence of the symbol
if(firstIndex == -1) return false // if there is no first occurrence there are not many symbols
return str.indexOf(symbol, firstIndex + 1) != -1 // whether or not there is a second occurrence
}
const validate = str => hasManySymbols(str, '.') ? 'invalid input' : 'valid input'
console.log(validate('1.23')) // "valid input"
console.log(validate('1.2.3')) // "invalid input"
I'm not sure if this is faster or slower but it should theoretically be faster I guess.
You can create a simple function to avoid repetition of code and hiding unnecessary details in functions. In addition, it helps to reduce convolution.
So create a function which will check eligibility of input and based on result just notify user or remove last incorrect character.
The sketch of function could like this:
const hasManySigns = (str, sign) => str.split(sign).length > 2
An example:
const hasManySigns = (str, sign) => str.split(sign).length > 2
let foo = '1.2.3'
const validate = str => hasManySigns(str, '.') ? 'incorrect input' : 'correct input'
console.log(validate(foo))
I have a function to validate phone number in a contact form, but i need to be able to put in "xxx xxx xxxx" for example, and not just "xxxxxxxx"
The number format should be:
xxx xxx xxxx
xxx-xxx-xxxx
xxx.xxx.xxxx
function validatePhone() {
var phone = document.getElementById("phone").value;
if (phone.length == 0) {
var w = document.getElementById("phoneError").textContent;
alert(w);
return false;
}
if (phone.length != 10) {
var r = document.getElementById("phoneError").textContent;
alert(r);
return false;
}
// THIS IS NOT WORKING
if (
!phone.match(/^[0-9]{10}$/) ||
!phone.match(/^\d{3}-\d{3}-\d{4}$/) ||
!phone.match(/^\d{3}.\d{3}.\d{4}$/)
) {
var t = document.getElementById("phoneError").textContent;
alert(t);
return false;
}
}
Two things: First, you are mixing up AND and OR:
if (
!phone.match(/^[0-9]{10}$/) ||
!phone.match(/^\d{3}-\d{3}-\d{4}$/) ||
!phone.match(/^\d{3}.\d{3}.\d{4}$/)
) {
As soon as one of the conditions fails, it will return false (which is basically always). You want this if to apply, when none of the expressions matches, e.g. when all of them are false. Therefor, you have to use && instead of ||. Not a AND not b AND not c.
Second: your 3rd regex is a bit off: . means "any character", so this regex would also match "123x123y1234". You need to escape the dot with a backslash: /^\d{3}\.\d{3}\.\d{4}$/
Also, you can improve this code significantly. You have 5 conditions, which could all be handled in one (if you want to allow the input of "123.123 234", otherwise you will have to do it using 3 regex). And for just checking if a regex matches a string, you maybe should use test(), because it is just slightly faster (it won't matter in your case, but just out of principle).
You can reduce your code to:
if (/^\d{3}[\s-.]\d{3}[\s-.]\d{4}$/.test(document.getElementById("phone").value) === false) {
alert (document.getElementById("phoneError").textContent);
return false;
}
I've been doing a lot of searching, chopping and changing, but I'm...slightly lost, especially with regards to many of the regex examples I've been seeing.
This is what I want to do:
I have a text input field, size 32.
I want users to enter their telephone numbers in it, but I want them to enter a minimum of 10 numbers, separated by a single comma. Example:
E.g. 1
0123456789,0123456789 = right (first group is >=10 numbers, second group = >=10 numbers & groups are separated by a single comma, no spaces or other symbols)
E.g. 2
0123456789,,0123456789 = wrong (because there are 2 commas)
E.g. 3
0123456789,0123456789,0123456789 = right (same concept as E.g. 1, but with 3 groups)
I've got the following, but it does not limit the comma to 1 per 10 numbers, and it does not impose a minimum character count on the number group.
$(document).ready(function(){
$("#lastname").keypress(function (e) {
//if the letter is not digit then display error and don't type anything
if (e.which != 8 && e.which != 0 && String.fromCharCode(e.which) != ','
&& (e.which < 48 || e.which > 57)) {
//display error message
$("#errmsg").html("Digits Only").show().fadeOut("slow");
return false;
}
});
});
Preferably, I'd like to warn the user of where they are going wrong as well. For example, if they try to enter two commas, I'd like to specifically point that out in the error, or if they havent inserted enough numbers, i'd like to specifically point that out in the error. I'd also like to point out in the error when neither a number or a comma is inserted. I'd like to ensure that the tab, and F5 keys are not disabled on the keyboard as well. And very importantly, I'd like to specifically detect when the plus or addition key is used, and give a different error there. I think I'm asking for something a little complex and uninviting so sorry :/
The example code I provided above works pretty well across all browsers, but it doesn't have any of the minimum or maximum limits on anything I've alluded to above.
Any help would be appreciated.
As far as a regex that will check that the input is valid (1-3 phone numbers of exactly 10 digits, separated by single commas), you can do this:
^\d{10}(,\d{10}){0,2}$
Try like the below snippet without Regex
var errrorMessage = '';
function validateLength (no) {
if(!no.length == 10) {
return false;
}
return true;
}
function validatePhoneNumbers (currentString, splitBy) {
if(currentString) {
var isValid = true,
currentList = currentString.split(splitBy);
// If there is only one email / some other separated strings, Trim and Return.
if(currentList.length == 1) {
errrorMessage = 'Invalid Length in Item: 1';
if(validateLength( currentString.trim() )) isValid = false;
}
else if(currentList.length > 1) {
// Iterating mainly to trim and validate.
for (var i = 0; i < currentList.length; i++) {
var listItem = currentList[i].trim();
if( validateLength(listItem ) ) {
isValid = false;
errrorMessage = 'Invalid Length in Item:' + i
break;
}
// else if for some other validation.
}
}
}
return isValid;
}
validatePhoneNumbers( $("#lastname").val() );
I have two text box in a form. One verifies for number only and another one for number and comma.
1st case number only.
function(textBoxObject) {
var that = $(this),
val = that.val();
if (val === "" || isNaN(val)) {
that.addClass("error");
} else {
that.removeClass("error");
}
}
2nd case number and comma.
How do I handle another textbox which takes numbers and commas? And is it possible to add the logic in the first function itself?
I assume you treat 12,34 as illegal and 1,234 as legal. Then here's the demo
function checkNumberWithComma(textBox) {
if ((textBox.value == 0 || textBox.value) && textBox.value.match(/^\d{0,3}(?:,\d{3})*$/)) {
$(textBox).removeClass("error");
}
else {
$(textBox).addClass("error");
}
}
And the regular expression:
^ means start
\d{0,3} means 0-3 digits
(?: means non-capturing group
,
\d{3} means 3 digits
)
* means repeat for 0 or more times
$ means end
You can use .indexOf() method.
something like...
if(val.indexOf(',') === -1) {
...your code here...
}
You could try and use if(val.match(/^(\d,?)*$/g))
It will allow an empty string, numbers and numbers seperated by commas. It does allow commas at the end of the string, though.
So, 1,2,3,4, 1234 and 1234, all pass, but ,12,34 and foo will fail.
Take a look a this codepen, I don't know exactly the behaviour you want but you can try something similar.
JS
$(function(){
function validateInput() {
var that = $(this),
val = that.val();
if (that.attr('data-type') === 'number') {
if (val === '' || isNaN(val)) that.addClass('error');
else that.removeClass('error');
}
else {
if (val.indexOf(',') === -1) that.addClass('error');
else that.removeClass('error');
}
}
$('input').change(validateInput);
});
HTML
<div>
<label> Number
<input type="text" data-type="number"/>
</label>
</div>
<div>
<label> Comma
<input type="text"/>
</label>
</div>
the question was accepting one or many ports that has one space between them with help of friends,
I used this one for my answer but for example if I enter 88888 it will alert me such this thing:
88888NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN is not correct
how can I correct this
<script type="text/javascript">
function portvalidating(field)
{
var output='';
m=field.value;
if(/^\d{1,5}([ ]\d{1,5})*$/.test(m))
{
var parts = m.split(' ');
for(i in parts)
{
var p= parseInt(parts[i]);
if(!((0 <= p) && (p<= 65535) && !isNaN(p)))
{
output+=p;
}
}
if(output=='')
var dummy=1;
else alert(output+'is not correct');
}
else alert('please enter a valid port!');
}
Unfortunately, regular expressions can't handle 'ranges', so you can't do this exactly as you want with regexp (therorically you can, but the regex would be hiper,hiper long).
However, you could validate your space-separated numbers with this regexp:
/^\d{1,5}([ ]\d{1,5})*$/
This will do what you want, except validating the range you supplied. But it controls that numbers have between 1 and 5 digits, and the other things you asked.
Hope this helps. Cheers
A crude regex without much error checking would be: exp = /\d{1,5}/g and then call .match(exp) on your string. However, you will need to use parseInt to convert the output to a number so that you can check it's value against your constraints.
I think you may be able to do this easier without Regex. Some quick code to split and parse a string is:
var s = "21 456 -32 70000";
var parts = s.split(' ');
var output;
for(i in parts)
{
p = parseInt(parts[i]);
if( (0 <= p) && (p <= 65535) && !isNaN(p) )
output += p+"<br />";
}
Hopefully this helps to some degree.
I think you would compromise your performance here if you want you are trying to validate a simple Integer value via RegEx.
IMO, try spiting the string with Space (' ') and and convert each value to Integer and perform myInt < 65535.
for( String str : portNumbers.split(' ') ){
try{
int i = Integer.parseInteger( str );
if( 0 > i && i > 65535 ){
errorMessage = str + " is out of range.";
}
}catch (NumberFormatException e) {
errorMessage = str + " is not a valid port.";
}
}
(6553[0-5]|655[0-2][0-9]|65[0-4][0-9][0-9]|6[0-4][0-9][0-9][0-9]|\d{2,4}|[1-9])