I need DRY validate function to make its shorter - javascript

I have a validation function were is some code is repeating, how I can make it more shorter.
function validated() {
if (user.value.length < 9) {
user.style.border = '1px solid red';
userError.style.display = 'block';
user.focus();
return false;
}
if (password.value.length < 9) {
password.style.border = '1px solid red';
passError.style.display = 'block';
password.focus();
return false;
}
}

function validateField(elt, errorElt, minLength) {
if (elt.value.length < minLength) {
elt.style.border = '1px solid red';
errorElt.style.display = 'block';
elt.focus();
return false;
}
return true;
}
function validated() {
return validateField(user, userError, 9) && validateField(password, passwordError, 9);
}

Related

How to make a loop wait for an event listener?

I am trying to create a coin toss game where you set the number of games you want to play, and then choose head or tails for each iteration. But my for loop doesen't wait for the eventListener and the loop is over before the user even clicked once.
function play(){
head.addEventListener("click", choice);
tails.addEventListener("click", choice);
}
function choice(e){
let random = Math.floor(Math.random() *2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
if (random == 0){
result.src = head.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
if (random == 1){
result.src = tails.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh(){
result.style.border = "none";
clicked.style.border = "none";
}
}
function wait(){
for (let i = 0; i < playAmount; i++){
console.log(i);
play();
}
}
wait();
Thank you in advance!
You can solve this problem without for loop.
Just take a variable count = 0 and flag = false at the starting .
Now just follow the program as under
var count = 0 , flag = true ;
flag&&head.addEventListener("click", choice);
flag&&tails.addEventListener("click", choice);
function choice(e){
if(count>=playAmount)flag=false;
else count++;
let random = Math.floor(Math.random() *2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
if (random == 0){
result.src = head.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
if (random == 1){
result.src = tails.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh(){
result.style.border = "none";
clicked.style.border = "none";
}
}
I hope this solves your problem .
Let us go through some key parts of your implementation(refer to my comments inline)
function play() {
head.addEventListener("click", choice);
tails.addEventListener("click", choice);
//the above 2 lines add a click event listener to the two buttons,
//that is, whenever these 2 buttons are clicked,
//the function `choice` will be called
}
function choice(e) {
let random = Math.floor(Math.random() * 2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
//the above 2 lines remove the click event listener from the two buttons
//that is, now the function `choice` will not be called at button click
if (random == 0) {
result.src = head.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
if (random == 1) {
result.src = tails.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh() {
result.style.border = "none";
clicked.style.border = "none";
}
}
function wait() {
for (let i = 0; i < playAmount; i++) {
console.log(i);
play();
//calls the play function `playAmount` times
}
}
wait();
Now let us discuss the problems with this approach
Calling the play() function playAmount times from wait() (tries to) binds(adds) the click event listener to both the buttons playAmount times, but adding the same function n times as an event listener is same as adding it once, reference : addEventListener docs
once choice is called, you remove the event listeners from both the buttons (remember , the event listeners were only bound once in a loop in the wait() function),
now with no event listener bound on the buttons, the buttons wont register the event click anymore.
The below implementation should work for you:
let numberOfTurnsTaken = 0;
//add a global variable to count the turns taken
function play() {
head.addEventListener("click", choice);
tails.addEventListener("click", choice);
//bind the event listeners
}
function choice(e) {
numberOfTurnsTaken++;
//increment the turns
let random = Math.floor(Math.random() * 2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
//remove the event listeners only when the turns are over and we are `handling` the last turn
if(numberOfTurnsTaken == playAmount){
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
}
if (random == 0) {
result.src = head.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
if (random == 1) {
result.src = tails.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh() {
result.style.border = "none";
clicked.style.border = "none";
}
}
//set things rolling by binding click event handlers on the buttons
play();
//the loop is no longer needed
//function wait() {
// for (let i = 0; i < playAmount; i++) {
// console.log(i);
// play();
// }
//}
//wait();

Regex not validating postal codes properly

I've been trying to validate USA and Canadian postal codes as I'm sending them through an api. However, I can't seem to get the regex to work. My validation is a bit messy but it should work nonetheless, I believe the regex is correct I just have the wrong logic? I would appreciate any help. Thanks.
function checkoutv2() {
var typepostal;
if (xcountry == 1) {
//canada
typepostal = "Canada";
} else if (xcountry == 2) {
//usa
var typepostal = "USA";
}
console.log(xcountry);
var xfirstname = document.getElementById("firstname").value;
var xlastname = document.getElementById("lastname").value;
var xemail = document.getElementById("email").value;
var xcity = document.getElementById("city").value;
var xaddress = document.getElementById("address").value;
var xpostal = document.getElementById("postal").value;
xpostal = xpostal.toString().trim();
var reg = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
var ca = new RegExp(/([ABCEGHJKLMNPRSTVXY]\d)([ABCEGHJKLMNPRSTVWXYZ]\d){2}/i);
var us = new RegExp("^\\d{5}(-{0,1}\\d{4})?$");
if (xfirstname == "" || xfirstname.length > 50) {
document.getElementById("firstname").style.border = "1px solid red";
} else if (xlastname == "" || xlastname.length > 50) {
document.getElementById("lastname").style.border = "1px solid red";
} else if (reg.test(xemail) == false || xemail.lenth > 100) {
document.getElementById("email").style.border = "1px solid red";
} else if (xcity == "" || xcity.length > 100) {
document.getElementById("city").style.border = "1px solid red";
} else if (xaddress == "" || xaddress.length > 100) {
document.getElementById("address").style.border = "1px solid red";
} else if (
typepostal == "Canada" &&
ca.test(xpostal.toString().replace(/\W+/g, "")) == false &&
xpostal.length >= 10
) {
console.log("postal is cad");
console.log(xpostal);
document.getElementById("postal").style.border = "1px solid red";
} else if (
typepostal == "USA" &&
xpostal.length > 10 &&
us.test(xpostal.toString()) == false
) {
console.log("postal is us");
document.getElementById("postal").style.border = "1px solid red";
} else {
checkout();
}
}

How to use regular expression for client side verification of entries using javascript?

This javascript code is working until the regular expression is used to evaluate the entries in client side verification through javascript. Please check the regular expressions and get me a solution that can check the entries by checking through regular expressions.
Here I am attaching the code to evaluate. Thanks in advance.
<script type="text/javascript">
var tuname=document.forms["teachersignup"]["tusername"];
var tname=document.forms["teachersignup"]["tname"];
var temail=document.forms["teachersignup"]["temail"];
var tpassword=document.forms["teachersignup"]["tpassword"];
var tiname=document.forms["teachersignup"]["tiname"];
var uname=document.getElementById("uname");
var naame=document.getElementById("nname");
var email=document.getElementById("email");
var pswd=document.getElementById("password");
var iname=document.getElementById("iname");
tuname.addEventListener("blur",unameVerify,true);
tname.addEventListener("blur",nameVerify,true);
temail.addEventListener("blur",emailVerify,true);
tpassword.addEventListener("blur",passwordVerify,true);
tiname.addEventListener("blur",inameVerify,true);
var ck_password = /^[A-Za-z0-9!##$%^&*()_]{8,30}$/;
var ck_iname = /^[A-Za-z0-9 ]*{3,60}$/;
var ck_username = /^[a-zA-Z0-9.\-_#]{3,20}$/;
var ck_name = /^[A-Za-z]{3,60}$/;
var ck_email = /^([\w-]+(?:\.[\w-]+)*)#((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
function ValidateForm(){
if(tuname.value == "" ){
tuname.style.border="1px solid red";
uname.innerHTML="Enter a valid username";
tuname.focus();
return false;
}
if(tname.value == "" ){
tname.style.border="1px solid red";
naame.innerHTML="Enter a valid name";
tname.focus();
return false;
}
if(temail.value == "" ){
temail.style.border="1px solid red";
email.innerHTML="Enter a valid email";
temail.focus();
return false;
}
if(tpassword.value == "" ){
tpassword.style.border="1px solid red";
pswd.innerHTML="Enter a valid password";
tuname.focus();
return false;
}
if(tiname.value == "" ){
tiname.style.border="1px solid red";
iname.innerHTML="Enter a valid institute's name";
tuname.focus();
return false;
}
}
function unameVerify(){
if(tuname.value!=""){
tuname.style.border="1px solid #5bc0de";
uname.innerHTML="";
return true;
}
}
function nameVerify(){
if(tname.value!="" ){
tname.style.border="1px solid #5bc0de";
name.innerHTML="";
return true;
}
}
function emailVerify(){
if(temail.value!="" ){
temail.style.border="1px solid #5bc0de";
email.innerHTML="";
return true;
}
}
function passwordVerify(){
if(tpassword.value!=""){
tpassword.style.border="1px solid #5bc0de";
pswd.innerHTML="";
return true;
}
}
function inameVerify(){
if(tiname.value!="" ){
tiname.style.border="1px solid #5bc0de";
iname.innerHTML="";
return true;
}
}
</script>
Try this.
var tuname_val = tuname.value;
var valid_tuname = tuname_val.match(ck_username);
This will return an object having a key 'input' that will store valid input that matched your pattern.
Tell me if this didn't work.

JavaScript - How to hide errors on Form Validation

How do I hide the error(s) messages and the red border when a user corrects their errors on my form? At the moment it will keep showing the error(s) until the page is refreshed or submitted.
function checkForm() {
var valid = true;
if (!retext.test(document.myform.textfield.value)) {
document.myform.textfield.style.border = "3.5px solid red";
document.getElementById("text").innerHTML = "Invalid text.";
document.getElementById("text").style.display = "block";
valid = false;
}
if (!re.test(document.myform.email.value)) {
document.myform.email.style.border = "3.5px solid red";
document.getElementById("emailwarn").innerHTML = "Invalid email.";
document.getElementById("emailwarn").style.display = "block";
valid = false;
}
if (!retel.test(document.myform.tel.value)) {
document.myform.tel.style.border = "3.5px solid red";
document.getElementById("telwarn").innerHTML = "Invalid telephone number.";
document.getElementById("telwarn").style.display = "block";
valid = false;
}
return valid;
}
I really have no idea on how to do this.
Assuming the checkForm function is called each time the form is amended you can include else clauses to reset the style and visible state of the warnings
function checkForm() {
var valid = true;
if (!retext.test(document.myform.textfield.value)) {
document.myform.textfield.border = "3.5px solid red";
document.getElementById("text").innerHTML = "Invalid text.";
document.getElementById("text").style.display = "block";
valid = false;
} else {
document.myform.textfield.border = 0;
document.getElementById("text").style.display = "none";
}
if (!re.test(document.myform.email.value)) {
document.myform.email.style.border = "3.5px solid red";
document.getElementById("emailwarn").innerHTML = "Invalid email.";
document.getElementById("emailwarn").style.display = "block";
valid = false;
} else {
document.myform.email.border = 0;
document.getElementById("emailwarn").style.display = "none";
}
if (!retel.test(document.myform.tel.value)) {
document.myform.tel.style.border = "3.5px solid red";
document.getElementById("telwarn").innerHTML = "Invalid telephone number.";
document.getElementById("telwarn").style.display = "block";
valid = false;
} else {
document.myform.tel.border = 0;
document.getElementById("telwarn").style.display = "none";
}
return valid;
}
Just add code which clears up the error messages at the beginning of your checkForm() function.
In your current code if error messages had been set once they have no chance to be changed on the correct input.
For example,
function clearErrors() {
document.getElementById("text").style.display = "none";
document.getElementById("emailwarn").style.display = "none";
document.getElementById("telwarn").style.display = "none";
}
function checkForm() {
var valid = true;
clearErrors();
...
Well first it would be better to seperate javascript and CSS styles, by applying classes:
input.error {
border: 3.5px solid red;
}
To apply the style:
document.myform.textfield.classList.add("error");
To remove the style:
document.myform.textfield.classList.remove("error");
To hide the warn element use:
document.getElementById("telwarn").style.display = "none";
Beware that classList does not work with ie < 10

JS trigger event when val() change

Q: How to trigger event when val is changed from onkey event?
Problem: When change one input, other will change value, but don't change css.
JsFiddle: http://jsfiddle.net/6Qnbh/
$('.stat').val(0);
$(".stat").change(function () {
var val = $(this).val();
if (val > 0) {
$(this).css("border", "1px solid #0f0");
} else if (val < 0) {
$(this).css("border", "1px solid #f00");
} else {
$(this).css("border", "1px solid #000");
}
}).trigger("change");
/**/
$('.stat').keyup(function () {
var val = $(this).val();
if (val > 0) {
var num = Math.abs(val) * -1;
} else {
var num = Math.abs(val) * 1;
}
$('input[data-id=' + $(this).attr("data-link") + ']').val(num);
});
On this line
$('input[data-id=' + $(this).attr("data-link") + ']').val(num);
Add .trigger("change"); to ensure the change event is triggered:
$('input[data-id=' + $(this).attr("data-link") + ']').val(num).trigger("change");
Fiddle:
http://jsfiddle.net/6Qnbh/4/
You need to trigger the change event after setting the value. See your updated fiddle
$(function () {
$('.stat').val(0);
$(".stat").change(function () {
var val = $(this).val();
if (val > 0) {
$(this).css("border", "1px solid #0f0");
} else if (val < 0) {
$(this).css("border", "1px solid #f00");
} else {
$(this).css("border", "1px solid #000");
}
}).trigger("change");
/**/
$('.stat').keyup(function () {
var val = $(this).val();
if (val > 0) {
var num = Math.abs(val) * -1;
} else {
var num = Math.abs(val) * 1;
}
// I have added the .trigger('change') part here
$('input[data-id=' + $(this).attr("data-link") + ']').val(num).trigger('change');
});
});
function test(){
$(".stat").each(function () {
var val = $(this).val();
if (val > 0) {
$(this).css("border", "1px solid #0f0");
} else if (val < 0) {
$(this).css("border", "1px solid #f00");
} else {
$(this).css("border", "1px solid #000");
}
})
}
and call the function on keyup
DEMO
In your code, $(this) refers to the currently changed jQuery object.
An easy solution is:
$(".stat").change(function () {
var val = $(this).val();
if (val > 0) {
$('.stat').css("border", "1px solid #0f0");
} else if (val < 0) {
$('.stat').css("border", "1px solid #f00");
} else {
$('.stat').css("border", "1px solid #000");
}
Edit: depending on what you want to happen, #Anton may have the effect you are looking for; I wasn't certain what you need.
As for the reason why the other input box doesn't change, the explanation is still the same.

Categories