November 20, 2008

Pages


Search Site


Topics



Archives

Tweets

Popular Posts Pod Plugin for Mango

November 11 2008 by Adam

I've created a plugin for Mango Blog that will list your N most popular (most commented) posts in a pod, at the request of Russ Johnson. I've been meaning to figure out how to make custom pods in Mango, so it seemed like a good place to dive in.

The plugin seems to work fine for me in my development site and on another Mango blog I have (not in use here on FusionGrokker – my theme isn't pod enabled), but I've been told by a friend who tried it that he had trouble with it and didn't see the pod show up. Everyone is short on time these days, so I've decided to throw this out to the community and see if anyone can find anything wrong with it. As far as I can tell, it should work fine, and generally I would just post it and call it done… but with the only report I've gotten back so far being negative, I'd like some more feedback.

Download Mango Popular Posts Pod Plugin

Here are some things to do to find issues (if there are any).

  • Is your Mango installation up to date? You should be at version 1.2.2, at least.
  • Is your theme pod-enabled? It must be. If you can view the "pod manager" section in admin and it doesn't say that your theme isn't pod enabled, then it is.
  • Did you correctly spell the Pod ID when you added it in Pod Manager? ("Popular Posts" the space is required, but the text is case-insensitive)
  • Make sure no errors or warnings are captured by Mango when activating the plugin or viewing your blog. To check this:
    • De-activate the plugin, if it's active
    • Delete these files, if they exist
      • /components/utilities/logs/error.log.html
      • /components/utilities/logs/warning.log.html
    • Activate the plugin; check for existence of error log or warning log
    • Configure; check for existence of error log or warning log
    • View your blog homepage, pod should be displayed; check for existence of error log or warning log

Like I said, it works fine for me. Hopefully it will work for you too. If any of the above steps cause the error and/or warning logs to come back for you, please feel free to email them to me. My email address is in the License.txt included in the zip, as well as the license blurb at the top of all of the other included files.

Posted in My projects | Mango | 2 comments

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:

<cffunction name="currentTime" output="false">
<cfreturn "The current time is #timeformat(now())#<br />"/>
</cffunction>

#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:

<cfscript>
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;
}
</cfscript>

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:

<div id="buttons">
<button class="standard" onclick="doStuff1();">1</button><br />
<button class="standard" onclick="doStuff2();">2</button><br />
<button class="standard" onclick="doStuff3();">3</button>
</div>

And now our single row of horizontal buttons:

<div id="buttons">
<button class="standard" onclick="doFoo();">Foo</button>
<button class="standard" onclick="doBar();">Bar</button>
<button class="standard" onclick="doFooBar();">Foo & Bar</button>
</div>

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:

<button class="standard fixedW">...</button>

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 | 7 comments

Announcing my Twitter Bot: TwitMeBack

September 28 2008 by Adam

Over a few evenings last week and over the weekend I wrote a twitter bot. It's not a client or a mashup. It simply looks for you to say certain things and replies later. It's basically a glorified alarm clock — one that you can set and receive via text message (if you have twitter setup for mobile updates).

The syntax is pretty simple:

@twitmeback in 15 time to make the donuts

or

@twitmeback in 1:45 check parking meter

You can specify the duration until you're reminded in either [hours]:[minutes] or just in a count of minutes.

Where I think this really gets useful is that it can do direct messages, too. Personally I prefer to keep mobile updates to directs only, so if I want a text message reminder, it needs to be in the form of a direct message. The bot will automatically follow you back if you follow it (it checks every half hour). Then, you can set reminders via direct message, like so:

d twitmeback in 30 don't forget to submit your time sheet

or

d twitmeback in 4:00 lunch time!

If your reminder is received via DM, it will remind you via DM. This way, your reminders can be totally private (if that's what you want), or work totally from text message.

Lastly, you can also specify a DM reminder by starting your message with "d", like so:

@twitmeback d in 90 is the pizza here yet?

Now go forth, and be reminded.

Posted in My projects | 2 comments