Adobe ColdFusion Inconsistencies

I've run into a couple of ColdFusion quirks over the past few days that I thought I'd share. (I should note that these were observed on Adobe CF 8.)

SerializeJSON and Boolean Strings

If you try to serialize the strings "Yes","No","True" or "False" using SerializeJSON, ColdFusion will convert these strings to boolean values. (i.e. "Yes" becomes true, "False" becomes false). This is because ColdFusion is weakly typed and uses some pretty liberal implicit conversion rules when it comes to boolean evaluation. I see this as an issue for the purposes of searializing and deserializing JSON for two reasons. First, there is the potential to lose data. If you serialize the string "Yes" and then deserialize the JSON that ColdFusion generates you are left with true, which is obviously a totally different value than what you started with. Second, it is not really consistent behavior because SerialzeJSON does not convert 1 or 0 (also ColdFusion booleans) to the boolean values true and false. I think the better approach here would be to serialize all strings as strings and only serialize "real" boolean values as booleans.

IsXML()

The other inconsistency I ran into was with IsXML. If you pass something other than a string to IsXML the function throws an error. This is different than the documented behavior which states:

Returns

True, if the function parameter is a string that contains well-formed XML text; False, otherwise.

This is also different than the other CFML decision functions which simply return false if passed a function parameter they can't handle. (See IsXmlAttribute for example.)

I think the IsXML issue could definitely be consider a bug, and while the SerializeJSON issue is a little fuzzy, I've gone ahead and reported both as bugs.

ColdFire 1.2 Released

The new beta for Firebug was released over the weekend so I'm happy to say I'm releasing ColdFire 1.2 into the wild. Head over to the RIA Forge site to check it out.

[More]

ColdFire SVN

As you may have heard Ray Camden and Rob Gonda recently made some updates to RIAForge which allow project owners to share SVN access. After this update Ray was kind enough to give me access to the ColdFire repository and since then I've done some reorganizing. So, what will you find in the ColdFire SVN repo?

[More]

ColdFire Security Update

A little over a week ago I became aware a 0-day security exploit in ColdFire. I finally have a working fix which Ray has just released over at RIAForge. I strongly recommend that all ColdFire users download and install the latest version (1.003) as soon as possible.

Spry AutoSuggest With Multiple Parameters

When loading datasets from the server for for the Spry AutoSugget widget, Spry passes the value of the search field as a parameter to the dataset URL. This works fine, but what if the suggestions you want to provide are based on a combination of form fields?

