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.

11 comments:

cinod said...

Cool,
Im gonna give this a try. RichUI simile version had a problem with url_prefixes.

Josh Reed said...

Hi cinod,

Let me know how it works. I've been using it successfully in two different grails webapps and it has been working well for me. I'm sure there's plenty of room for improvement, though.

Cheers,
Josh

Andreas said...

The issue you mentioned with RichUI should be resolved now, as it also uses a local copy of the Timeline API.

Josh Reed said...

Good to know, Andreas. I'll definitely check it out as RichUI offers more functionality (in terms of other libraries) than my version. I'm also interested in checking out how you handled the Timeline creation boilerplate code in an actual view.

Cheers,
Josh

cinod said...

Just Gave the RichUI version a try. Too bad the taglib doesnt allow setting the interval of the timeline.

I tried your simile version the other day but do i have to call the javascript myself?

Josh Reed said...

There is a taglib for helping out. Check out lines 8-10 in:
http://hg.andrill.org/timelines/file/083edce12b79/grails-app/views/timeline/show.gsp

The taglib is out at:
http://hg.andrill.org/simile-grails-plugin/file/21b2f019fe3e/grails-app/taglib/SimileTagLib.groovy

It is not very flexible at the moment.

Andreas said...

Hi cinod,

an interval setting will be added, you are not the only one who requested this feature.

@josh
Do you plan to integrate other Simile projects such as Timeplot?

Josh Reed said...

Hi Andreas,

Potentially, but I haven't had a need in my own projects for it yet. If you're serving local copies of the Timeline code with RichUI, I should be able to use it. The main reason I did my own was because I'm using a custom unit extension to Timeline.

I need to go back and check out RichUI to see how easy it is to serve my own extension and replicate my application with it. Give me a day or so to check it out. If it does what I need, I'll deprecate my plugin in favor of RichUI and we can perhaps collaborate on future enhancements.

Cheers,
Josh

cinod said...

Thanks alot Andreas, will look forward to it.

Stephen said...

I just downloaded the complete source code, but am a newbie to this. I have an existing Timeline up and running and was wondering if you had some simple directions on how to integrate your plugin into my existing SIMILE Timeline application web page?

thanks

Steve

Anonymous said...

Your ideas seem interesting but none of the examples-links work. Please make them available again.Thanks.
- Mike S.