Chrome/Safari Gotcha: Nameless Form Fields
In ColdFusion, you can loop over the keys in a structure without knowing what the key names are, by using either this syntax:
<cfloop collection="#myStruct#" item="key">
<cfset foo = myStruct[key] />
</cfloop>
Or this syntax:
<cfscript>
for (var key in myStruct){
foo = myStruct[key];
}
</cfscript>
This is useful when you need to loop over a form with dynamically created fields — like editing N person records at a time.
I recently found out that in Webkit — and thus Safari and Google Chrome — form fields without a name attribute are included in a form post, just without a name. Odd, right? I know. I've used nameless form fields in the past, like a select box that's only used for UI functionality, tied to JavaScript. In IE and Firefox, the field is ignored and not posted with the form. In Chrome and Safari, though? Included! Let's look at an example form.
<form action="" method="post">
<select id="test">
<option value="foobar" selected="selected">Foobar</option>
</select>
<input type="submit" name="submitBtn" value="Submit" />
</form>
<cfif structKeyExists(form, "submitBtn")>
<cfdump var="#form#">
</cfif>
This page will submit to itself, and if the form was submitted, dump the form scope. In Firefox, we see what you might expect:

But in Chrome or Safari, you'll notice a small difference:

The extra table row shows that there is another key in the structure; but as we can see it doesn't have a key name. I'm not sure why the value isn't displaying, because it's there. I'm guessing it's got something to do with the null key name. (I'm filing this whole thing under odd but true.)
So if you attempt to loop over each key and output it, depending on your method, you'll run into an error. I'm personally a fan of the structName[keyName] notation, so when I first tried this, no error was thrown, and my output was:
<cfif structKeyExists(form, "submitBtn")>
<cfloop collection="#form#" item="key">
<cfoutput>#key#=#form[key]#</cfoutput><br/>
</cfloop>
</cfif>
Outputs:
=foobar SUBMITBTN=Submit FIELDNAMES=SUBMITBTN
I know that not having a key name can cause problems though. Let's try outputting each value using evaluate instead of structName[keyName] notation.
<cfif structKeyExists(form, "submitBtn")>
<cfloop collection="#form#" item="key">
<cfoutput>#key#=#evaluate("form." & key)#</cfoutput><br/>
</cfloop>
</cfif>

Now, I'm always saying there's almost never a good excuse for using evaluate because there's almost always a more efficient way around it. For that reason, I can't think of what you might be doing that would put you in this situation… but it's still best that you're aware of the potential issue.
My advice would be to either try to put the nameless form fields outside of a form (which would be considered malformed XHTML), or to just give it a name and ignore it in your processing. The real lesson here is not to ever rely on browser quirks, because they may not exist in your favor forever.
Posted in Best Practices | ColdFusion | 3 Responses
While the name attribute is indeed marked as #IMPLIED in the HTML DTD, if you look, there is a comment on the input element that states: "attribute name required for all but submit and reset." (http://www.w3.org/TR/REC-html40/sgml/dtd.html)
Furthermore, if you look at the HTML spec you will see that in order for a form control to be successful, i.e. valid for submission, it must have a control name. (http://www.w3.org/TR/REC-html40/interact/forms.html#successful-controls)
Still this is very good to know.
I was able to find a bug already entered for it in the WebKit bug database (https://bugs.webkit.org/show_bug.cgi?id=20184), but they claim it's already fixed -- or at least the fix has been committed to the repository, as of 23 Feb 2009. Perhaps that's just not made its way into the latest Safari and Chrome releases. Seems reasonable enough, considering how recent the fix was committed.