Tuesday, November 05, 2002
CF Webtools
MX Consulting
Nebraska CFUG
mkruger@cfwebtools.com
Adaptive Tags
Among the many ingenious presentations I've seen on the subject of the new CFMX server, the one by Tim Buntel (Product Manager for Cold Fusion) was the best. He demonstrated the use of "adaptive tags" using the new <Cfimport...> tag.
<Cfimport...> is use to import one or more "tags" (either CF custom tags or java custom tags) into a page process. The syntax is quite easy
<cfimport taglib="somedirectory/" prefix="tgLib">
The prefix is then used to reference that library, followed by a colon, followed by the name of the tag. For example, if you had a tag named "calculate" in the /somedirectory directory, you would do something like the following (assuming that "tgLIb" is your prefix):
<tgLib:calculate number_x="10" number_y="15" method="Add">
"Great..." you say, "an easy way to group methods and tags together and use a single call to get them into the request. But wait, there's more (with my apologies to Ron Poppeal)! CFMX, either by design or by design flaw, allows you to use the <Cfimport...> tag without a valid prefix. You can actually do this:
<cfimport taglib="somedirectory/" prefix="">
How is that cool? Consider what would happen if you created a simple CF template called "b.cfm" with the following code in it:
if(thisTag.executionMode is "end"){
thisTag.generatedContent = '<b style="font-size: 14pt; font-weight: bold">';
}
If you imported the tag library folder without a prefix, this code would run whenever you placed a <b> </b> around any code you wished to bold face. This would enforce, not only bold face type, but a particular style of bold face. Yeah, I know, you can do the same thing with style sheets (designers always think they are so clever - sheesh). Ok, before we start rewriting the entire HTML standard, let's look at an example that is really useful. How about solving the "cookieless browser" problem once and for all.
Every CF programmer knows about the cookieless browser problem. It's a big pain in the keester. The problem is pretty simple to explain. Most really useful applications rely on some form of user identification. For example, a user logs in, you identify who he or she is by their username and password, then you let them have access to something. Simple - right? Wrong! A ColdFusion session (whether you are using client variables or session variables) relies on something being passed back and forth from the client to the web server. Because HTTP is a stateless protocol, it is necessary to constantly remind the web server of who you are. Essentially, every http request has to say, "hey! it's me again... remember me?"
The simplest way to do this is with cookies. This is CF's "default implementation". 1 or more cookies are set that are unique to the user. In CFMX you can choose between the traditional CFID/CFTOKEN, a UUID (new in CF 5 and carried forward) or a JSessionID (which does not work very well with an IIS installation - go figure). This item is stored in a cookie and passed back to the server as a way of identifying their unique session.
The problem with this approach has always been that not every user or browser supports cookies. Some users turn them off for security reasons. Some firewalls and proxies deny cookies as well. Therefore, to support sessions on a cookieless browser, a developer had to append the CFID and CFTOKEN (or whatever session identifier he was using) to every URL in a given application. Believe me, that's a real headache.
In CFMX Macromedia has made it much easier. They have provided a function (called UrlSessionFormat()) that you can wrap around your href that will append the variables if the browser doesn't support cookies. This is nice. Cookie people will see nice clean URLs, and non-cookie people will see the session Identifier passed with every URL. But this is still not quite convenient is it? A developer will still have to wrap the function around every Href - making it tedious to use. All of his link code will resemble the following:
<a href="<cfoutput>#UrlSessionFormat(blah.cfm)#</cfoutput>">click here</a>
Ok Macromedia - I appreciate the effort, but my keester is still bugging me (maybe I need more roughage). This is where the adaptive tag can come to the rescue. What if we rewrote the anchor tag (<a...>) to automatically wrap the href in the UrlSessionFormat() function. That aught to be easy. Let's try it. Here's a tag we call "a.cfm" and we store it in the /tagLib/ mapping.
<cfscript>
if(thisTag.executionMode is "end"){
/* Copy out the Href into a local
variable so we can safely delete it */
href = attributes.href;
/* delete the Href key so our loop
through the attributes doesn't duplicate it */
structDelete(attributes,"href");
// loop through attributes and write link
strTemp = ' ';
FOR(att IN Attributes)
{
strTemp = strTemp & att & '="' & Attributes[att] & '" ';
}
// Write out to the page (line breaks are for clarity)
thisTag.generatedContent = '<a href="' & UrlSessionFormat(href) & '" '
& strTemp & ">" thisTag.generatedContent & "</a>";
}
</cfscript>
Now, all we need to do is include the <Cfimport...> call shown below at the top of our page request, or perhaps in the application.cfm file.
<cfimport taglib="somedirectory/" prefix="">
Every anchor tag included in the document from that point forward will automatically support cookieless browsers. That is one real-world example of how adaptive tags can solve a long standing programming problem.
:: posted by Mark at 9:30 AM
|