does my div look big in this?
DESCRIPTION
A small set of Grails UI refactors that make it easier to manage the view tier.TRANSCRIPT
Does my <div/> look big in this?
Putting some DRY in Grails UI with Glen Smith
Ancient Hacker Wisdom…
If the ax is dull and its edge unsharpened, more strength is needed, but skill will bring success.
Solomon, Ecclesiastes 10:10
Why this talk?
“The only thing I’m addicted to right now is
winning.”
Since we’re talking…
HTML
CSS
JavaScript
DRY up Resources,
Forms & Nav…
DRY up CSS and standardise
fonts/layout..
Sort out the mess of JS event
handling…
Best Case Outcomes • Learn Grails Resources
•Pickup some UI Plugin Love
•Try Less CSS & Twitter Bootstrap
•Swap stories & have fun!
Could be handy…
https://github.com/glenasmith/shameless
App Demo
See Food Diet Account
Meal
Picture
<html>
Refactoring Resources
Benefits • Much DRYer Grails views
• Dependency management of view tier stuff
• Bundle and Minify/Compress automagically
• Stops duplicate inclusions
• Defers JS for performance
• Caching forever (intelligent hashing)
• Makes plugins for UI play nice (standardised)
• Blah, Blah, Blah, it’s worth it, ok?
The 3 Essentials 1. DEFINE (/grails-app/conf/MyAppResources.groovy *)
2. TEMPLATE (<r:layoutResources/> in head and body)
3. REQUIRE (target page <r:require modules=“growl”/>)
1. Define Modules
modules = {
growl {
dependsOn 'jquery‘
// order is important
resource url:'/css/growl/growl.css'
resource url:'/js/growl/growl.js'
}
}
Also: Disposition Tricks
resource url:'/js/growl/growl.js', disposition: ‘head'
2. Change the Template
<r:layoutResources/>
3. Change the Page
<r:require modules=“a,b,c”/>
Look at the Chrome
X-Grails-Resources-Original-Src:
/bundle-bundle_jqplot_defer.js, /js/jqplot/excanvas.js, /js/jqplot/jquery.jqplot.js, /js/jqplot/jqplot.pieRenderer.js, /js/jqplot/jqplot.barRenderer.js, /js/jqplot/jqplot.categoryAxisRenderer.js, /js/jqplot/jqplot.pointLabels.js
Resources Demo
Lesser Known Goodness •<r:img>
•<r:external>
•<r:script disposition=“head”>
•Module overrides
Debugging Resources ?_debugResources=y
grails.resources.debug = true
Tools that play nice… •Cached-Resources
•Zipped-Resources
•And millions of 3rd party library
ones (blueprint, 960gs)
DRY Forms
Coming in Grails 2.x…
UNTIL THEN… bean-fields
A Typical Grails form…
<ul class="errors" role="alert">
<g:eachError bean="${authorInstance}" var="error">
<li <g:if test="${error in
org.springframework.validation.FieldError}">data-
field-id="${error.field}"</g:if>><g:message
error="${error}"/></li>
</g:eachError>
</ul>
Add tons of field code… <tr class="prop">
<td valign="top" class="name">
<label for="name"><g:message code="account.name.label" default="Name" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: accountInstance, field: 'name', 'errors')}">
<g:textField name="name" maxlength="200" value="${accountInstance?.name}" />
</td>
</tr>
With bean-fields…
<bean:form
beanName=“account”
properties=“name,email”/>
Or Probably…
<bean:form beanName=“account”>
<bean:field property=“name”/>
<bean:field property=“email”/>
<!-- etc -->
</bean:form>
Customisation…
Beans Demo
Strategy • Create a GSP that contains all your
<bean:xxxxTemplate> tags.
• In your layout do <g:render template=“/common/formconf"/>
• This will set up all your field styling for your pages.
TAMING THE DREADED…
navigation
Geez, you don’t want…
<div id="tabs">
<ul>
<li id="${request.forwardURI =~ /entries\/recent/ ? 'current' : 'notcurrent'}"><a href="<g:createLink controller='entries' action='recent'/>">Just In</a></li>
<li id="${request.forwardURI =~ /entries\/popular/ ? 'current' : 'notcurrent'}"><a href="<g:createLink controller='entries' action='popular'/>">Popular</a></li>
<li id="${request.forwardURI =~ /entries\/lists/ ? 'current' : 'notcurrent'}"><a href="<g:createLink controller='entries' action='lists'/>">The Lists</a></li>
<li id="${request.forwardURI =~ /account/ ? 'current' : 'notcurrent'}"><a href="<g:createLink controller='account' action='edit'/>">My Blogs</a></li>
<ul>
</div>
Get DRY with Controllers static navigation = [
group:'tabs',
order:99,
title:'Admin',
action:'index',
isVisible: { SpringSecurityUtils.ifAnyGranted("ROLE_ADMIN") }
]
And the markup… <html> <head><nav:resources/></head> <body>
<div id="menu">
<nav:render group="tabs"/>
</div>
<g:layoutBody/>
</body> </html>
Going Custom
<nav:eachItem group="tabs" var="item">
<li class="${item.active ? 'active' : ''}">
<g:link controller="${item.controller}" action="${item.action}">${item.title} </g:link>
</li>
</nav:eachItem>
Navigation Demo
.css
I mean, what could be
better than css?
CSS:
the death
of 1,000
cuts
How about Less css!?!?
Enter Less.css • Variables
• Mixins (with parameters!)
• Nested Rules
• Functions & Operators
• Compiles to real CSS (or use as .less files with JS)
How It Works myfile.less
• Write source.less using variables, mixins & nesting
Lessc or less.js
• Precompile (or use JavaScript compiler straight from the DOM)
myfile.css • Generate .css file for your browser
Compiling Less
grails install-plugin lesscss-resources
Variables @color: #4D926F;
#header {
color: @color;
}
h2 {
color: @color;
}
Nested Resources #header {
h1 {
font-size: 26px;
font-weight: bold;
}
p { font-size: 12px;
a { text-decoration: none;
&:hover { border-width: 1px }
}
}
}
Mixins .rounded-corners (@radius: 5px) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}
#header { .rounded-corners; }
#footer { .rounded-corners(10px); }
Less.css Demo
Doing this stuff by hand …is for bozos
It’s time to get
really, really,
ridiculously
good looking…
Meet Twitter Bootstrap • Grid system
• Fonts & Styling
• Forms
•Nav
• Alerts
Everything* you need to know
.span16
.span12
.span6 .span6
.span4
.span4 .offset4
.co
nta
iner
OR
.co
nta
iner
-flu
id
.ro
w
.ro
w
.ro
w
* For very small values of everything
You do design on paper?
Integration Options 1. Plugin (but you’re stuck with updates)
2. CSS (but it’s hard to tweak)
3. LESS files (like a complete boss!)
Getting Jiggy with UI You’re going to like this…
</wrap>
What we’ve learned…
HTML
CSS
JavaScript
DRY up Resources,
Forms & Nav…
DRY up CSS and standardise
fonts/layout..
Sort out the mess of JS event
handling…
Thanks for Coming!
@glen_a_smith
blogs.bytecode.com.au/glen
Image Credits • Hipster - http://www.flickr.com/photos/another_point_in_time/4743084835
• The Knives - http://www.flickr.com/photos/mcdnry/2347884938
• Giant Backbone - http://www.flickr.com/photos/25289142@N05/4559842516
• Tangled Wires - http://www.flickr.com/photos/randomurl/440190706