Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Passing Objects Between Functions 1

Status
Not open for further replies.

maxhugen

Programmer
May 25, 2004
498
AU
I'm working on a function validate(), which will validate data entry in a <form>. The function loops through the form's elements collection. For each element, another function - doSomething() - is called.

I tried to pass a reference to the form as an argument for the second function, but I couldn't seem to access the elements collection.

Then I tried passing the name of the form, and establishing a separate reference to the form as per the code that follows, but again, cannot reference the elements collection.

As I'm a raw novice, I'm probably missing something really obvious, if you can make any suggestions I'd welcome them.

Code:
function validate(formID) {

    // Get a ref to the form

    var x=document.getElementById(formID);


    // Do something with each element in the form
    for (var i=0;i<x.length;i++) {
        doSomething(formID,i);
    }
}


function doSomething(formID,i) {

    // Tried passing a ref to the form from the 
    // validate() function above, didn't work, so
    // trying a separate ref, using the formID.

    var x=document.getElementById(formID);


    with (document) {
        // The form's properties can be accessed:
        write('The forms name is: ' + x.name);
        write('The element index number we passed is: ' + i);

        // BUT the form's elements collection can't 
        // be accessed, as this doesn't work:
        write('The elements name is: ' + x.elements[i].name);

        // In fact the code stops running as soon as the
        // elements collection is referenced.
    }
    return;
}


Max Hugen
Australia
 
Try accessing it as an associative array... something like this:

Code:
function validate(formID) {
    var frm = document.getElementById(formID).elements;
	for (formElements in frm) {
        doSomething(frm[formElements]);
    }
}

function doSomething(formElement) {
	alert('Procressing element with name: ' + formElement.name);
}

Hope this helps,
Dan

Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Hi Dan

I've tried your method, but I'm getting 'undefined' returned. I tried using both formElement.name, and frm[formElements].name (in first function).

Can you suggest what I'm missing pls?


MTIA

Max Hugen
Australia
 
[tt] [red]//[/red]with (document) {
// The form's properties can be accessed:
[blue]document.[/blue]write('The forms name is: ' + x.name);
[blue]document.[/blue]write('The element index number we passed is: ' + i);

// BUT the form's elements collection can't
// be accessed, as this doesn't work:
[blue]document.[/blue]write('The elements name is: ' + x.elements.name);

// In fact the code stops running as soon as the
// elements collection is referenced.
[red]//[/red]}
[/tt]
 
Hi Dan

I've included here a html page I'm using to test my validation function. This function is in a .js file.

One thing that puzzles me: I can't access the function validate() from a button, eg onClick="validate('mainForm');". It seems I have to call a function on the page first, which in turn can call this validate() function. Is that normal behaviour?

The html and js code follows:

Code:
<html>
<head>

<script language="JavaScript" type="text/javascript" src="../library/valid.js"></script>

<script>
function checkForm(formID) {
	return validate(formID);
}
</script>

<title>Testing Validation</title>

</head>


<body> 

<form id="mainForm" name="mainForm" method="post" onSubmit="return checkForm(this.name)">

<table>
	<tr><td>Checkbox</td>
		<td><input class="" type="checkbox" id="MC_checkbox"	name="Checkbox Test"  value="1" checked></td></tr>
	<tr><td>Numeric</td>
		<td><input class="" type="text" 	id="MN_numeric"		name="Numeric Test" 	 size="20" maxlength="50" value=""></td></tr>
	<tr><td>Date</td>
		<td><input class="" type="text" 	id="MD_date"		name="Date Test" 	 size="20" maxlength="50" value="19/06/2007"></td></tr>
</table><br /><br />

<input type="submit" name="Submit" value="Submit"><br /><br />

<p>Manually run the Validation: 
	<input type="button" name="validate" value="Validate" onClick="checkForm('mainForm');">
	<br /><br />
</p>
</form>
</html>

The js file:

