Jquery - if value empty rule only on non hidden form elements

Hello all. I have some jquery on my form that shows/hides divs based on the chosen value of a drop down menu


function show1() {
   var div_num = $("#airpvtyesno").val();
   if (div_num == 0) {
   $("#pickuppvt").hide();
   $("#pickuplhr").hide();
	};
   if (div_num == 1) {
   $("#pickuppvt").hide();
   $("#pickuplhr").show();
   	};
	   if (div_num == 2) {
   $("#pickuppvt").show();
   $("#pickuplhr").hide();
	};
}

I am trying to implement a rule on my form that if a specific form element is left empty, the form cannot be processed and an alert is called.

Here is an example of the javascript I use for that feature:


function IncompleteForm()
{
var FormOk  = true;

	if (document.myform.myfield.value == '')
    {
        alert('Please enter a value for this field.');
        document.myform.myfield.focus();
        FormOk = false;
	};

return FormOk;

}

However, I need to combine the two features.

I only want specific field elements to run this rule if the div they are contained in is shown.

It would ideally look something like this:


function show1() {
   var div_num = $("#airpvtyesno").val();
   if (div_num == 0) {
   $("#pickuppvt").hide();
   $("#pickuplhr").hide();
	};
   if (div_num == 1) {
   $("#pickuppvt").hide();
   $("#pickuplhr").show();
   IF pickuplhr.FIELD1 IS EMPTY - ALERT - PLEASE ENTER A VALUE FOR FIELD 1
   	};
	   if (div_num == 2) {
   $("#pickuppvt").show();
   $("#pickuplhr").hide();
   IF pickuppvt.FIELD2 IS EMPTY - ALERT - PLEASE ENTER A VALUE FOR FIELD 2

	};
}

my limited ability in jquery and general syntax is giving me difficulties combining these features.

as always any help is much appreciated. thanks

You can use the :visible selector.


if ($(':visible', document.myform.myfield) && document.myform.myfield.value == '') {
    ...
}

Or:


if ($(document.myform.myfield).is(':visible') && document.myform.myfield.value == '') {
    ...
}

Hi Paul, thanks again.

I have got the feature working but it calls all three alerts at once. How can I edit the code so it only calls the one alert (whichever one is empty) and then returns to that field.


<script type="text/javascript">

function IncompleteForm()
{
var FormOk  = true;

if ($(document.bookingform.paxtitle).is(':visible') && document.bookingform.paxtitle.value == '') {
alert("Please enter the passenger title");
document.bookingform.paxtitle.focus();
FormOk = false;

};

if ($(document.bookingform.paxfirstname).is(':visible') && document.bookingform.paxfirstname.value == '') {
alert("Please enter the passenger first name");
document.bookingform.paxfirstname.focus();
FormOk = false;

};

if ($(document.bookingform.paxlastname).is(':visible') && document.bookingform.paxlastname.value == '') {
alert("Please enter the passenger last name");
document.bookingform.paxlastname.focus();
FormOk = false;

};

return FormOk;

}

</script>

You don’t need to use the FormOK variable because this is a small function and no other parts of the function rely on the FormOK information.

Just return false when a problem is found, and at the end of the function return true…

you’re FAB

here it is working in all it’s glory


<script type="text/javascript">

function IncompleteForm()
{

if ($(document.bookingform.paxtitle).is(':visible') && document.bookingform.paxtitle.value == '') {
alert("Please enter the passenger title");
document.bookingform.paxtitle.focus();
return false;
};

if ($(document.bookingform.paxfirstname).is(':visible') && document.bookingform.paxfirstname.value == '') {
alert("Please enter the passenger first name");
document.bookingform.paxfirstname.focus();
return false;
};

if ($(document.bookingform.paxlastname).is(':visible') && document.bookingform.paxlastname.value == '') {
alert("Please enter the passenger last name");
document.bookingform.paxlastname.focus();
return false;
};

return true;

}

</script>

That can now be simplified, by moving the common behaviour out to a separate function.


function isFilled(field) {
    return $(field).is(':visible') && field.value === '';
}
function validateForm(form, toValidate) {
    var i,
        validateInfo,
        field;
    for (i = 0; i < toValidate.length; i += 1) {
        validateInfo = toValidate[i];
        field = form.elements[validateInfo.field];
        if (!validateInfo.rule(field)) {
            window.alert(validateInfo.message);
            field.focus();
            return false;
        }
    }
    return true;
}
function IncompleteForm() {
    var toValidate = [
        {field: 'paxtitle', rule: isFilled, message: 'Please enter the passenger title'},
        {field: 'paxfirstname', rule: isFilled, message: 'Please enter the passenger first name'},
        {field: 'paxlastname', rule: isFilled, message: 'Please enter the passenger last name'}
    ],
        form = document.bookingform;
    return validateForm(form, toValidate);
}

Then, if different fields required some additional rules, other than checking that they’re filled, that information can be added in to the toValidate structure too. But that would be for later planning only if needed.

By the way, that validateForm function looks much simpler when the browsers can handle certain techniques.


function validateForm(form, toValidate, onFailure) {
    return toValidate.every(function (validateInfo) {
        var field = form.elements[validateInfo.field];
        if (!validateInfo.rule(field)) {
            onFailure();
            return false;
        }
        return true;
    });
}
...
return validateForm(form, toValidate, function () {
    window.alert(validateInfo.message);
    field.focus();
});


Hi Paul, that’s great a lot easier to code that way.

Using the original method I had some trouble applying that to a different page because some of the fields were in different divs.

I tried to fiddle with the syntax of the command by using