To give you a better of idea of what I mean, here is an example of a search form I was working on earlier today: (Note: this form doesn't work.)

Find users within of the following :

I wanted to provide suggestions for the search term, but I wanted to limit those suggestions to only the country (U.S. or Canada) and type (City or Postal Code) selected. So if a user selects U.S. Cities they should only get U.S cities as suggestions, no Canadian cities or postal codes of any kind. This turned out to be fairly easy but I though I'd share my approach in case others are interested.

Basically what I needed to do is append multiple parameters to the dataset URL. To accomplish this I added a new function to the Spry AugoSuggest widget named addReplaceParams:

Spry.Widget.AutoSuggest.prototype.addReplaceParams = function(params)
{
   
   var ds = this.dataset;
   ds.cancelLoadData();
   ds.useCache = false;
   
   this.setValue('');
   this.showSuggestions(false);
      
   var url = ds.url;
   
   for(var i=0; i < params.length; i++) {   
      url = Spry.Widget.Utils.addReplaceParam(url, params[i].param, params[i].value);   
   }      
   
   ds.setURL(url);
   ds.loadData();
   
};
In a nutshell this function clears the search term, hides suggestions and updates the AutoSuggest's dataset URL using an array of parameters passed to the function. The parameters are defined as simple JavaScript objects with two keys: param which is the name of the URL parameter, and value which is the value of the URL parameter. It does the actual parameter additon/replacement using the Spry.Widget.Utils.addReplaceParam() function. To update the URL using this function I wrote another function which I use as the onChange event handler for the country and type select elements.
function updateDsURL(f){
   
   var country = f.radiusCountry[f.radiusCountry.selectedIndex].value;
   var type = f.radiusType[f.radiusType.selectedIndex].value;
   
   var params = [];
   params[0] = {param:'radiusCountry',value:country};
   params[1] = {param:'radiusType',value:type};
   
   theSuggest.addReplaceParams(params);   
};

Putting it all together this is what it looks like:

<html>
<head>
<script language="JavaScript" type="text/javascript" src="includes/xpath.js"></script>
<script language="JavaScript" type="text/javascript" src="includes/SpryData.js"></script>
<script language="JavaScript" type="text/javascript" src="includes/SpryAutoSuggest.js"></script>
<link href="includes/SpryAutoSuggest.css" rel="stylesheet" type="text/css" />
<script language="JavaScript" type="text/javascript">
var ds1 = new Spry.Data.XMLDataSet("/suggestions.cfm","radiusvalues/radiusvalue");

function updateDsURL(f){
   
   var country = f.cboRadiusCountry[f.cboRadiusCountry.selectedIndex].value;
   var type = f.cboRadiusType[f.cboRadiusType.selectedIndex].value;
   
   var params = [];
   params[0] = {param:'radiusCountry',value:country};
   params[1] = {param:'radiusType',value:type};
   
   theSuggest.addReplaceParams(params);   
};


Spry.Widget.AutoSuggest.prototype.addReplaceParams = function(params)
{
   
   var ds = this.dataset;
   ds.cancelLoadData();
   ds.useCache = false;
   
   this.setValue('');
   this.showSuggestions(false);
      
   var url = ds.url;
   
   for(var i=0; i < params.length; i++) {   
      url = Spry.Widget.Utils.addReplaceParam(url, params[i].param, params[i].value);   
   }      
   
   ds.setURL(url);
   ds.loadData();
   
};
</script>
</head>

<body>
<form>
<p>
Find candidates within
<select name="radius">
   <option value="0" selected>Any Distance</option>
   <option value="1">1 mile</option>
   <option value="2">2 miles</option>
   <option value="3">3 miles</option>
   <option value="4">4 miles</option>
   <option value="5">5 miles</option>
   <option value="10">10 miles</option>
</select>
of the following
<select name="radiusCountry" onChange="updateDsURL(this.form);">
   <option value="U" selected>U.S.</option>
   <option value="C">Canadian</option>
   <option value="B">U.S. or Canadian</option>
</select>
<select name="radiusType" onChange="updateDsURL(this.form);">
   <option value="City"selected>City</option>
   <option value="Zip">Postal Code</option>
</select>:
</p>

<div id="mySuggest">
<input type="text" name="radiusValue"/>
<div id="resultsDIV" spry:region="ds1">
<ul>
<li spry:repeat="ds1" spry:suggest="{radiusvalue}">{radiusvalue}</li>
</ul>
</div>
</div>
<script type="text/javascript">
   var theSuggest = new Spry.Widget.AutoSuggest("mySuggest","resultsDIV", "ds1","name",{minCharsType:3, loadFromServer:true, urlParam:'filter'});
</script>

</form>
</body>
</html>

You may ask why two functions? Well, I thought this is something I may want to use again so I made the Spry.Widget.AutoSuggest.addReplaceParams() function fairly generic. For this example I included the function in the inline script block, but if I use it enough I'll probably end up putting it in my AutoSuggest.js file.

OK, that's one down...

ColdFire 1.002

Today Ray and I released ColdFire 1.002 which fixes a few minor issues with JSON encoding. If you were having problems with the variables feature of ColdFire this update may fix your issue. Be sure to update both the Firefox extension and coldfire.cfm debugging template. You can get both via the download at RIAForge.

We have also been discussing upcoming features so if there is something you would really like to see be sure to let us know via the RIAForge site.

Troubleshooting ColdFire

A few people have reported that they are unable to see debugging in the ColdFire Firebug panel. I've been unable to reproduce these issues so I thought I put together a quick post on how ColdFire works in hopes that it may help people debug their issues.

[More]

ColdFire 1.001

Ray just posted version 1.001 of ColdFire over at Riaforge. This version should now work when you open Firebug in a new window.

Get ColdFire!

As you may have seen on Ray's blog, today we released version 1.0 of the ColdFire ColdFusion Debugger. For those that don't know ColdFire is extension to the Firebug Firefox extension, similar to YSlow, only ColdFire displays ColdFusion debugging info. To use ColdFire you need to install a custom debugging template on your server (coldfire.cfm) then configure ColdFusion to use this template via the Administrator. (Detailed installation instructions can be found in the download.)

[More]

ColdFire 0.0.6

On Sunday Ray quietly released version 0.0.6 of ColdFire. With this version, the ColdFire extension actually modifies the user agent by adding "ColdFire/0.0.6" to the end of the string. This allows the coldfire.cfm debug template to check the user agent header for this string and only return debugging info if it is present. This means you shouldn't encounter much debugging overhead if you don't have ColdFire installed or if you choose to disable Firebug for your site. ColdFire only modifies the user agent header if Firebug is enabled.

While this may seem like a minor update it actually involved some major changes to the FireFox extension code. The biggest change was the addition of an XPCOM object to handle the request header modification. Compiling an XPCOM typelib requires the Gecko SDK and unfortunately there isn't an Intel Mac build of the SDK. While I could have tried to build it myself, in the interest of time I ended up switching to my PC for extension development. Even then, building the typelib wasn't exactly straightforward. If you find yourself trying to build a XPCOM component on Windows you may find the following helpful: Find xpidl.exe in Gecko SDK for compiling IDL files.

Anyway , enjoy and look for more ColdFire updates soon.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.