Tuesday 8 May 2012

CFScript: Odd Struct Initialisation Syntax

Ok, so today I was putting together an application.cfc in CFScript and I ran into an interesting problem.  I was setting up my application variables, and I arrived at this.mappings where I needed to add a couple of custom locations.  With tags it was easy enough:
        <cfset this.mappings["/stuff"] = "C:\assets\resources\stuff">
        <cfset this.mappings["/things"] = "C:\assets\lib\things">

And I know that in script I could have used:
        this.mappings = {};
        this.mappings["/stuff"] =  "C:\assets\resources\stuff";
        this.mappings["/things"] = "C:\assets\lib\things";
But I thought, wouldn't it be better to declare and initialise that struct at the same time?  When I tried to look this up in the Adobe docs, I found the following syntax:
         myStruct = { 
             key1 = "value1",
             key2 = "value2",
             key3 = "value3"
The problem is, in the case of mappings, my key names are all prefixed with a slash.  So trying to write
          this.mappings  = {  /stuff  = "C:\assets\resources\stuff" };
just doesn't work, since it's invalid syntax.  Based on that, I supposed it just wasn't possible to do a declare and initialise in that situation. 

Then I had a crazy thought...waaaay too crazy to work, but I gave it a shot anyway:
         this.mappings = {
             "/stuff" = "C:\assets\resources\stuff",
             "/things" = "C:\assets\lib\things" 
And that WORKS!  To me, the syntax seems completely bizarre because it looks like we're assigning one literal string to another literal string.  But somehow, the universe doesn't implode and ColdFusion interprets it just fine.  As a bonus, the case of the keys is preserved just like when we use the square-bracket notation.  Good stuff!

Does that seem really weird to anyone else?

Saturday 28 April 2012

Multiselect Checkboxes and ColdFusion

Use Checkboxes to Make Multi-Select Option Lists
I've been working with HTML on and off for a while, but somehow I managed to completely miss the idea of multi-select checkboxes until a few days ago.  I've used <select> lists with the multiple attribute, but recently I came across something like this:

Example 1

Notice that all the checkboxes share the same name attribute.  Now, my first though was that this was just plain wrong.  I knew that in the case of radio buttons, options were grouped by giving them the same name.  But I always thought of checkboxes as isolated yes/no controls.  Consequently, if I wanted to add the fruit choices above to a form, I might have done something like this:

Example 2

Checkbox inputs have the interesting beahaviour that, if they're not checked, they're simply not submitted as part of the form.  In terms of ColdFusion, unchecked checkboxes are not contained in the Form struct after submission.  So, in Example 2 (what I previously thought was the "right" way), let's say I check Orange, Kiwi, and Pear but leave Lime unchecked.  Then I submit the form and dump the Form struct in fruitPicker.cfm.  I see the following:

So, my code to determine what fruits had been chosen would simply examine the fieldnames list, and extract the elements that contained the word fruit.  Then I could build a list of selected fruit options.  Something like this:

That works fine, but it turns out I've been doing extra work for nothing.  If we use the form code in Example 1 and submit it with Orange, Kiwi and Pear checked, a dump of the form scope shows the following:

There it is.  Giving all of the checkboxes the same name attribute causes ColdFusion to interpret the selected values as a nice pre-built list associated with that name.  That saves a bit of code and I thought it was pretty cool.  I wondered if it was exploiting some HTML quirk, but it turns out that it's actually in the spec.  Check it out: http://www.w3.org/TR/html4/interact/forms.html#checkbox.

This is likely old-news to some, but if you were in the dark like me, give it a try!

NOTE: It's only the name attribute you want to make the same.  Never give the same id to multiple elements on the page.  It's bad for your DOM and people will laugh at you.