Building Progressive UIs with
            Grails
         Rob Fletcher
        Energized Work
Who am I?
Examples



  gr8-examples.cloudfoundry.com

github.com/robfletcher/gr8-examples
What is Progressive Enhancement?

Approach to building web UIs that emphasizes:
• Semantic markup
• Separation of markup, appearance, behaviour
• Rich appearance and
  behaviour applied selectively
• Adaptive design for cross-browser & cross-
  device support
• Distinct from 'graceful degradation’
Designing with Progressive
      Enhancement




 http://filamentgroup.com/dwpe/
Is this worth the effort?
• Cross-browser compatibility
• SEO compliance
• Mobile device support
• Support for assistive devices e.g.
  screenreaders
• Low bandwidth environments
• Maintainable structure
• Testability
Fundamentals



• JavaScript and CSS separated from markup
• Script reads and enhances markup
• Presentational markup injected by script
dowebsitesneedtolookexactlythesameineverybrowser.com
Don’t Break The Web!
Separation of markup & behaviour


Markup:
<a href="/foo” class="profile">Click me</a>
 <a href="/foo"
 onclick="return doSomething()">
     Click me
External script file:
</a>
   $('a.profile').click(doSomething);
Read and enhance markup


<a href="/foo" class="popup">Click me</a>

$('a.popup').click(function() {
    displayInPopup('/foo');
    displayInPopup($(this).attr('href'));
    return false;
});
Form enhancements and dialogs

EXAMPLE
The X-Ray Perspective


1. Map design components to basic HTML
2. Build markup with simple styles & no JS
3. Layer visual & interaction enhancements
   using JS & CSS
Data visualisation

EXAMPLE
How can Grails help?

request.xhr
•  different response for AJAX requests
•  render template / view
•  disable SiteMesh
•  forward rather than redirect
withFormat
•  respond with different data types
WebUtils.isIncludeRequest
•  tailor response for full page or content section
Varying output for AJAX

def show = {
    def model = // … whatever
    if (request.xhr) {
        render template: "basket", model: model
    } else {
        return model
    }
}
Disabling SiteMesh for AJAX


<!doctype html>
<html>
    <head>
        <g:if test="${!request.xhr}">
            <meta name="layout" content="main">
        </g:if>
Pagination -> infinite scroll

EXAMPLE
Test-driven progressive
           enhancement
Use browser capability detection to…
• activate script-driven behaviour
• activate 'polyfills' on less capable
   browsers
• selectively load JavaScript and CSS files
• apply advanced CSS rules to capable
   browsers
Modernizr
<html class="js flexbox canvas canvastext
    webgl no-touch geolocation postmessage
    no-websqldatabase indexeddb hashchange
.dialog {
if (Modernizr.geolocation) { rgba
    history draganddrop no-websockets
    background-color: #ccc;
    hsla multiplebgs backgroundsize
    // use native geolocation
    borderimage borderradius boxshadow
}
} else {
    textshadow opacity no-cssanimations
.rgba .dialog cssgradients no-cssreflections
    csscolumns {
    // activate JavaScript polyfill
    csstransforms no-csstransforms3d0, 0.3);
    background-color: rgba(0, 0,
} csstransitions fontface video audio
}   localstorage sessionstorage webworkers
    applicationcache svg inlinesvg smil
    svgclippaths">
FOUC prevention

EXAMPLE
Yepnope.js