Code:
function validate(formID) {

    var frm = document.getElementById(formID).elements;
	var valMsg = '';

    for (formElement in frm) {

		switch (formElement.type) {
			case 'button': case 'checkbox': case 'file': case 'hidden': 
			case 'radio': case 'reset': case 'submit':

				break;

			case 'password': case 'text': case 'select-one':
			case 'select-multiple': case 'textarea':

				valMsg += 'Element being tested: ' + formElement.id + '\n';
				valMsg += 'Element value: ' + formElement.value + '\n';

				if (formElement.value.charAt(0) == 'M' && formElement.value == '') {
					valid=false;
					valMsg += indent + 'Failed, no value entered\n';
				} else {
					valMsg += indent + 'Passed, value entered or not required\n';
				}
				valMsg += '\n';

				// Problem with passing the right parameters...
				//validateMandatory(frm[formElement]);

				break;

			default: alert('Element type not listed in validate()');
		}
    }
	alert(valMsg);
}

Many thanks for having a look at it.

Cheers, max

Max Hugen
Australia
 
The original layout is clear enough. But if you don't understand my revision of it. Here is another equivalent revision of the problematic block.
[tt]
with (document) {
// The form's properties can be accessed:
write('The forms name is: ' + [red]getElementById("formID")[/red].name);
write('The element index number we passed is: ' + i);

// BUT the form's elements collection can't
// be accessed, as this doesn't work:
write('The elements name is: ' + [red]getElementById("formID")[/red].elements.name);

// In fact the code stops running as soon as the
// elements collection is referenced.
}
[/tt]
You want to use with (document), and then within the block you use x.elements... the script engine might be confused to look for document.x.elements which it cannot locate.
 
correction
I meant formID without quote, being the param of the function.
[tt]
with (document) {
// The form's properties can be accessed:
write('The forms name is: ' + [red]getElementById(formID)[/red].name);
write('The element index number we passed is: ' + i);

// BUT the form's elements collection can't
// be accessed, as this doesn't work:
write('The elements name is: ' + [red]getElementById(formID)[/red].elements.name);

// In fact the code stops running as soon as the
// elements collection is referenced.
}
[/tt]
 
Max,

When you hacked my code into yours, you missed off one important step. Why not take my code as-is, see tht it works, and then extend that?

The part you missed out was getting the individual element with:

Code:
frm[formElements]

so you'd want to do something like:

Code:
var el = frm[formElements];

right inside the "for" loop, and then access "el" instead of "formElement".

Dan

Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Thanks for your patience, Dan. That did indeed fix my problem.

I think that coming from VBA, I had *assumed* that the formElement in
Code:
for (formElement in frm)
would be a ref to frm[formElement]... Hmmm, need more study on how to use references, arrays and collections.

