Entries for month: March 2012

CFIMAGE and alt tags

ColdFusion 2 Comments »

Ever used CFIMAGE with the "writeToBrowser" action?  A nifty way to display an image you've read into memory, or maybe made with ImageNew.  However, you may have found yourself looking at the source code and going ARG! when you spotted that empty alt tag. 

<cfset myImage = ImageNew("", 100, 100, "rgb", "##000033") />
<cfset sText.font = "Lucida Sans Regular" />
<cfset sText.style = "bold" />
<cfset sText.size = 14 />
<cfset ImageSetDrawingColor(myImage, "white") />

<cfset ImageDrawText(myImage, "Hello World!!", 5, 50, sText) />

<cfimage action="writeToBrowser" source="#myImage#" />

Get's us:

When you view the source, you see something like:

<img src="/CFFileServlet/_cf_image/_cfimg-9138836666536180171.PNG" alt="" />

Not very good for accessibility at all.  And what if you want to add a style class or ID to that image for CSS or JS purposes? If you just look in the "official" docs, you might feel like too bad, so sad because they don't even mention it at all!

Fortunately, that isn't true, thanks to a feature of this particular tag. Similar to what you'll find with the various form tags, CFIMAGE will basically pass any "extra" parameters to stick on the tag to the resulting img src. So if you need to do an alt, a title, a style, whatever, just tack it on to your tag.  I.E. So with the same image, and using a different CFIMAGE tag:

<cfimage action="writeToBrowser" source="#myImage#" alt="I'ma saying Hello World!" title="I'ma saying Hello World!" style="border: 5px red solid" />

We get:

I'ma saying Hello World!

And the view source shows us something like:

<img src="/CFFileServlet/_cf_image/_cfimg-7816565574866006559.PNG" style="border: 5px red solid" alt="I'ma saying Hello World!" title="I'ma saying Hello World!" />

Nice, eh? :)

Var Scope and CFArgument

ColdFusion No Comments »

I've been developing ColdFusion applications for over ten years now. I wrote fairly good stuff. Some of my apps have pretty much just run since launch with no real issues. But they weren't the best they could be, because I was stuck behind the times. In the last three years or so, thanks to some reorganizations in our unit, attending CFUnited 2009, and I think most importantly having a great working partner, I've been working towards being a better coder and following more "best practices".

One of those best practices is to "VAR scope" variables inside functions. This privatizes the variables in each function, reducing the chance for bleed over, particularly if you use like named variables (for example, many of our functions set up a return status structure of MyResults). By VAR scoping them, each variable will only be seen by that specific function. Without the VAR scope, the variables default to the variables scope, which is open to all functions and those functions can each modify them, which can cause unexpected results.

Putting a variable into the VAR scope is pretty easy, just preface it with VAR:

<cfset VAR myVariable = 1 />

All VAR scoped variables must be immediately after the last tag of your function. You can put comments in, of course, but no other sets or the like can go in until you are done. So I do it in all my functions. When while working on a new project, particularly as I began implementing our first service layer, I had an error come back that I was trying to declare a local variable twice! What? I checked the code again and again, but I was still confused.

<cffunction name="saveCoordinator" access="public" output="false" returntype="struct">
        <cfargument name="Coordinator" type="Coordinator" required="true" />

        <cfset VAR Coordinator = variables.coordinatorsDAO.save(Arguments.Coordinator) />
        
        <cfreturn Coordinator  />

</cffunction><cfset VAR myVariable = 1 />

Some of you are already probably going "well duh, idiot" but it took me a few frustrating minutes to realize my error. Despite my years of experience, I hadn't run into it before because it just wasn't something that had happened before because it wasn't something I'd ever done, until I tried this service layer. The problem?

All cfargument variables are automatically VAR scoped! So with that code, I might as well have had something like:

<cffunction name="saveCoordinator" access="public" output="false" returntype="struct">
        <cfset VAR Coordinator = Arguments.MyCoordinator />
        <cfset VAR Coordinator = variables.coordinatorsDAO.save(Arguments.Coordinator) />
                <cfreturn Coordinator  />

</cffunction><cfset VAR myVariable = 1 />

Now obviously this was a simple example with a simple solution, namely redoing the function like so:

<cffunction name="saveCoordinator" access="public" output="false" returntype="struct">
        <cfargument name="Coordinator" type="Coordinator" required="true" />
    
        <cfreturn variables.coordinatorsDAO.save(Arguments.Coordinator) />
</cffunction>

I am honestly surprised it hadn't happened before, particularly some functions I've built with 20 some arguments coming in. Conflict would seem to be inevitable, but maybe that's because most were built before I started VAR scoping and just haven't been updated yet. Suffice to say, if you get that error about local variables declared twice, but don't see a repeat in your set of VAR variables, make sure you don't have a repeat of that variable in the CFARGUMENT group.

Powered by Mango Blog. Based on the Glossy Blue mango template design and utilizing the Icons of N.Design Studio
RSS Feeds