Monday, April 28, 2008

Using CIUI in Grails

So this past weekend I needed a fun yet mindless task one morning during at 4 am. I have been looking at both CIUI and IUI and knew they would lend themselves well to being implemented in Grails what with it's oh so easy REST/AJAX style call to the controller layer. In fact this was ever so easy and so I thought I would mention it here so people would know of these nice packages and add these as tools to their Grails toolbox. If you are doing this from Linux (Ubuntu in my case) like I am, you may want to use the webkit engine (Ref: Webkit on Ubuntu performance ). Especially for the IUI package since it seems to render best in Webkit even over the latest FF3 engine.

Starting with CIUI the approach is easy. Place the CiUI.css in your [project]/web-app/css and the CiUI.js into the [project]/web-app/js directories. You may need to scan the CSS file and change image paths and such if you are using images from an other than default location.

I created a simple controller CiuiController.groovy and an associated GSP page index.gsp. Into the GSP page be sure to place:

<link rel="stylesheet" href="${createLinkTo(dir:'css',file:'CiUI.css')}" />
<g:javascript library="CiUI"/>

to load the CiUI css and js files. Obviously you can alter the directory paths and such to keep your application file structure in whatever order you wish.

My whole GSP pages looks like:
<html><head> 
<title>Grails and CiUI Demo</title>
<meta name="viewport" content="width=320"/>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="${createLinkTo(dir: 'css', file: 'CiUI.css')}"/>
<g:javascript library="CiUI"/>
</head>

<body>
<div id="iphone_header">
<div id="iphone_backbutton">
<img src="images/back-button-tip.png" border="0" align="left"/>
<a id="iphone_backbutton_text" href="#" class="go_back">Back</a>
</div>
<div id="iphone_title"></div>
</div>

<div id="iphone_body" style="clear:both;">
<ul class="menu">
<li><a href="${createLink(controller: 'ciui', action: 'page', id: '1')}" class="go_forward" title="Feeds">
Groovy and Grails Feeds
</a>
</li>
</ul>
</div>

<div id="iphone_footer">My footer for CiUI demo</div>

<div id="iphone_loading_page">
<div id='loading' class="info_msg">
<img src="images/loading.gif"/><br/>
loading...
</div>
</div>
</body>
</html>




Next it's just a few simple method calls in the controller. I decided to have a little fun and used the Groovy XML features to pull down RSS feeds from Groovy Blogs, Groovy on Grails and Groovy Zone. There are really only a couple of comments:

1) This whole effort is made very easy by use of the Grails "render" call. It means that we can do things like:

   def page = { 

// you would make this more dynamic in a real app
def feedMap = ['Groovy Blogs': 'http://feeds.feedburner.com/groovyblogs', 'Grroovy on Grails': 'http://feeds.feedburner.com/groovyongrails', 'Groovy Zone': 'http://feeds.dzone.com/zones/groovy']

render(contentType: "text/xhtml") {

// If there are some menu items to show.. show them
ul(class: "menu") {
for (i in feedMap.keySet()) {
li {
a(class: "go_forward", title: "${i}", href: "${createLink(controller: 'ciui', action: 'getFeed')}/?url=" + feedMap[i]) {
div("${i}")
}
}
}
}
}

}

Check out more on the render method at http://grails.org/Controller+Dynamic+Methods. For sake of a short blog entry I have just placed the whole controller file on-line (Ref: CIUI Controller ) It's all just a simple zero'th order pass at using CiUI. There are many extensions that one could do with this (more with templates, webflow, etc.). I didn't implement the search interface or anything fancy here as this is just a review to see what is involved (practically nothing) in using CIUI in Grails. I will likely go back and add something like that in and see if I can call back with parameters to my controller.

Note however that when generating the mark up in the controller it's likely a bit more "proper" to do something like the following MarkupBuilder example. This is actually an example from the IUI test I did and not used in this CIUI example, however the principle is the same.

    def search = { 
def mywriter = new StringWriter()
def xml = new MarkupBuilder(mywriter)

xml."form"(id: "searchForm", class: "dialog", action: "${createLink(controller: 'iui', action: 'doSearch')}") {
fieldset {
h1("Search the records")
a(class: "button leftButton", type: "cancel", "Cancel")
a(class: "button blueButton", type: "submit", "Search")
label("First Name")
input(id: "fname", type: "text", name: "fname")
label("Last Name")
input(id: "lname", type: "text", name: "lname")
}
}
render mywriter.toString()
}

Here we used the Groovy MarkupBuilder to generate our XML outside the render method and then just pass it along. This means we can push this logic down into a service or at least have a bit better logic to our controller code designs.

This youTube video shows what it looks like in action

Implementing these JS/CSS packages inside Grails is trivial. As the iPhone and Google Android phones become more and more a mechanism for people to obtain information from the web the ability for developers easy represent data in appropriate formats will be more important. Grails is a wonderfull platform for addressing that.

enjoy
Doug

No comments: