Monday, April 28, 2008

Using IUI in Grails

So the first package I used in reviewing phone based UI's from Grails was CIUI. The other popular one that I found was IUI. This one seems a bit more advanced or at least feature rich than CIUI. I should point out it will be interesting to see how move advanced iPhone and HTML 5.0 features are going to play out in all this. That aside, implementing IUI was only marginally harder than CIUI. Again we download and place the CSS and JS files into the css and js directories located in [project]/web-app. In the case of IUI I did have to edit the CSS file to have it correctly locate the images folder (where I placed all the images that come with IUI). You could make a separate directory for these images as a sub-directory of images and alter the CSS file as you see fit in that case. Note, this package didn't render well for me outside of the webkit engine. I did a post on Webkit javascript performance on Ubuntu that also links to resources for compiling this package on Linux (Mac and Windows builds are available at the webkit site )

For the case of IUI I used the samples that came with the package as a guide to for all this. My GSP files looks like:

<%@ page contentType="text/html;charset=UTF-8" %> 
<html>
<meta name="layout" content="iuiLayout"/>

<head><title>IUI test</title>
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
</head>

<body onclick="console.log('Hello', event.target);">
<div class="toolbar">
<h1 id="pageTitle"></h1>
<a id="backButton" class="button" href="#"></a>
<a class="button" href="${createLink(controller: 'iui', action: 'search')}">Search</a>
</div>

<ul id="home" title="Home" selected="true">
<li><a href="${createLink(controller: 'iui', action: 'category1')}">Category 1</a></li>
<li><a href="${createLink(controller: 'iui', action: 'category2')}">Category 2</a></li>
<li><a href="${createLink(controller: 'iui', action: 'stats')}">Stats</a></li>
<li><a href="${createLink(controller: 'iui', action: 'settings')}">Settings</a></li>
<li><a href="${createLink(controller: 'iui', action: 'about')}">About</a></li>

</ul>
</body>
</html>


Here I just linked into my IuiController.groovy file to various methods to demonstrate some of the different features IUI has. The only interesting points in this are that it does demonstrate how to use the render method for cases like this where you need to include attributes and such. One interesting note was that the render method refused to provide a node named "form" in the XML return. I assume this is perhaps related to a keyword issue or some such. However, MarkupBuilder has no issues so where this does NOT work:

    // shows a form but doesn't work due to keyword issue with "form'? 
def searchDoesNotWork = {
render(contentType: "text/xhtml") {
"form"(id: "searchForm", class: "dialog", action: "foo") {
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")
}
}
}
}
this method will:
    def search = { 
def mywriter = new StringWriter()
def xml = new MarkupBuilder(mywriter)

// had to do this since the render method seemed to not want to return form (key word?)
// this is really how they should dbe done anyway... but I am too lazy to change all the
// examples

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()
}

In point of fact it's likely better form in most cases to use the MarkupBuilder as you can incorporate it into code logic easier. Though for simple cases there seems to be nothing wrong with render. As with the CIUI example I'll just post up the whole controller file for people to look at (IUI Controller ).

Note, I did modify the iui.js file line:

req.open(method || "GET", href, true);

to

req.open(method || "POST", href, true);

in order to get the search call to work to my controller. For some reason the URL encoding version would not send back the variables. I may contact the IUI people about this and see if I can resolve why this occured.

I was not able to wire up the toggle button to a controller method.. I got the error:

console message: http://localhost:8080/phoneUIGarden/iui#_Settings @35: Can't find variable: settingCallBack

Likely this is something simple (a guess) but I didn't bother to track it down since this was just a "for fun exploration" project.

It's easy to see how this could all be extended into a secured area of a site via Acegi or jsecurity and perhaps even attached to webflow . All fun stuff if I was paid to do that. This is by no means and in depth review, it's just my 4am feeding hacking to see what is involved in using IUI and CIUI. I thought I would share since I haven't seen much on using these in the Grails framework.

It's obvious that
A) it's simple
B) Groovy and Grails are a wonderful language/framework environment to do this in.
C) Someone with more time for this could flesh it all out rather quickly

enjoy...
Doug


1 comment:

aeischeid said...

playing with iUi the last couple of days. I ran across your article off of a google search. Have you been playing with this recently?