A user on the CF irc channel had an interesting problem. She was trying to use a custom tag to iterate over some data. What most folks don't realize is that custom tags can act as iterators, looping over their body as many times as you want. Consider this first code sample:

<cf_looper from="1" to="10" index="x">

<cfoutput>#x#</cfoutput><br>

</cf_looper>

Now, obviously, you wouldn't do this. You would just use the loop tag. But what if you did? Let's take a look at how looper.cfm would work:

<cfparam name="attributes.from" type="numeric"> <cfparam name="attributes.to" type="numeric"> <cfparam name="attributes.index" type="variableName">

<cfif not isDefined("counter")> <cfset counter = attributes.from> </cfif>

<cfif thisTag.executionMode is "start">

<cfset caller[attributes.index] = counter>

<cfelse>

<cfset counter = counter + 1> <cfset caller[attributes.index] = counter>

<cfif counter lte attributes.to> <cfexit method="loop"> </cfif>

</cfif>

The first three lines simply validate my arguments. We then create a variable to serve as our counter. We start it at our FROM value. We then branch between the start and end execution of our custom tag. When ColdFusion sees <cf_looper>, it runs the tag with thisTag.executionMode equal to start. When ColdFusion sees </cf_looper>, executionMode is end. Now pay attention to what I do in there. First I increase counter. I copy the value again. (This is so that my calling document can output the value.) Then I check to see if I'm at the end of my loop. If I'm not, I use cfexit with method="loop". What that tells ColdFusion is - return to right after <cf_foo>, basically the inside of my tag, execute the code there, than run <cf_foo> in end mode again.

To be honest, I haven't seen many people use the tag like this. The last time I saw it in production mode was in Spectra. Spectra would wrap a content handler with a tag so it could be executed N times. You can imagine code that would print the "Teaser" for an article. You would write the display (Name, a line break, and a portion of the body), wrap it in the tag, and it would work correctly for one content object, or twenty. You could even tell it to use a hr tag, or some other html tag, between each item. Handy! (Not that many of my readers even remember Spectra. -sigh-)