Jump to content

Calling function with PHP generated arguments


ShadowMage

Recommended Posts

Hey guys, I need some advice on a piece of code I've written. It's a tricky little situation I have, so I'll try my best to explain.I've got some inputs that are generated with PHP. These inputs have onchange events attached to them which are also written in PHP. The arguments for the function that runs in the onchange are calculated and written by PHP as well. I'm trying to call this function again later but I have no good way to pass the same arguments (since everything was generated by PHP) so I decided to access the function assigned to the onchange event and manipulate it to fit my needs. Boy that's about as clear as mud. :) Hope you can understand it! :)Anyway here's my code:

for (x=0; x<fields.length; x++) {	if (fields[x].nodeName.toLowerCase() == 'input') {		currInput = fields[x];		if (currInput.type.toLowerCase() == 'text') {			func = currInput.onchange.toString();			func = func.replace("ValueChanged", "return Validate");			func = func.replace(/this[,]/, "document.getElementById(\""+currInput.id+"\"),");			func = eval("("+func+")");			valid = func();			if (!valid) {				blnErrors = true;			}		}	}}

What I'd like to know is if this is acceptable practice. Or is there a better/correct/more reliable way to do this?

Link to comment
Share on other sites

It might be easier to assign the onchange events with javascript when the page loads. PHP could deliver the list of inputs and event handlers.
How would I pass the list of inputs and event handlers? JSON? That sounds like it might be more complicated.Here's how the inputs are generated:
$required = "false";$rqdSpan = '';$class = '';if (strtolower($arrColumns[$colIndex]['Null']) != 'yes') { //Field is required (Can't be NULL)	$required = "true";	$rqdSpan = "<span class='rqdText'>Required</span>";	$class = " class='required'";}echo "<div><span id='".$name."'".$class.">".$name.$rqdSpan."</span><br />\n";$type = $arrColumns[$colIndex]['Type'];$regex = '/([a-z]+)(?:[(](\d{1,})(?:[,](\d{1,}))?[)])?/';preg_match($regex, $type, $matches);//Set each parameter, skipping $matches[0] since it is the full string match$type = $matches[1];$length = '';if (!empty($matches[2])) {	$length = $matches[2];}$decimals = '';if (!empty($matches[3])) {	$decimals = $matches[3];}echo "<input type='text' id='".$name."_input' name='".$name."' value='".$value."' onchange=\"ValueChanged(this, ".$required.", '".$type.";".$length.";".$decimals."');\" />";echo "<input type='hidden' id='".$name."_orig' value='".$value."' /></div>\n";

This little snippet is run inside a loop for each column in a database table.

Link to comment
Share on other sites

After the loop completes, you could add script tags, something similar to:The idea would be to create arrays of the inputs and then the functions, and assign them with javascript.echo '<script type="text/javascript">'echo 'var aInputs=new Array('foreach ($aInput as $k => $v) echo $v['name'].','; /* this will need quotes, and commas - implode might be better or some other function */echo ')';echo '</script>';What you're doing looks like Zend Framework forms ... http://framework.zend.com/manual/en/learni...reate-form.html

Link to comment
Share on other sites

After the loop completes, you could add script tags, something similar to:The idea would be to create arrays of the inputs and then the functions, and assign them with javascript.echo '<script type="text/javascript">'echo 'var aInputs=new Array('foreach ($aInput as $k => $v) echo $v['name'].','; /* this will need quotes, and commas - implode might be better or some other function */echo ')';echo '</script>';
That could possibly work, except I'm using AJAX to generate the content as well, so that's another added complication. :) EDIT: On second thought, maybe not. I just remembered that script tags can be placed anywhere so I should just be able to print the array where ever my content goes. Thanks for the suggestion!I might have to figure out how to make it work this way though as the code I currently have doesn't seem to work in IE. I get an 'Object expected' error on the following line: valid = func();Anybody know what might be causing that?
Link to comment
Share on other sites

I'm trying wirehopper's approach to see if I can get it to work. Here's what I've come up with:java script:

if (arrInputs) {	if (arrInputs[currInput.name]) {		valid = Validate(document.getElementById(currInput.id), arrInputs[currInput.name][0], arrInputs[currInput.name][1]);	}}

PHP:

$required = "false";$rqdSpan = '';$class = '';if (strtolower($arrColumns[$colIndex]['Null']) != 'yes') { //Field is required (Can't be NULL)	$required = "true";	$rqdSpan = "<span class='rqdText'>Required</span>";	$class = " class='required'";}echo "<div><span id='".$name."'".$class.">".$name.$rqdSpan."</span><br />\n";$type = $arrColumns[$colIndex]['Type'];$regex = '/([a-z]+)(?:[(](\d{1,})(?:[,](\d{1,}))?[)])?/';preg_match($regex, $type, $matches);//Set each parameter, skipping $matches[0] since it is the full string match$type = $matches[1];$length = '';if (!empty($matches[2])) {	$length = $matches[2];}$decimals = '';if (!empty($matches[3])) {	$decimals = $matches[3];}echo "<input type='text' id='".$name."_input' name='".$name."' value='".$value."' onchange=\"ValueChanged(this, ".$required.", '".$type.";".$length.";".$decimals."');\" />";echo "<input type='hidden' id='".$name."_orig' value='".$value."' /></div>\n";if (!empty($JSON_array)) {	$JSON_array.=", ";}$JSON_array.=("\"".$name."\": [".$required.", \"".$type.";".$length.";".$decimals."\"]");.....if (!empty($JSON_array)) {	echo "\n<script type='text/javascript'>var arrInputs = {".$JSON_array."};\n</script>\n";}

Problem is it keeps telling me that arrInputs is undefined. :)

Link to comment
Share on other sites

func is defined as per the code in my first post.
I see that, but are you tracking it to figure out what you're telling the browser to do? I don't know what the initial value of currInput.onchange is that you're replacing, are you sure that IE is getting the correct string, and that when it evals the string it's using what you expected it to use?
Problem is it keeps telling me that arrInputs is undefined.
Are you checking what that scripts prints to make sure it defines the variable and formats everything correctly?
Link to comment
Share on other sites

I see that, but are you tracking it to figure out what you're telling the browser to do? I don't know what the initial value of currInput.onchange is that you're replacing, are you sure that IE is getting the correct string, and that when it evals the string it's using what you expected it to use?Are you checking what that scripts prints to make sure it defines the variable and formats everything correctly?
Yes and yes.1- I've placed alert statements throughout that block of code and checked it in FF and IE. Both browsers alert exactly the same thing but IE explodes when it tries to eval() it.2- I looked in the source code and the script tags show up right where they should be. The JSON looks alright to me too, but I'll post it here. Maybe I'm missing something.
var arrInputs = {"FinishCode": [true, "int;11;"], "Description": [false, "varchar;15;"], "CostPerFt": [false, "decimal;10;2"], "MinCharge": [false, "decimal;10;2"]};

Link to comment
Share on other sites

With apologies for going off-topic, here's a whole different approach.form.ini.php - An .ini fileR_field=true V_field="/^[a-z0-9]{5,10}$/"P_field="Enter data for field"E_field="Field data must be 5-10 alphanumeric characters"T_field=textPrefix mapR=requiredV=validation stringP=prompt text - I actually put these in .conf files (Smarty) so they can be swapped on multi-lingual appsE=error textT=typefield is the name of the field in the database.Therefore, you can look through the database fields and build the inputs with the data from the .ini file.For example:$aIni=parse_ini_file('form.ini.php',true);foreach ($aDbFields as $k => $v)echo '<input type="'.$aIni['C_'.$v].'" name="_'.$k.'" id="'.$v.'" />';... later ...(javascript)e=document.getElementById('field');/* extract the input number from the input name *//* use the input number as an index into an array of validation strings *//* validate with the validation string out of the array */-- or you could use dojo --http://docs.dojocampus.org/dijit/form/ValidationTextBox

Link to comment
Share on other sites

Does IE throw the error when it evals the string or tries to run func?
Sorry, my bad. It actually throws the error when it tries to run func, but returns undefined when it evals. So when IE tries to eval the string it returns undefined, which means that func equals undefined, which means it's not a function and that's why IE throws the error.Thanks for the suggestion, wirehopper, but I think that's a little more complicated than I wanted to get with this project.I decided to show you exactly what each browser has in func just before it goes to the eval statement. I placed an alert just before the eval which alerts the value of func. Here's what I get:FireFox:
function onchange(event) {	return Validate(document.getElementById("FinishCode_input"), true, "int;11;");}

IE:

function onchange() {	return Validate(document.getElementById("FinishCode_input"), true, 'int;11;');}

So not exactly the same but the differences are trivial and should not affect the outcome.

Link to comment
Share on other sites

Well I fixed the issue with this code. The post by Garrett Smith here gives a very detailed explanation of this issue.Here's the code I ended up with:

for (x=0; x<fields.length; x++) {	if (fields[x].nodeName.toLowerCase() == 'input') {		currInput = fields[x];		if (currInput.type.toLowerCase() == 'text') {			func = currInput.onchange.toString();			func = func.replace("onchange", "validField");			func = func.replace("ValueChanged", "return Validate");			func = func.replace(/this[,]/, "document.getElementById('"+currInput.id+"'),");			eval(func);			valid = validField();		}	}}

FWIW, though, I'd really like to find a solution to my other problem instead of this one. If I can get that code to work, it'll greatly help me with a different issue I need to solve.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...