if ($("#mydiv").myform.myfield).is(':visible') && ("#mydiv").myform.myfield.value == '') {

but obvsiouly this didn’t work.

using the new method you suggested, will the code work even if the field elements are held in different divs?

By using the elements collection of the form, you will be able to access any of the named fields that you have in your form.

Hi Paul, I cannot get the new code working (on a different page).

I have stripped my page bare. Any table and div sections need to remain in place.

Here is the code


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<script type="text/javascript" src="http://www.londonheathrowcars.com/scripts/jquery-1.7.1.js"></script>

<script type="text/javascript">

function show1() {
   var div_num = $("#airpvtyesno").val();
   if (div_num == 0) {
   $("#pickuppvt").hide();
   $("#pickuplhr").hide();
      $(':input', '#pickuplhr').each(function () {
   this.value = '';
   });
      $(':input', '#pickuppvt').each(function () {
   this.value = '';
   });
	};
   if (div_num == 1) {
   $("#pickuppvt").hide();
   $("#pickuplhr").show();
   $(':input', '#pickuppvt').each(function () {
   this.value = '';
   });
   	};
	   if (div_num == 2) {
   $("#pickuppvt").show();
   $("#pickuplhr").hide();
   $(':input', '#pickuplhr').each(function () {
   this.value = '';
   });
	};
}

function isFilled(field) {
    return $(field).is(':visible') && field.value === '';
}
function validateForm(form, toValidate) {
    var i,
        validateInfo,
        field;
    for (i = 0; i < toValidate.length; i += 1) {
        validateInfo = toValidate[i];
        field = form.elements[validateInfo.field];
        if (!validateInfo.rule(field)) {
            window.alert(validateInfo.message);
            field.focus();
            return false;
        }
    }
    return true;
}
function IncompleteForm() {
    var toValidate = [
        {field: 'pk1flightno', rule: isFilled, message: 'Please enter the Flight Number'}
    ],
        form = document.bookingform;
    return validateForm(form, toValidate);
}

</script>



<style type="text/css">
#pickuplhr, #pickuppvt {
display:none;}
</style>

</head>

<body>
<div id="wrap" class="clearfix">

	<div id="top">
		LOGO
	</div>

<div id="subheader">
</div>

<div id="main">
	
<table border="0" width="800" cellspacing="0" cellpadding="0">
	<tr>
		<td width="164" align="left" valign="top"></td>
		<td width="436" align="left" valign="top">

		<table class="maintable" cellspacing="0" cellpadding="0">
    <tr>
        <td class="top"></td>
        <td class="mid"></td>
        <td class="top2"></td>
    </tr>
    <tr>
        <td class="lcol"></td>
        <td class="mid">


<table border="0" width="386" cellspacing="0" cellpadding="0">

<tr>
<td width="20" align="left" valign="top">&nbsp;</td>
<td width="12" align="left" valign="top"></td>
<td width="177" align="left" valign="top"><p>Where is the pick-up address?</p></td>
<td width="177" align="left" valign="top"><p><select name="airpvtyesno" id="airpvtyesno" onchange="show1();">
<option value="">...</option>
<option value="1">Heathrow Airport</option>
</select></p></td>
</tr>
<tr><td width="20" align="left" valign="top">&nbsp;</td><td width="12" align="left" valign="top">&nbsp;</td><td width="177" align="left" valign="top">&nbsp;</td><td width="177" align="left" valign="top">&nbsp;</td></tr>

</table>


<div id="pickuplhr">
<form method="post" name="bookingform" id="bookingform" action="nextpage.asp" onsubmit="return IncompleteForm()">

<table border="0" width="386" cellspacing="0" cellpadding="0">

	<tr>
		<td width="20" align="left" valign="top">&nbsp;</td>
		<td width="12" align="left" valign="top">&nbsp;</td>
		<td width="354" align="left" valign="top" colspan="2"><h2 style="margin-left:0px;margin-bottom:15px;">Heathrow Airport</h2></td>
	</tr>


<tr>
<td width="20" align="left" valign="top">&nbsp;</td>
<td width="12" align="left" valign="top"><p class="asterix">*</p></td>
<td width="177" align="left" valign="top"><p>Flight number:<br /><i><font style="color:#333333;font-size:8.5pt">e.g. BA123</font></i></p></td>
<td width="177" align="left" valign="top"><p><input type="text" name="pk1flightno" id="pk1flightno" /></p></td>
</tr>
</table>

<p><input value="Next >>" type="submit" /></p>
</form>
</div>



<br /><br />

		</td>
        <td class="rcol"></td>
    </tr>
    <tr>
        <td class="base"></td>
        <td class="mid"></td>
        <td class="base2"></td>
    </tr>

</table>


</td>
		<td width="200" align="left" valign="top"></td>
</tr>
</table>
</div>
</div>
</body>
</html>

You can see the page here: http://www.londonheathrowcars.com/bookings/tester.asp

The form is allowed to submit even if there is no value in the flight number. Funnily enough, when you DO enter a value into the flight number field, the message DOES pop up and the form does not submit (ie it works but only if there is a value).

I have no idea why, I have tried to change this line:
return $(field).is(‘:visible’) && field.value == ‘’;

but that line looks correct?!?

Your isFilled function is returning the opposite of what it should be.


function isFilled(field) {
    return $(field).is(':visible') && [color="red"]field.value === ''[/color];
}

The isFilled function should return true if there’s something in there, and false if there isn’t.

Try this instead:


function isFilled(field) {
    return $(field).is(':visible') && field.value !== '';
}

yes that has done the trick… so simple

thanks