Mobile development with HTML5 »
Created at: 26.08.2011 01:54, source: Engine Yard Blog, tagged: Technology html5 jquery local storage mobile
HTML5: the standard, the buzzword and the legend
If you read blogs that are even slightly related to tech, you likely hear about HTML5 on a near-weekly basis. Although the new web standard does not do your laundry, it has features that enable the creation of powerful applications—using only HTML, CSS and JavaScript (a Rails back-end can bring additional firepower to the table). This post will go over some key concepts and features of HTML5, setting the stage for more advanced subjects.
Browser Compatibility
Perhaps the biggest pain in developing a web-based application is ensuring that your application is compatible with the various browsers in use today. Fortunately, this is less of a problem in the mobile world. Because people get new phones more often than new computers and because the smart phone space is relatively young, there are simply fewer old smart phones out in the wild. However, this is not a carte blanche; you should test your site with any devices you wish to support, not just simulators.
Viewport
When you visit a website not designed for mobile browsers, it first appears very zoomed out. This is done intentionally by the mobile browsers to make the website viewable. They set the default viewport width to between 800 and 980 pixels (depending on the browser). This allows the user to view the whole website and then zoom in as needed. However, if you are crafting a website specifically for mobile, it make sense to set the initial viewport for the mobile device. This is accomplished with the viewport meta tag.
<meta name="viewport" content = "width=device-width”>
This sizes the viewport to the device’s width, so the content does not initally appear zoomed out. You will likely want to disable zooming entirely, so the user doesn’t accidentally zoom out and distort the UI. Do this by setting user-scalable to no.
<meta name="viewport" content = "width=device-width , user-scalable=no">
Some sites currently hard-code the width of the viewport to 320. Why? Because this is the width of the iPhone. However, in general, it is a better practice to use “device-width” instead of 320.
Having your site correctly sized for mobile is nice but the next two features of HTML5, caching with the cache manifest and local storage, allow for fully functional offline sites.
HTML5 Caching
HTML5 caching allows users to view websites they have visited before without a connection to the web. Not only is this extremely useful for users who may not get coverage where they want to use the application, but it can also mitigate brief drops in a connection.
To setup HTML5 caching, you add a manifest file to the html tag of every page you want to cache.
<html manifest="/cache.manifest">
This file starts with “CACHE MANIFEST” and then enumerates the files that the application should cache.
CACHE MANIFEST
/mystyle.css
/scripts.js
/logo.jpg
Now those files will be available offline. Frankly, there is a long list of gotchas with the cache manifest. I review some key ones below but suggest reading Dive into HTML5 for all the details.
The first and foremost, your site will default to cached files over recently downloaded ones, meaning that even if the cache has changed since the browser has last visited the page, the browser displays the old pages until the page is refreshed (or told with JavaScript to update). This is further compounded by the fact that most web servers tell the browser cache the files they serve. When you are developing your site, be sure to tell your web server not to cache the cache manifest, so you always download the most recent copy.
The next big gotcha is how the browser manages the downloading process. If the browser detects that the manifest has changed, it re-downloads every single file. Not only does this make the process expensive, if a single file fails to download correctly, the browser abandons the update and loads the previous cache. When this happens the browser does not post any error by default. However, you can use JavaScript to detect the error thrown by the manifest.
$(function() {
$(window.applicationCache).bind("error", function() {
alert("Cache: update failed");
});
});
So now your site is cached and everything worked. You’re ready to launch? Not really. This caching technique works well with static content. However, if your application has content that is dynamically created and frequently changed (most web apps), it will not work well. This is because, unless the cache is changed, the old html page will be displayed, not the page with your new content. The simple answer is to change the cache manifest file whenever new content is added. However, this is generally not a good idea because it forces the browser to re-download every file every time any content is changed—very costly if your content is updated frequently. The solution is to use jQuery templates to build the page dynamically.
jQuery Templates
The best practice is to populate your content through JavaScript templates. In this way, the content is not part of the HTML page and thus is not cached with the cache manifest. For this, you need to download and add jQuery and the jQuery template plugin to your application.
There are three steps to using these templates:
- Define the template.
- Define the collection.
- Tell jQuery to populate to the page with the template.
Below is an example for a simple blog application.
1. Define the template:
<script id="post_template" type="text/html”>
<div>
<h2>${Name}</h2>
<p>${Body}</p>
</div>
</script>
2. Define the collection (of posts in JSON).
<script>
var posts = [
{ Name: "First!", Body: "This is pretty cool" },
{ Name: "Another post", Body: "This is pretty cool" },
{ Name: "Yet another blog post", Body: "This is pretty cool" }];
</script>
3. Tell jQueryto populate to the page with the template.
<script>
$( "#post_template" ).tmpl( posts ).appendTo( "#blog_posts" );
</script>
…
<body>
<div id="blog_posts"></div>
</body>
Although this content is loaded via JavaScript, it is not dynamic—it is just defined on the page. For dynamic content we will want to use JSON provided by the server. Let’s assume our blog application provides us with the JSON representation of our blog at this URL:
/posts.json
We will tell jQueryto make a request for the JSON and then use it to populate the page.
<script type="text/javascript">
$.getJSON('/posts.json', function(data) {
$( "#post_template" ).tmpl( data ).appendTo( "#blog_posts" );
});
</script>
We also need to change the template so that it can handle the JSON elements, substituting post.name for Name and post.body for Post:
<script id="post_template" type="text/html">
<div>
<h2>${post.name}</h2>
<p>${post.body}</p>
</div>
</script>
Now our blog is pulling content that is not cached in the cache manifest and using jQuery templates to populate the page. However, this works only if our mobile browser can connect to our server. This feels like two steps forward and three steps back, but trust me, we almost have a working mobile HTML5 app. We just need to include one last component of HTML5, Local Storage.
Local Storage
Christopher Haupt of Webvanta recently authored a guest blog post about Local Storage. See the Enhancing Client-side Storage with HTML5 post for details and general use.
On a high level, Local Storage is a client-side key-value store implemented by the browser. It stores strings of text locally and then recalls them later. Here, we use it to store JSON so we can populate the blog with posts even if there is no connection to the server.
Although we could write this by hand, there is a great plugin to manage the process for us. The jQuery Offline plugin uses content from Local Storage if the server is not available and will store fresh content in local storage when it’s received.
Download this plugin from jQuery-Offline
To use the plugin we change the getJSON call to retrieveJSON. We will also need to change our script slightly as there is one key difference between getJSON and retrieveJSON. The latter will execute twice, once to pull from the cache and again to get the new content from the server. This will cause the posts to appear twice if we simply append the new posts to the page.
<script type="text/javascript">
$.retrieveJSON('/posts.json', function(data) {
$( "#blog_posts" ).html($( "#post_template" ).tmpl( data ));
});
</script>
The blog application can now be viewed offline and is correctly sized for a mobile browser! You can download this example here offline-blog.
I hope you enjoyed this initial look at some of the technologies that are making mobile development easier. In the coming weeks I hope to be covering more advanced topics such as the popular MVC framework Backbone.js.
more »
Double Shot #653 »
Created at: 22.02.2010 12:36, source: A Fresh Cup, tagged: Double Shot currencies gems jquery rails rghost
No shortage of interesting and shiny distractions today.
- Bling Bling gem management - Why yes, there is already a replacement for Bundler.
- Announcing the Currencies Gem - Multi-currency and exchange rate support for the money gem.
- htmlBurger - Paid service to convert PSD to XHTML/CSS/light JS.
- Inline Styler - Convert CSS rules to inline style attributes for use in HTML email.
- rghost - Another alternative for PDF creation from Ruby. Anyone used this one?
- Running Rails 2.3.x on IronRuby - Rob Bazinet shows how to take the first steps.
- HTML Dog - Well-recommended set of HTML and CSS tutorials.
- What really happens when you navigate to a URL - It's complicated.
- RubyGems.org move complete - GemCutter has finished its bloodless coup over ruby gem hosting. Time to upgrade your rubygems to 1.3.6.
- jQuery Simple Multi-Select, jQuery Multiselect list plugin, and jQuery MultiSelect Plugin w/ ThemeRoller Support - Three options for adding click-to-toggle functionality to HTML select controls. I ended up using the first of these on a project, and it works well.
- Use a 503 for your Rails maintenance page - One more little bit of polish and standards.
- Rails 3 Upgrade Handbook - Now out and ready to download. Looks well-worth the $12.
more »
Double Shot #652 »
Created at: 19.02.2010 13:56, source: A Fresh Cup, tagged: Double Shot bundler css git hoptoad jquery nested_attributes query_trace rails
Remember kids, sleep is for the weak and sensible.
- Nathan Myhrvold's Intellectual Ventures Using Over 1,000 Shell Companies To Hide Patent Shakedown - The only reason I call the patent system "broken" is that I can't think of a more appropriate word that's fit for polite company.
- Git v1.7.0 Release Notes - Time to upgrade again. Note that there are some minor behavior changes.
- EZ-CSS - Yes, another CSS framework - but not yetanother grid.
- Hoptoad Notifier: Rack and automatic Metal support - Another functionality bump from the Hoptoad folks.
- A Visual Git Reference - With boxes and arrows.
- query_trace - I pushed out a new version of this gem yesterday.
- Rails 3 Beautiful Code - Presentation from Greg Pollack. Personally I am skeptical of "beauty" as a code metric in the working world.
- Bundler and I are breaking up - I've seen quite a bit of Bundler hate recently. Maybe it's just that it's not stable enough yet.
- Is The Singularity Here Yet? - Check the page source.
- Complex Nested Forms with Rails and Unobtrusive jQuery - This worked fine for me after I remembered that _delete had been renamed to _destroy in Rails 2.3.5.
more »
Double Shot #651 »
Created at: 18.02.2010 12:01, source: A Fresh Cup, tagged: Double Shot git icons jquery moonshine rails
Deadlines are raining on me like snowflakes lately.
- VersionControlTools - Somewhat rambling evaluation from Martin Fowler. It's interesting that he chooses git, Mercurial, and svn as the only three to recommend despite plenty of experience with the more "enterprisey" tools.
- Icons Etc. - Another big pile of royalty-free icons and images.
- Rails/jQuery UI sortables with single UPDATE query - Simple tutorial from Henrik Nyh. The SQL is MySQL-specific, but it's easy enough to write a workable method if you're on a different database.
- Smooth Devoperations: Deploying Rails 3 with Moonshine - The Rails Machine guys are committed to making Moonshine work well with Rails 3 while keeping Rails 2 support. Good news all around.
- Rails 3 Upgrade Handbook - Sign up for notification when this one comes out. Jeremy McAnally has already done some great Rails 3 blog entries, so this should be super-useful.
more »
Double Shot #649 »
Created at: 16.02.2010 12:57, source: A Fresh Cup, tagged: Double Shot heroku jquery paperclip rails
A slow day yesterday, at least on the web for me.
- Ketchup - jQuery plugin for forms validation.
- rails_metrics - Metrics engine for Rails 3 applications.
- paperclip-on-heroku - Fully-worked example of how to do it.
more »


