March 12, 2010

Pages


Search Site


Subscribe

...to receive future posts via email.

Topics



Archives

Entries for month: October 2008

Easily Cache the Return Value of Any Function

October 14 2008 by Adam

Work in web development long enough, and you'll run into caching. When done appropriately, it can be a real life saver. In CFML, we have several caching tools at our disposal.

The built in cfcache function will cache an entire page, and there are a bunch of projects on RIA Forge (search for "cache") that deal with caching of whole pages, partial pages, and specific data; and use various methods from memcached to underlying java caching. And of course, you can always roll your own cache using a persistent scope (application, session, client, or cookie) and some date comparison.

After about the 100th time of rolling my own custom caching, I decided it was time to wrap it up in a nice little UDF.

Before I show you the code, here's an example of how to use it:

"/> #cacheCallback("myApp.CurrentTime", CreateTimeSpan(0,0,2,0), variables.currentTime)#

Pretty simple, right? The first argument is a unique string that's used as the cache key, to identify which bit of data we're caching. The second is how long the cache is good for, and the third argument is a reference to a simple function that displays the current time.

Notice that the 3rd argument is not a string containing the name of the function to be executed, but actually a reference to the function itself. My cacheCallback function will check to see if the cache is expired, and either return the cached value or re-run the function being passed in and return the result, as appropriate.

A fourth and optional (boolean) parameter will force a cache refresh if true.

This has already proven useful, as a fellow Mango Blog plugin developer is using it to cache API results from services like Twitter and Flickr in some plugins he'll be releasing soon.

Here's the code for the cacheCallback function:

function cacheCallback(cacheKey, duration, callback){ var data = ""; //optional argument: forceRefresh if (arrayLen(arguments) eq 4){ arguments.forceRefresh=arguments[4]; }else{ arguments.forceRefresh=false; } //clean cachekey of periods that will cause errors arguments.cacheKey = replace(arguments.cacheKey, '.', '_', 'ALL'); //ensure cache structure is setup if (not structKeyExists(application, "CCBCache")){ application.CCBCache = StructNew(); } if (not structKeyExists(application.CCBCache, arguments.cacheKey)){ application.CCBCache[arguments.cacheKey] = StructNew(); } if (not structKeyExists(application.CCBCache[arguments.cacheKey], "timeout")){ application.CCBCache[arguments.cacheKey].timeout = dateAdd('yyyy',-10,now()); } if (not structKeyExists(application.CCBCache[arguments.cacheKey], "data")){ application.CCBCache[arguments.cacheKey].data = ''; } //update cache if expired if (arguments.forceRefresh or dateCompare(now(), application.CCBCache[arguments.cacheKey].timeout) eq 1){ data = arguments.callback(); application.CCBCache[arguments.cacheKey].data = data; application.CCBCache[arguments.cacheKey].timeout = arguments.duration; } return application.CCBCache[arguments.cacheKey].data; }

I've submitted this to CFLib, so hopefully it will be approved soon.

Disadvantages:

I tried for a while to figure out a way to pass arguments into the callback function, but never came up with anything. When I added a callbackArgs argument and passed that in as an argumentCollection to the callback function, CF threw an error telling me that I couldn't use named arguments in this case. I also tried to use CFInvoke, but that required passing in a string containing the name of the function instead of a reference to it, which while it would actually work with some massaging, wouldn't work as well in an Object Oriented architecture where passing objects (like function references) as arguments is common practice.

So for now, your callback functions must run without any arguments. If anyone has any other ideas for how to pass in arguments, I'm all ears.

Posted in ColdFusion | 1 comments

New Themes for Mango Blogs

October 13 2008 by Adam

Mango Blog comes with some great themes, and with Mango's awesome custom tag access to data, it's super simple to create your own or modify an existing one to suit your tastes. But not everyone is a designer or has time to give it a shot. My buddy Mark has created a new site devoted to Mango themes called MangoWear.

There are both free and "premium" (paid) themes, but judging by his portfolio and free themes, I would say that they are definitely worth the cost if you don't want to do the work yourself.

So far there are only a couple of themes available, but it should be growing all the time. Go check it out!

Posted in Mango | 0 comments

HTML/CSS Tip: Specifying Multiple Classes

October 06 2008 by Adam

Since CFML developers are essentially very specialized web developers, I feel that it's important to continually learn and improve my skills not only with CFML, but also with HTML and CSS. Here's a trick I picked up earlier this year that I think could benefit a lot of people.

The beauty of CSS is that you can write simple, reusable rules that can be applied throughout your site to provide a consistent look and feel without setting individual display properties on every object on the page. You already knew that.

But let's say that you want all of your site's button elements to have the same overall style: a specific font, a background and border color, and maybe a set of color changes for hover (not displayed in IE). But on certain pages, you want all buttons to have a fixed width so that their edges line up when stacked vertically, and on other pages you want widths to be automatic so that you can fit more in a single horizontal row. This is a great case for multiple classes.

Take these two HTML samples (from different pages) for example. We'll start with our set of vertically stacked buttons:



And now our single row of horizontal buttons:

Let's make them flat, with a light shade of gray for their background, and a darker shade of gray for their border. Add some font styling and a hover style, and they start to look pretty decent:

button.standard{ background-color: #eee; border: 1px solid #bbb; text-align: center; color: #666; font-family: Tahoma, Verdana, Helvetica; font-weight: bold; } button.standard:hover{ background-color: #935232; color: #fff; }

Now, here are the two classes that we'll use to specify widths:

button.autoW{ width: auto; } button.fixedW{ width: 200px; }

To apply these size style classes without losing our other styles, we can add them to the class attribute, as if it were a space-delimited list, like so:

Now, we can have consistent color & hover styles for our site, and be able to specify either a fixed or automatic width for it. Using this method, if you decide later that you want your button hover color to be something different, you only have to change it in one place.

I've tested this with IE6 and 7, Safari, and Firefox 1-3. I presume Opera and other modern browsers also support this functionality.

Posted in HTML/CSS | 5 comments