What is failing in my form validation function? - javascript

So I've tried making a function that loops through the elements of a form and checks the length of the elements, and if so, change the class so they can be styled differently. The code I have I assumed would work, and I'm not getting any errors in my console, so I can't pinpoint what is going wrong exactly. If someone could tell me why this won't work or how to fix it that would be awesome! Thankyou!
function validate_form(){
var form = document.forms['form_name']; //store form into a variable
var validated = true; // store return value for onsubmit attribute
for(i=0; i<form.elements.length; i++){
if(form.elements[i].value.length){ // check if form elements are empty
form.elements[i].className = "validate_failed"; // if elements are empty, add a class that will style them
validated = false;
return validated;
} else{
validated = true;
return validated;
}
return validated;
}
return validated;
}

Try
function validate_form(){
var form = document.forms['form_name']; //store form into a variable
for(var i=0; i<form.elements.length; i++){
if(form.elements[i].value.length===0){ // check if form elements are empty
form.elements[i].className = "validate_failed"; // if elements are empty, add a class that will style them
return false;
}
return true;
}
assuming
<form onsubmit="return validate_form()" ...
or make it all unobtrusive
window.onload=function() {
document.forms['form_name'].onsubmit=function() {
for(var i=0; i<this.elements.length; i++){
this.elements[i].className = "";
if(this.elements[i].value.length===0){ // check if form elements are empty
this.elements[i].className = "validate_failed"; // if elements are empty, add a class that will style them
return false;
}
return true;
}
}
}

Because your are returning validated during the first run through of the loop, you'll only ever check the first element of the form. You'll just want to set validated, and return it after the loop (or return when you first set it to false, depending on what you want to do).
Also, like Joe commented, you should have var i instead of just i so that i is not global.

Following code will work for empty element
if(!form.elements[i].value.length){
OR
if(form.elements[i].value.length === 0){

Related

Trigger event for each object

I want website to change class of an element if it is filled. So, when user blurs out of an input field the program checks if it has any value and if yes adds a class. The problem is to pass this behaviour to each element in class' collection.
var input = document.getElementsByClassName('input');
contentCheck = function(i){
if(input[i].value>0) input[i].classList.add('filled');
else input[i].classList.remove('filled');
};
for(var i=0; i<input.length; i++) {
input[i].addEventListener('blur',contentCheck(i));
}
This works once after reloading the page (if there's any content in cache), but contentCheck() should trigger each time you leave the focus.
You've half-applied the "closures in loops" solution to that code, but you don't need the closures in loops solution, just use this within contentCheck and assign it as the handler (rather than calling it and using its return value as the handler):
var input = document.getElementsByClassName('input');
var contentCheck = function(){ // <== No `i` argument (and note the `var`)
// Use `this` here
if(this.value>0) this.classList.add('filled');
else this.classList.remove('filled');
};
for(var i=0; i<input.length; i++) {
input[i].addEventListener('blur',contentCheck);
// No () here -------------------------------------^
}
Side note: classList has a handy toggle function that takes an optional flag:
var contentCheck = function(){
this.classList.toggle('filled', this.value > 0);
};
If you needed the "closures in loops" solution (again, you don't, but just for completeness), you'd have contentCheck return a function that did the check:
var input = document.getElementsByClassName('input');
var makeContentCheckHandler = function(i){
return function() {
if(input[i].value>0) input[i].classList.add('filled');
else input[i].classList.remove('filled');
};
};
for(var i=0; i<input.length; i++) {
input[i].addEventListener('blur', makeContentCheckHandler(i));
}
Note I changed the name for clarity about what it does.
Try to use anonymous function
input[i].addEventListener('blur',function(e){
console.log(e);
});
Example: https://jsfiddle.net/42etb4st/4/

How to echo something from javascript to div class html

Javascript
function validateForm() {
var result;
var keywords = document.querySelectorAll('#keywords');
[].slice.call(websites).forEach(function(website) {
if (website.value == '') {
website.focus();
HERE I SAY SOMEHOW THE ERROR
result = false;
return true;
}
});
return result;
}
HTML
<div class="error-website">HERE THE ERROR IS GETTING ECHOED</div>
How do i echo website in that div above and how do i add the error in that if condition.
Try:
document.querySelectorAll('.error-website')[0].innerHTML = 'Website';
As NULL and VisioN has pointed , this:
document.querySelector('.error-website').innerHTML = 'Website';
is even faster , because of "querySelector is faster unless the match is the last DomNode in the DOM".
First of all, it would be more appropriate to use an ID not a class; the reason is that classes are meant for, well, classes (i.e. categories) of elements; however, in your case, you are dealing with one single unique element (you'll only have one), so assuming you take my advice and change to the following markup:
<div id="error-website">HERE THE ERROR IS GETTING ECHOED</div>
... it will be as simple as:
document.getElementById('error-website').innerHTML = "whatever <strong>you</strong> <em>like</em>";
$(".error-website").text("Website")
document.getElementById('error-website').innerHTML = ....
if you use an id...
Use DOM document.getElementsByClassName
Eg.
function validateForm() {
var result;
var keywords = document.querySelectorAll('#keywords');
[].slice.call(websites).forEach(function(website) {
if (website.value == '') {
website.focus();
HERE I SAY SOMEHOW THE ERROR
result = false;
return true;
}
});
return result;
var a=validateForm();
if(a){
document.getElementsByClassName("error-website")[0].innerHTML=a;
}
NOTE: getElementsByClassName() does not work in Internet Explorer 5,6,7, and 8

JavaScript: Intercepting form submit and identifying which form made the submission

I am trying to intercept form submits from webpages I dont control.
My current implementation is ...
// During onLoad, loop through all forms and for each form object
var prevonsubmit = formobj.onsubmit;
if (prevonsubmit) {
formobj.onsubmit = function f() {
if(prevonsubmit()) {
interceptform();
return true;
}
return false;
};
} else {
formobj.onsubmit = function ff() {
interceptform();
return true;
};
}
The problem with this is, inside interceptform(), I am unable to identify which form actually made this submission. Is there a way I actually get the form object that is trying to submit? Keep in mind that some of the forms I see do not have a name or id specified and there is more than one form (in the same webpage) with same action.
Edit:
The purpose is capture the content in the input tags that belong to the form.
A made up example of what I see in a form:
<form action="https://duckduckgo.com/html/" method="GET">
<input type="text" name="q"/>
</form>
<form action="https://duckduckgo.com/html/" method="GET">
<input type="text" name="l"/>
</form>
<form action="https://duckduckgo.com/html/" method="GET">
<input type="text" name="l"/>
<input type="text" name="q"/>
</form>
Edit2:
Based on #ruakh answer, the solution I ended up using:
var prevonsubmit = formobj.onsubmit;
if (prevonsubmit)
formobj.onsubmit = createOnSubmitFunctionWithOld(prevonsubmit, formobj);
else
formobj.onsubmit = createOnSubmitFunction(formobj);
// Definition of the functions:
function createOnSubmitFunctionWithOld(prevonsubmit,formObj) {
return function () {
if (prevonsubmit()) {
interceptform(formObj);
return true;
}
return false;
};
}
function createOnSubmitFunction(formObj) {
return function () {
interceptform(formObj);
return true;
};
}
You can simply pass formobj as an argument to interceptform():
interceptform(formobj);
But bear in mind that both with formobj and with prevonsubmit, you have to be careful to avoid capturing a variable you don't want to. For example, in JavaScript, this:
var functions = [];
for(var i = 0; i < 10; ++i)
{ functions[i] = function() { return i; }; }
creates ten functions that all return 10, because they all capture the same i variable that's been incremented up to 10 by the time the functions are ever called. In the above example, you could write something like:
function new_constant_function(return_value)
{ return function() { return return_value; }; }
// ...
var functions = [];
for(var i = 0; i < 10; ++i)
{ functions[i] = new_constant_function(i); }
to copy each value of i into a new local variable return_value whose value never changes; or, a bit more tersely, this:
var functions = [];
for(var i = 0; i < 10; ++i)
{ functions[i] = (function(_i){ return function(){ return _i; } })(i); }
You'll almost certainly need to do something similar in your case. (But without seeing a bit more of the context of your code, it's hard to say exactly what.)
Why not loop through document.forms and append a hidden field to each one, or assign an id to the form itself.
If you are loopoing over the forms from a function, then:
> var prevonsubmit = formobj.onsubmit;
> if (prevonsubmit) {
> formobj.onsubmit = function f() {
> if(prevonsubmit()) {
prevonsubmit has a closure to the outer variable, it will reference the last value of prevonsubmit, so they will all reference the same function. This may "work", but will fail if any of your forms has a current listener that is different to any other form.
> interceptform();
You can simply pass this from the function to interceptform:
interceptform(this);
and interceptform will be passed a reference to the element calling the function (presumably the form being submitted).
> return true;
> }
> return false;
That will (probably) cancel submission of any form that doesn't have an existing listener. Is that what you want?
> };
> } else {
> formobj.onsubmit = function ff() {
Named function expressions are known to be buggy in at least one widely used browser. If you don't need a name (and it doesn't seem to be used here for anything), dont' use one. Keep the function anonymous.
> interceptform();
> return true;
> };
> }

Javascript check multiple textbox for numeric

I am checking numeric value for one textbox like this:
function validateNumeric() {
var old = document.getElementById("tbNum").value;
var new = old_val.replace(/^\s+|\s+$/g,"");
var validChars = '0123456789';
for(var i = 0; i < new.length; i++){
if(validChars.indexOf(new.charAt(i)) == -1){
alert('Please enter valid number');
return false;
}
}
document.getElementById("tbNum").value = new;
return true;
}
I want to use the same function and check numeric value for other text boxes that requires numeric value. How can I pass value of tbID, tbDiscID, as well as above and return true before submitting the form.
I am not sure what you mean by tbId and tbDiscID, but to do this in plain JavaScript, you can generalize this solution by traversing JavaScript's arguments object, which lets you pass in any variable number of arguments to your function. This will help you take in the IDs you need. Your new solution would look something like the following:
function validateNumeric() {
for (var arg in arguments) {
var id = arguments[arg];
var old = document.getElementById(id).value;
var new = old_val.replace(/^\s+|\s+$/g,"");
var validChars = '0123456789';
for(var i = 0; i < new.length; i++){
if(validChars.indexOf(new.charAt(i)) == -1){
alert('Please enter valid number');
return false;
}
}
document.getElementById(id).value = new;
return true;
}
}
Then invoke it like:
validateNumeric("myTextbox1", "myTextbox2", ..., "myTextboxN");
Where myTextBox1 ... myTextBoxN are the IDs of your textboxes.
use parameter for the function, for using it on different elements
validateNumeric(value) {
use the onsubmit parameter on the form tag to call a validation
<form name="myForm" action="dosomething.php" onsubmit="return validateForm()"
write your validate function with calls for all elements
function validateForm() {
if (!validateNumeric(document.getElementById("tbNum"))) {
return false;
}
...
return true;
would be one way..
edit
forgot the check within the validateForm method

Avoid execution goes on in a .each loop

I've got a code like this one to see whether some radio buttons have been checked or not. I'm using .each function of jquery to show an alert when I find a group of radio buttons with the same name value and none of them have been checked. When I find one I want to fire an alert and return false, but after the alert is shown the execution of the .each stops but the lines after .each function are executed (I mean true value is executed).
$(":radio").each(function(){
var name = $(this).attr('name');
var numAnswered = $(":radio").filter('[name='+name+']').filter(":checked").length;
var notAnswered = numAnswered == 0;
if(notAnswered){
alert("Must answer all questions");
return false;
}
});
console.log('still goes here even when alert is fired');
return true;
How can I avoid this situation?
Thanks.
var myreturnvalue = true;
$(":radio").each(function(){
var name = $(this).attr('name');
var numAnswered = $(":radio").filter('[name='+name+']').filter(":checked").length;
var notAnswered = numAnswered == 0;
if(notAnswered){
alert("Must answer all questions");
myreturnvalue = false;
return false;
}
});
console.log('still goes here even when alert is fired');
return myreturnvalue;
You can use that same notAnswered variable (or another, whatever floats your boat) at a higher scope, like this:
var notAnswered;
$(":radio").each(function(){
notAnswered = $(":radio[name="+this.name+"]:checked").length == 0;
if(notAnswered){
alert("Must answer all questions");
return false;
}
});
if(notAnswered) return false;
console.log("will only fire if there's an answer");
return true;
The other changes above are just slimming down the code, you can get away with far fewer selector engine invocations :)

Categories

Resources