Archive for the ‘ColdFusion’ Category

I love the CFSPREADSHEET tag that was added to ColdFusion9. It makes working with spread sheet data so easy. The spreadsheets I am given to work with often contain descriptive column names that contain spaces like “First Name” or “Home Phone”. This causes a problem when you try to work with the data in a QoQ (query of a query).

Lets say you have a spread sheet containing these columns: Name, City, State, Postal Code. Then pull it into a query using the cfspreadsheet tag:
<cfspreadsheet action="read" src="c:\Customers.xls" query="customers" headerrow="1" rows="2-65536" sheetname="Customers">

Now try to narrow down the results to only those in a certain postal code. This won’t work of course:
<cfquery name="qryCA" dbtype="query">
SELECT * FROM customers WHERE [Postal Code] = '90210'
</cfquery>

Neither will this:
<cfquery name="qryCA" dbtype="query">
SELECT * FROM customers WHERE [Postal\ Code] = '90210'
</cfquery>

Or this:
<cfquery name="qryCA" dbtype="query">
SELECT * FROM customers WHERE ['Postal Code'] = '90210'
</cfquery>

I have not found any way to escape a space in a column name inside QoQ. But, thankfully there is a way we can manipulate the column names to remove the space.

<cfset colNameArray = customers.getColumnNames() />
<cfloop from="1" to="#arrayLen(colNameArray)#" index="i">
	<cfset colNameArray[i] = colNameArray[i].replace(' ','') />
</cfloop>
<cfset customers.setColumnNames(colNameArray) />

You could use this to completely rename column names if you wanted to. This isn’t just useful for working with cfspreadsheet either, I could see this being used in other circumstances to change the column names.

Thanks to Steven Neiland for pointing me in this direction.

A while back I had the need to do some formatting on a cfgrid. I was using a typical product/price table but the prices are stored with 4 decimals and we needed to display that much resolution. The html version of CFGRID does not directly support this.

Consider this “fake” query set:

<cfset materials=QueryNew("ProductCode,Description,Price","VarChar, VarChar, decimal")>
</cfset><cfset Temp=QueryAddRow(materials,1)>
</cfset><cfset Temp=QuerySetCell(materials,"ProductCode","MAT1")>
</cfset><cfset Temp=QuerySetCell(materials,"Description","Copper Bar")>
</cfset><cfset Temp=QuerySetCell(materials,"Price",3.3400)>
</cfset><cfset Temp=QueryAddRow(materials)>
</cfset><cfset Temp=QuerySetCell(materials,"ProductCode","MAT2")>
</cfset><cfset Temp=QuerySetCell(materials,"Description","Feeler Gauge")>
</cfset><cfset Temp=QuerySetCell(materials,"Price",2.2900)>
</cfset><cfset Temp=QueryAddRow(materials)>
</cfset><cfset Temp=QuerySetCell(materials,"ProductCode","MAT3")>
</cfset><cfset Temp=QuerySetCell(materials,"Description","Plastic Retainer")>
</cfset><cfset Temp=QuerySetCell(materials,"Price",1.3201)>  </cfset>

Note the prices have 4 decimal values, this is how they come to us from the database. If you try to display these with this cfgrid code:

<cfform>
<cfgrid name="testgrid" format="html" query="materials">
</cfgrid>
</cfform>

You will end up with this:

Continue reading ‘Formatting CFGRID with JavaScript’ »

When you pass several form or URL variables into ColdFusion with the same name, they end up as a comma separated list. This is commonly done with checkboxes – a user can check as many items as they want, then they will end up in your code all in a single variable. In many other languages, Ruby or PHP for example, the selected items will end up in an array. Getting these values as a list usually works fine, until one of your values contains the list delimiter (comma). Take this form, for example:

<form action="test.cfm" method="post">
<p>Select your books:</p>
<input type="checkbox" name="books" value="A Wrinkle in Time"/>
A Wrinkle in Time<br />
<input type="checkbox" name="books" value="A Tale of Two Cities"/>
A Tale of Two Cities<br />
<input type="checkbox" name="books" value="The Lion, the Witch and the Wardrobe"/>
The Lion, the Witch and the Wardrobe<br />
<input type="submit" name="submitButton" value="Go"/>
</form>

example of the book form

If you check the first two boxes and submit the form, you will end up with this in the form scope:
a dump of the form scope shows two books separated by a comma

But if you check the third book, which has a title containing commas, things start to get messy:
Dumping the form scope with a book containing commas - you can't tell them apart.
Continue reading ‘Accessing ColdFusion form values as an array’ »

At work we had an issue where we had too many FCKeditor rich text controls on a page at once. We probably had 6 or 7, each on their own tab. For the tabs we are using the <cflayout type="tab"> tag. FireFox would handle the page with no problems, but IE would sometimes fail to load one or more of the rich text controls and would not throw any kind of error about it. The controls simply did not display.

A solution we came up with was to load the rich text controls on demand, when the user needed to use them, rather than load them all when the page first loads. At first I thought we’d have to install a separate, stand alone copy of FCKeditor (now called “CKEditor”) to do this, but we found out this is unnecessary, you use the version that comes with CF to do this.

First, we manually load the FCKeditor JavaScript:
<script type="text/javascript" src="/CFIDE/scripts/ajax/FCKeditor/fckeditor.js"></script>

Then create a function that can change a regular textarea into a rich text controls:

<script type="text/javascript">
function changeToRichText(elementToHide,id,width,height) {
	var oFCKeditor = new FCKeditor(id,width,height,'my_toolbar_set') ;
	oFCKeditor.BasePath = "/CFIDE/scripts/ajax/FCKeditor/";
	oFCKeditor.ReplaceTextarea();
	if (elementToHide) elementToHide.style.display = 'none';
	}
</script>

Then we changed the places on the page that used to have rich text controls to instead use plain textareas. Then placed an link next to each one the user can click on to change the textarea into a rich text. Sometimes they don’t need the functionality of rich text and will just enter plain text into a textarea. Here is the code:

<div id="rootCause_outter" style="text-align: left; width: 100%;">click to use editor<br /></div>
<textarea name="rootCause" style="width:740px; height: 290px;"></textarea><br />

This is used for creating records only, not editing. But it would not be hard to modify this to make it work on an edit page also.

I have been involved in setting up a new Mura site on Windows 2008 Server. Mura is a full featured CMS written in ColdFusion.

By default Mura URLs look something like /index.cfm/SiteID/pagename. So for example the contact us page might look like /index.cfm/default/contact-us. Not a great URL. But its fairly simple to translate into /contact-us which is much nicer.

Getting rid of the SiteID

Getting rid of the siteID is easy in the newest version of Mura. In the config/settings.ini.cfm file there is a setting named “siteidinurls”. Set this to 0 and Mura will no longer add the siteID to the URLs it generates. Of course this only works if you plan on only using Mura for one site. If you had more than one site, Mura wouldn’t know which one you are trying to access. There are several ways to get around this if you have more than one site, but I won’t get into that in this article.

Getting rid of the index.cfm

Getting rid of the index.cfm takes a little more work. There is another setting in the ini file called indexfileinurls. Setting this to 0 will remove the index.cfm from the URLs Mura generates. But when you click on any of those links you are going to get the 404 page. To fix this, you’ll need to tweak your webserver.

Apache is pretty straight forward, as you would expect. Enable the mod_rewrite module and drop this into an .htaccess file in your webroot:

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]

Our site happens to be hosted on Windows 2008 Server / IIS7. To do the rewriting on II7 you’ll need to install Microsoft’s URL rewriting extension. You can get it from here: http://www.iis.net/download/URLRewrite

Once its installed, open IIS Manager. Click on your website, then double click on the new URL rewrite icon.

Continue reading ‘Mura URL rewriting on Windows 2008 / IIS7’ »

I ran into an issue today where users were unable to lookup a certain part in our system. The part in question had a µ character in the product code (don’t get me started!). I started adding some debug outputs and found that when the part number was passed to our back end system, the µ had been replaced with an ‘M’!

After some more troubleshooting I figured out the culprit was ucase(). We run all part numbers through ucase() before passing them in. At first I thought this was a CF bug, after verifying that the java string.toUpperCase() method did exactly the same thing I had to look into it some more.

It turns out that M actually is the uppercase version of µ, sort of. The µ character, which is ascii code 181, is often used to abbreviate ‘micro’ as in microamp (µA) or microfarad (µF). Its the 12th letter of the greek alphabet, ‘Mu‘. The lowercase version is μ, the uppercase version is M.

I tested this on Railo and got exactly the same result, which makes sense because I think both engines just call the .toUpperCase() method in the JVM.

So while this is technically correct, I’m certain is almost never what the developer actually wants to do. I have not found a good way around this issue, except to maybe look specifically for this character, replace it out, do the ucase(), then put the character back. For now I was able to remove the ucase() calls because they were not absolutely necessary. Any other ideas?

Update: This is what I came up with as a work around. I thought it would be slow but benchmarking it shows its 0ms even with a 50 character string.

<cffunction name="safeUcase" returntype="string" hint="Uppercases only letters">
	<cfargument name="inputString" />
	<cfset local.outputString = "" >
	<cfloop from="1" to="#Len(arguments.inputString)#" index="local.i">
		<cfset local.chr = Mid(arguments.inputString,local.i,1) />
		<cfset local.asciiCode = Asc(local.chr) />
		<cfif local.asciiCode LTE 122 AND local.asciiCode GTE 97>
			<cfset local.outputString &= ucase(local.chr) />
		<cfelse>
			<cfset local.outputString &= local.chr />
		</cfif>
	</cfloop>

	<cfreturn local.outputString />
</cffunction>

The built in CF debugging information displayed at the bottom of every page is very useful. But there are times where it doesn’t work very well. For example, any time you are using a framework, or where you are passing content around to CFC methods. Any data passed to a CFC method will be shown in the standard debugging information. This can cause havoc if the content contains some JavaScript. I use the datatables jQuery plugin on my site, so I have some JavaScript calls that turn a regular HTML table into a “datatable”. But when debugging info is on, this JavaScript code can get run several times, since the browser doesn’t know to ignore the JavaScript listed in the debugging information. This causes problems.

So I have an interest in getting rid of some of the info, but I do want some of it, mainly the queries. Its actually very easy to customize the ColdFusion debugging information. In the ColdFusion administrator, under the Debugging Output Settings menu there is a drop down to select the debugging format.

CF Debugging drop down

The files listed here are the contents of the C:\ColdFusion9\wwwroot\WEB-INF\debug directory. To create a custom debugging output all you need to do is drop a new file in this directory. Start with an existing one and customize it to your needs.

Here is one I’ve created that only shows database queries: Download queriesOnly.cfm

Did you know there is an IsDebugMode() function in ColdFusion? I just discovered this. This will be great for showing additional data when you are debugging your app. For example, you could leave this code in your order view page all the time:

<cfif IsDebugMode()>
    By the way here is the complete order:
    <cfdump var="#orderBean.toStruct()#">
</cfif>

IsDebugMode() will return true whenever you have debugging enabled in the Administrator and you are coming from one of the allowed debugging IP addresses. This works in Railo and OpenBD, too.

There is an interesting change in the CF9.0.1 updater that will make CF sites more secure. The CFID and CFToken cookies will now be marked as httpOnly. What this means is your browser will not allow JavaScript to access the CFID and CFToken cookies. I think this will greatly help to reduce XSS hacks on CF sites.

If you are using jSessionID instead of CFID/CFToken, you need to take an additional step. jSessionID is a session cookie, session cookies aren’t httpOnly by default. But if you add a “-Dcoldfusion.sessioncookie.httponly=true” argument in your jvm.config file, all your session cookies will be httpOnly, including jSessionID.

It would be nice if there was an option to the CFCOOKIE tag to mark a cookie as httpOnly or not. Lacking that, you could always send the cookies yourself using cfheader or java.

We have a new ColdFusion book! The CF community has not been blessed with an abundency of printed materials, so I was excited when I heard this book was coming out. Adobe ColdFusion Anthology is a compilation of Fusion Authority Quarterly Update articles. FAQU is a great publication that has contributions from many smart ColdFusion developers.

This book is 476 and covers a lot of interesting things. I’ve been using CFCs for years but I learned some new things in Michael Dinowitz’s chapters on Components. There are articles on all the major frameworks, there is even one on the new FW/1 framework.

Pete Freitag has a good article on image processing that also covers creating your own captchas. Did you know ColdFusion can read EXIF data?!

I also found John Mason’s article on BlazeDS interesting since I’ve never used BlazeDS before. I’ve always been confused about the differences between BlazeDS and LiveCycle Data Services, and this article helped clear some of that up.

This isn’t a beginner book, I’ll bet every CF developer out there could learn a few things from this book. Also they’ve done a nice job with the editing, everything is clearly explained.

Adobe ColdFusion Anthology
http://www.amazon.com/dp/1430272155/