More properly, how to repopulate a form after client-side validation has failed, in particular when you are not directly writing the form code.
In this case the form is created through a WYSIWYG interface (by a 3rd party). The available tools are cookies (for passing the data back from the validation script) and javascript (which can be entered in the 'Source' view of the WYSIWYG editor and is permitted by the CMS).
For a few fields it is easy enough to give each field it's own cookie or use a simple join/spilt scheme, but for longer forms (more than about 10 fields) this gets unwieldy very fast, and you start to run into the cookie limit.
Enter JSON, to tidily package all your field-data pairs in a way that javascript can natively interpret.
Step 1.
Construct the JSON string as part of your validation script (this in php)
// my whitelist is ('var_in_script'=>'form-field-name') so I can't just json_encode it.
$json = '{';
foreach($whitelist as $f => $v)
{
$n = str_replace('-','_',$v); //valid js variable names , form names are constructed with hyphens
$x = html_entity_decode($$f,ENT_QUOTES); // undo input cleaning
$x = str_replace('"',"'",$x); // or escape as '\"'
$json .= '"'.$n.'":"'.$x.'",';
}
$json = rtrim($json,',').'}';
setcookie('membershipformJson',$json,time()+30);
Step 2.
Put this function (and ancillary cookie handling functions) in the global javascript if possible, or at the top of the WYSIWYG source otherwise.
function refillFormAdv(x)
{
// x is the id of the form
fields = document.forms[x].elements;
// is the cookie set?
j = readCookie(x+'formJson');
if(!j)
{
return;
}
v = eval("("+URLDecode(j)+")"); // extract values
for(i in fields)
{
f = fields[i];
id = f.id;
if(id)
{
id = id.replace(/-/g,'_'); // convert to valid var name
}
else
{
continue;
}
//look for the var in the JSON data
z=eval('v.' + id);
if(z)
{
t = f.type;
switch(t)
{
case "text":
case 'textarea':
f.value = z;
break;
case 'checkbox':
f.checked = true;
break;
case 'select-one':
for(o in f.options)
{
if(f.options[o].value == z)
{
f.options[o].selected=true;
}
}
break;
// add other element types later if needed
// radio buttons are going to be more difficult
// will need to alter the script to look for name instead of id
default:
break;
}// end switch
}// end if
}// end while
//clean up
eraseCookie(x+'formJson');
}
function URLDecode(v)
{
v = unescape(v);
while(v.indexOf('+')>-1){ v = v.replace("+"," "); }
return v;
}Step 3. Make sure your form has an id (in the code above the id is 'membership') and that all fields have an id matching their name. (This highlights the one as yet unaddressed problem with the script - a set of radio buttons can not all have the same ID. I would address this by extending the function to check the "name" attribute if a matching "id" is not found, then comparing the "value" of each matching element against z. )
Step 4. Include the function call immediately after the form. If possible set it to fire after the page has loaded (at this point I was really wishing the system supported jQuery or any javascript framework).
<script type="text/javascript">
refillFormAdv('membership');
</script>

1 comments:
Note, it's particularly important to make sure the form input is at least trim()ed. Trailing line breaks from a textarea will break the repopulation script.
Post a Comment