yepnope({
    test : Modernizr.geolocation,
    yep : 'normal.js',
    nope : ['polyfill.js', 'wrapper.js’]
});
AJAX-enhanced pagination

EXAMPLE
Mobile-first progressive
           enhancement
body {
    background: url(low-res-image.png);
}
• Build for mobile devices first
@media screen and (min-width: 480px) {
•   Layer up to desktop using media queries
    body {
        background: url(hi-res-image.png);
•   }Prevent large images & supplementary
 
        max-width: 1140px;

     content sections loading
    #main, #sidebar { float: left; }
    #main { width: 65%; }
    #sidebar { width: 35%; }
}
What to avoid in Grails


AJAX tags:
•   g:formRemote
•   g:remoteField
•   g:remoteFunction
•   g:remoteLink
Resources plugin & templates

<r:use module="div-enhance-script"/>


•    Useful for highly modular apps
•    Script included at end of page
•    Can be used multiple times & script is
     only included once
Resources plugin & yepnope.js

<r:script disposition="head">
    yepnope({
        test : Modernizr.geolocation,
        yep  : "${r.resource(uri: 'normal.js')}",
        nope : [
            "${r.resource(uri: 'polyfill.js')}",
            "${r.resource(uri: 'wrapper.js')}"
        ]
    });
</r:script>
Thank you!


@rfletcherEW

adhockery.blogspot.com

www.energizedwork.com

GR8Conf 2011: Building Progressive UIs with Grails

  • 1.
    Building Progressive UIswith Grails Rob Fletcher Energized Work
  • 2.
  • 3.
  • 4.
    What is ProgressiveEnhancement? Approach to building web UIs that emphasizes: • Semantic markup • Separation of markup, appearance, behaviour • Rich appearance and behaviour applied selectively • Adaptive design for cross-browser & cross- device support • Distinct from 'graceful degradation’
  • 5.
    Designing with Progressive Enhancement http://filamentgroup.com/dwpe/
  • 6.
    Is this worththe effort? • Cross-browser compatibility • SEO compliance • Mobile device support • Support for assistive devices e.g. screenreaders • Low bandwidth environments • Maintainable structure • Testability
  • 7.
    Fundamentals • JavaScript andCSS separated from markup • Script reads and enhances markup • Presentational markup injected by script
  • 8.
  • 9.
  • 10.
    Separation of markup& behaviour Markup: <a href="/foo” class="profile">Click me</a> <a href="/foo" onclick="return doSomething()"> Click me External script file: </a> $('a.profile').click(doSomething);
  • 11.
    Read and enhancemarkup <a href="/foo" class="popup">Click me</a> $('a.popup').click(function() {     displayInPopup('/foo'); displayInPopup($(this).attr('href'));     return false; });
  • 12.
    Form enhancements anddialogs EXAMPLE
  • 13.
    The X-Ray Perspective 1.Map design components to basic HTML 2. Build markup with simple styles & no JS 3. Layer visual & interaction enhancements using JS & CSS
  • 14.
  • 15.
    How can Grailshelp? request.xhr • different response for AJAX requests • render template / view • disable SiteMesh • forward rather than redirect withFormat • respond with different data types WebUtils.isIncludeRequest • tailor response for full page or content section
  • 16.
    Varying output forAJAX def show = { def model = // … whatever if (request.xhr) { render template: "basket", model: model } else { return model } }
  • 17.
    Disabling SiteMesh forAJAX <!doctype html> <html> <head> <g:if test="${!request.xhr}"> <meta name="layout" content="main"> </g:if>
  • 18.
    Pagination -> infinitescroll EXAMPLE
  • 19.
    Test-driven progressive enhancement Use browser capability detection to… • activate script-driven behaviour • activate 'polyfills' on less capable browsers • selectively load JavaScript and CSS files • apply advanced CSS rules to capable browsers
  • 20.
    Modernizr <html class="js flexboxcanvas canvastext webgl no-touch geolocation postmessage no-websqldatabase indexeddb hashchange .dialog { if (Modernizr.geolocation) { rgba history draganddrop no-websockets background-color: #ccc; hsla multiplebgs backgroundsize // use native geolocation borderimage borderradius boxshadow } } else { textshadow opacity no-cssanimations .rgba .dialog cssgradients no-cssreflections csscolumns { // activate JavaScript polyfill csstransforms no-csstransforms3d0, 0.3); background-color: rgba(0, 0, } csstransitions fontface video audio } localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths">
  • 21.
  • 22.
    Yepnope.js yepnope({ test : Modernizr.geolocation, yep : 'normal.js', nope : ['polyfill.js', 'wrapper.js’] });
  • 23.
  • 24.
    Mobile-first progressive enhancement body {     background: url(low-res-image.png); } • Build for mobile devices first @media screen and (min-width: 480px) { •   Layer up to desktop using media queries     body {      background: url(hi-res-image.png); •   }Prevent large images & supplementary   max-width: 1140px; content sections loading #main, #sidebar { float: left; } #main { width: 65%; } #sidebar { width: 35%; } }
  • 25.
    What to avoidin Grails AJAX tags: • g:formRemote • g:remoteField • g:remoteFunction • g:remoteLink
  • 26.
    Resources plugin &templates <r:use module="div-enhance-script"/> • Useful for highly modular apps • Script included at end of page • Can be used multiple times & script is only included once
  • 27.
    Resources plugin &yepnope.js <r:script disposition="head">     yepnope({         test : Modernizr.geolocation,         yep  : "${r.resource(uri: 'normal.js')}",         nope : [             "${r.resource(uri: 'polyfill.js')}",             "${r.resource(uri: 'wrapper.js')}"         ]     }); </r:script>
  • 28.