SlideShare a Scribd company logo
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

More Related Content

PDF
Grails and Neo4j
PDF
CouchDB: replicated data store for distributed proxy server
PDF
Pump up the JAM with Gatsby (2019)
PPTX
Introduction to Javascript
PDF
Performance (browser)
PDF
Gatsby (Code.Talks) 2019
PDF
U C2007 My S Q L Performance Cookbook
PDF
Grails and Neo4j
CouchDB: replicated data store for distributed proxy server
Pump up the JAM with Gatsby (2019)
Introduction to Javascript
Performance (browser)
Gatsby (Code.Talks) 2019
U C2007 My S Q L Performance Cookbook

What's hot (20)

PDF
Relevance trilogy may dream be with you! (dec17)
PPSX
Mongodb
PDF
Pre rendering media sites with nuxt.js & netlify
PDF
Mongo db transcript
PPTX
The Basics of MongoDB
PPTX
Introduction to mongo db
PDF
Drupal performance and scalability
PDF
N hidden gems in forge (as of may '17)
PDF
Hidden gems in Apache Jackrabbit and BloomReach Forge
PDF
Getting started with the Lupus Nuxt.js Drupal Stack
PPTX
Top 10 frameworks of node js
PPTX
Node js crash course session 5
PDF
Decoupling Drupal mit dem Lupus Nuxt.js Drupal Stack
PDF
Mojo Facets – so, you have data and browser?
PPTX
A faster web
PDF
MongoDB
PPT
PDF
Lean and mean MongoDB
PDF
Intro Couchdb
PPTX
MongoDB basics & Introduction
Relevance trilogy may dream be with you! (dec17)
Mongodb
Pre rendering media sites with nuxt.js & netlify
Mongo db transcript
The Basics of MongoDB
Introduction to mongo db
Drupal performance and scalability
N hidden gems in forge (as of may '17)
Hidden gems in Apache Jackrabbit and BloomReach Forge
Getting started with the Lupus Nuxt.js Drupal Stack
Top 10 frameworks of node js
Node js crash course session 5
Decoupling Drupal mit dem Lupus Nuxt.js Drupal Stack
Mojo Facets – so, you have data and browser?
A faster web
MongoDB
Lean and mean MongoDB
Intro Couchdb
MongoDB basics & Introduction
Ad

Viewers also liked (6)

PDF
GR8Conf 2009: Griffon by Jim Shingler
PDF
GR8Conf 2011: Grails Infinispanplugin, Tom Fuller
PDF
GR8Conf 2011: Canoo RIA Suite
PDF
GR8Conf 2011: Groovy 1.8 update
PDF
GR8Conf 2009: Industrial Strength Groovy by Paul King
KEY
Grails EE
GR8Conf 2009: Griffon by Jim Shingler
GR8Conf 2011: Grails Infinispanplugin, Tom Fuller
GR8Conf 2011: Canoo RIA Suite
GR8Conf 2011: Groovy 1.8 update
GR8Conf 2009: Industrial Strength Groovy by Paul King
Grails EE
Ad

Similar to GR8Conf 2011: Building Progressive UIs with Grails (20)

KEY
It's a Mod World - A Practical Guide to Rocking Modernizr
PDF
Familiar HTML5 - 事例とサンプルコードから学ぶ 身近で普通に使わているHTML5
PDF
Web Development for UX Designers
PDF
Front-End Frameworks: a quick overview
PDF
Client Side Optimization
PDF
The Heron Mapping Client - Overview, Functions, Concepts
PPTX
Html5 more than just html5 v final
PPTX
Introduction to Jquery
PDF
HTML5 & CSS3 refresher for mobile apps
PDF
[2015/2016] HTML5 and CSS3 Refresher
PDF
Integrating React.js Into a PHP Application
PPT
Responsive content
PPTX
HTML5: An Overview
PDF
Pinkoi Mobile Web
PDF
Html 5 mobile - nitty gritty
PDF
Developing High Performance Web Apps
PDF
Web app and more
PDF
Web Apps and more
PPTX
Developing JavaScript Widgets
PPTX
HTML5 - A Whirlwind tour
It's a Mod World - A Practical Guide to Rocking Modernizr
Familiar HTML5 - 事例とサンプルコードから学ぶ 身近で普通に使わているHTML5
Web Development for UX Designers
Front-End Frameworks: a quick overview
Client Side Optimization
The Heron Mapping Client - Overview, Functions, Concepts
Html5 more than just html5 v final
Introduction to Jquery
HTML5 & CSS3 refresher for mobile apps
[2015/2016] HTML5 and CSS3 Refresher
Integrating React.js Into a PHP Application
Responsive content
HTML5: An Overview
Pinkoi Mobile Web
Html 5 mobile - nitty gritty
Developing High Performance Web Apps
Web app and more
Web Apps and more
Developing JavaScript Widgets
HTML5 - A Whirlwind tour

More from GR8Conf (20)

PDF
DevOps Enabling Your Team
PDF
Creating and testing REST contracts with Accurest Gradle
PDF
Mum, I want to be a Groovy full-stack developer
PDF
Metaprogramming with Groovy
PDF
Scraping with Geb
PDF
How to create a conference android app with Groovy and Android
PDF
Ratpack On the Docks
PDF
Groovy Powered Clean Code
PDF
Cut your Grails application to pieces - build feature plugins
PDF
Performance tuning Grails applications
PDF
Ratpack and Grails 3
PDF
Grails & DevOps: continuous integration and delivery in the cloud
PDF
Functional testing your Grails app with GEB
PDF
Deploying, Scaling, and Running Grails on AWS and VPC
PDF
The Grails introduction workshop
PDF
Idiomatic spock
PDF
The Groovy Ecosystem Revisited
PDF
Groovy 3 and the new Groovy Meta Object Protocol in examples
PDF
Integration using Apache Camel and Groovy
PDF
CRaSH the shell for the Java Virtual Machine
DevOps Enabling Your Team
Creating and testing REST contracts with Accurest Gradle
Mum, I want to be a Groovy full-stack developer
Metaprogramming with Groovy
Scraping with Geb
How to create a conference android app with Groovy and Android
Ratpack On the Docks
Groovy Powered Clean Code
Cut your Grails application to pieces - build feature plugins
Performance tuning Grails applications
Ratpack and Grails 3
Grails & DevOps: continuous integration and delivery in the cloud
Functional testing your Grails app with GEB
Deploying, Scaling, and Running Grails on AWS and VPC
The Grails introduction workshop
Idiomatic spock
The Groovy Ecosystem Revisited
Groovy 3 and the new Groovy Meta Object Protocol in examples
Integration using Apache Camel and Groovy
CRaSH the shell for the Java Virtual Machine

Recently uploaded (20)

PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Encapsulation theory and applications.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
KodekX | Application Modernization Development
PDF
Empathic Computing: Creating Shared Understanding
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Electronic commerce courselecture one. Pdf
PPT
Teaching material agriculture food technology
PPTX
Cloud computing and distributed systems.
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
cuic standard and advanced reporting.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Unlocking AI with Model Context Protocol (MCP)
Network Security Unit 5.pdf for BCA BBA.
Encapsulation theory and applications.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Reach Out and Touch Someone: Haptics and Empathic Computing
Chapter 3 Spatial Domain Image Processing.pdf
Review of recent advances in non-invasive hemoglobin estimation
KodekX | Application Modernization Development
Empathic Computing: Creating Shared Understanding
Building Integrated photovoltaic BIPV_UPV.pdf
Electronic commerce courselecture one. Pdf
Teaching material agriculture food technology
Cloud computing and distributed systems.
Understanding_Digital_Forensics_Presentation.pptx
cuic standard and advanced reporting.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
The Rise and Fall of 3GPP – Time for a Sabbatical?
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
MIND Revenue Release Quarter 2 2025 Press Release
Unlocking AI with Model Context Protocol (MCP)

GR8Conf 2011: Building Progressive UIs with Grails

  • 1. Building Progressive UIs with Grails Rob Fletcher Energized Work
  • 4. 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’
  • 5. Designing with Progressive Enhancement http://filamentgroup.com/dwpe/
  • 6. 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
  • 7. Fundamentals • JavaScript and CSS separated from markup • Script reads and enhances markup • Presentational markup injected by script
  • 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 enhance markup <a href="/foo" class="popup">Click me</a> $('a.popup').click(function() {     displayInPopup('/foo'); displayInPopup($(this).attr('href'));     return false; });
  • 12. Form enhancements and dialogs 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
  • 15. 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
  • 16. Varying output for AJAX def show = { def model = // … whatever if (request.xhr) { render template: "basket", model: model } else { return model } }
  • 17. Disabling SiteMesh for AJAX <!doctype html> <html> <head> <g:if test="${!request.xhr}"> <meta name="layout" content="main"> </g:if>
  • 18. Pagination -> infinite scroll 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 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">
  • 22. Yepnope.js yepnope({ test : Modernizr.geolocation, yep : 'normal.js', nope : ['polyfill.js', 'wrapper.js’] });
  • 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 avoid in 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>