Showing posts with label demo. Show all posts
Showing posts with label demo. Show all posts

Wednesday, March 12, 2008

Simile Timeline and Grails

I just put the finishing touches on a Grails plugin for Simile Timeline. There's already the RichUI Grails plugin which provides a nice wrapper for incorporating Timeline into your Grails app. However, I couldn't use RichUI because it links to the libraries out at the Simile site instead of serving them up locally. This causes cross-domain issues when using my depth extension.

Developing the plugin wasn't too terribly difficult and it was a great opportunity to dig into the internals of Grails a bit. Its plugin architecture is pretty slick. I actually created my plugin directly inside the plugins directory of a webapp I was working on. This allowed me to develop on both the webapp and the plugin at the same time. It's a pretty nice way to work when you have a pretty decent understanding of which pieces you want to go in your webapp and which you want to go in your plugin.

My Simile Grails plugin does a bit more than just packaging the Timeline javascript for serving locally. I put together a handy SimileTagLib for including the libraries so you can simply throw a
<simile:ajax/>
and a
<simile:timeline/>
tag in your view and that will include the javascript libraries. I ran into a bit of a stumbling block when trying to do this because the Javascript code is actually in the plugin. Hardcoding the links wouldn't work because I would have to change the link every time I updated the plugin's version number (Grails installs a plugin as {plugin.name}-{plugin.version}). Fortunately, you can look up the plugin's name and version at runtime:

def p = PluginManagerHolder?.pluginManager.getGrailsPlugin('simile')
return "<script type="text/javascript" src="${request?.contextPath}/plugins/${p.name}-${p.version}/js/${lib}.js?"></script>"

You may be wondering why I called it the Simile plugin instead of the Timeline plugin or what have you. I actually made the plugin generic enough that if I have a need to later, I can package all of the Simile code in the same plugin. The Timeline code already relies on the Simile Ajax library, so the plugin actually packages both libraries.

Along with the taglib, I also created some Timeline-related domain classes for working with timelines and events. I used these domain classes to bootstrap the example webapp I was working on. I simply did a:

grails create-app timelines
cd timelines
grails install-plugin simile
grails generate-all Timeline (domain class provided by the plugin)
grails generate-all TimelineEvent (ditto)
grails run-app

and I was up and running with a webapp that could create and edit timelines and events. Actually displaying the timelines took a bit more customizing, but not all that much.

I've made the source code for the completed webapp available via a Mercurial repository. The webapp gives you a CRUD style interface for creating timelines and timeline events. It supports both date-type of timelines as you see in the examples out at the Timeline site, as well as depth-type of timelines with my depth extension. I've put up a live demo on my development server at work. Feel free to play around with it by creating your own timeline and adding events. It'll stay up until as long as it isn't abused.