Just 2 more questions (if you don't mind) on this exercise:

1. I can't seem to call a function in a separate .js file directly from the page, such as in a button:
Code:
<input type="button" name="validate" value="Validate" onClick="validate('mainForm');">
Instead, I have to add a 'wrapper' function to the page, which in turn calls the validate() function:
Code:
<script>
function checkForm(formID) {
	return validate(formID);
}
</script>
Am I missing something here?

2. In the validate() function, I am trying to exclude testing of certain element types, in the first case block of the switch statement. Am I using the correct syntax here? For some reason, the break statement is being ignored, and it processes the default case as well.

MTIA


Max Hugen
Australia
 
It could be a crappy IE quirk where because you have an element with the same name as your function it fails (I bet it only happens in IE, right?)... so you could rename your function or input to be different from the other.

The switch statment looks correct - it's odd that you get the alert, as the code seemed to work for me this morning. Does it happen in other browsers?

Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
G'day Dan

Actually, I use Firefox. You were spot on with the element name, once I changed it, the validate() function worked. Thanks, I'll keep that in mind.

After many hours, I've found some unexpected behaviour. If I use your 'for' loop
Code:
for (formElement in frm)
it actually returns 3 additional 'psuedo' elements which are all undefined, even though it correctly reports the number of elements as 5!!! And I can't get it to work in IE.

The js script following can be toggled in the html page to use one method or the other for testing:
Code:
function validate(formID) {
	var method = (document.getElementById('MT_text').value);

	var valMsg = '';
	valMsg += 'Using \'' + method + '\' in a ' + navigator.appName + ' browser\n';
	if (method == 'method_1') {
		var x=document.getElementById(formID);
		valMsg += 'There are ' + x.length + ' elements in the form\n';
		valMsg += '\n';
		for (var i=0;i<x.length;i++) {
			valMsg += 'Element being tested: ' + x.elements[i].id + '\n';
			valMsg += 'Element type: ' + x.elements[i].type + '\n';
			valMsg += validateMandatory(x.elements[i]);
			valMsg += '\n';
		}
	} else {
		var frm = document.getElementById(formID).elements;
		valMsg += 'There are ' + frm.length + ' elements in the form\n';
		valMsg += '\n';
		var i = 0;
		for (formElement in frm) {
			i += 1;
			var el = frm[formElement];
			valMsg += 'Element being tested: ' + el.id + '\n';
			valMsg += 'Element type: ' + el.type + '\n';
			valMsg += validateMandatory(frm[formElement],method);
			valMsg += '\n';
		}
		valMsg += 'The \'for (formElement in frm)\' looped through ' + i + ' elements???\n';
		valMsg += '\n';
	}
	alert(valMsg);
}

function validateMandatory(el,method) {
	// just testing that I've passed a reference to the 
	// element correctly in the validate function.

	// Having some probs with IE (no kidding!), so had to
	// add this browser crap...
	var browserName=navigator.appName; 

	var valMsg = '';
	if (browserName=="Netscape") { 
		var valMsg = '2nd Function: Element tested is: ' + el.id + '\n';
	} else if (browserName=="Microsoft Internet Explorer") {
		if (method == 'method_1') {
			valMsg = '2nd Function: (IE only) Element tested is: ' + el.id + '\n';
		} else if (method == 'method_2') {
			valMsg = '2nd Function: (IE only) Element undefined using ' + method + '\n';
		} else {
			valMsg = '2nd Function: (IE only) Parameters not working\n';
		}
	} else {
		// do nothing
	}
	return valMsg;
}
The simple html page isL
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "[URL unfurl="true"]http://www.w3.org/TR/html4/frameset.dtd">[/URL]
<html debug=true>
<head>
<!--#include virtual="../config.htm" -->

<script language="JavaScript" type="text/javascript" src="lib/js/valid.js"></script>
<script language="JavaScript" type="text/javascript" src="firebuglite/firebug/firebug.js"></script>

<title>Testing Validation</title>

</head>


<body> 

<form id="mainForm" name="mainForm" method="post" onSubmit="return validate(this.name)">
<table>
	<tr><td>Checkbox</td>
		<td><input class="" type="checkbox" id="MC_checkbox"	name="Checkbox Test"  value="1" checked></td></tr>
	<tr><td>Numeric</td>
		<td><input class="" type="text" 	id="MN_numeric"		name="Numeric Test"		size="20" maxlength="50" value=""></td></tr>
	<tr><td>Date</td>
		<td><input class="" type="text" 	id="MD_date"		name="Date Test" 	 size="20" maxlength="50" value="19/06/2007"></td></tr>
</table><br /><br />

<br /><br />

<p>Enter the method of iterating through the elements ('method_1' or 'method_2')<br>
	<input class="" type="text" id="MT_text" name="Text Test" size="20" maxlength="50" value="method_1"></p>

<p>Manually run the Validation: 
	<input type="button" id="btnValidate" value="Validate Now" onClick="validate('mainForm');">
	<br /><br />
</p>
</form>
</html>

MTIA


Max Hugen
Australia
 
If you remove the Firebug script (in fact, remomve all scripts other than the validation routine), do the extra 3 'elements' dissapear?

It's possible Firebug (or something else) is attaching some sort of extra methods / properties to the form elements collection.

I mention this because the Prototype JS library suffers from exactly this problem.

Dan



Coedit Limited - Delivering standards compliant, accessible web solutions

[tt]Dan's Page [blue]@[/blue] Code Couch
[/tt]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top