<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Christian Cantrell</title>
	<atom:link href="http://blogs.adobe.com/cantrell/feed" rel="self" type="application/rss+xml" />
	<link>http://blogs.adobe.com/cantrell</link>
	<description>Adobe AIR Application Developer, Product Manager, and Evangelist</description>
	<lastBuildDate>Thu, 09 Feb 2012 19:08:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>CSS Regions Support in Google Chrome for Android</title>
		<link>http://blogs.adobe.com/cantrell/archives/2012/02/css-regions-support-in-google-chrome-for-android.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2012/02/css-regions-support-in-google-chrome-for-android.html#comments</comments>
		<pubDate>Thu, 09 Feb 2012 19:04:05 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1123</guid>
		<description><![CDATA[I&#8217;ve been working on some CSS Regions prototypes recently (if you&#8217;re new to CSS Regions, check out this post), so when the Chrome for Android beta came out the other day, I decided to see how some of my samples looked on mobile. It turns out, they work perfectly: The CSS Regions capabilities currently in [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on some CSS Regions prototypes recently (if you&#8217;re new to CSS Regions, <a href="http://blogs.adobe.com/cantrell/archives/2011/05/screencast-of-css-regions.html">check out this post</a>), so when the Chrome for Android beta came out the other day, I decided to see how some of my samples looked on mobile. It turns out, they work perfectly:</p>
<div align="center">
<img src="http://blogs.adobe.com/cantrell/files/2012/02/android_chrome_hlp_1.png" width="300" height="533" style="-moz-box-shadow: 0 0 5px #888; -webkit-box-shadow: 0 0 5px #888; box-shadow: 0 0 5px #888; margin-right: 10px;"/><img src="http://blogs.adobe.com/cantrell/files/2012/02/android_chrome_hlp_2.png" width="300" height="533" style="-moz-box-shadow: 0 0 5px #888; -webkit-box-shadow: 0 0 5px #888; box-shadow: 0 0 5px #888; margin-left: 10px;"/>
</div>
<p>The CSS Regions capabilities currently in Chrome are pretty rudimentary, but I&#8217;m also working with some nightly WebKit builds which definitely take the feature to the next level (they include CSS Object Model support which enables the scripting of CSS Regions &mdash; that&#8217;s when they get really interesting). I&#8217;ll have plenty more samples and prototypes in the near future.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2012/02/css-regions-support-in-google-chrome-for-android.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting Text Selection Colors in JavaScript</title>
		<link>http://blogs.adobe.com/cantrell/archives/2012/02/setting-text-selection-colors-in-javascript.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2012/02/setting-text-selection-colors-in-javascript.html#comments</comments>
		<pubDate>Fri, 03 Feb 2012 16:18:33 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1117</guid>
		<description><![CDATA[If you&#8217;re building any kind of a text editor in JavaScript, you might want to be able to dynamically set or change the text selection color. I discovered it wasn&#8217;t as easy to do as I expected it to be, so I thought I&#8217;d share the code. I created this extreme (and admittedly, somewhat obnoxious) [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re building any kind of a text editor in JavaScript, you might want to be able to dynamically set or change the text selection color. I discovered it wasn&#8217;t as easy to do as I expected it to be, so I thought I&#8217;d share the code. I created <a href="http://christiancantrell.com/adobe/selection_test/">this extreme (and admittedly, somewhat obnoxious) example</a> showing the selection color changing as the mouse moves, but the core of the code is something like this:</p>
<p><code>
<pre>var ss = document.styleSheets[0];
ss.insertRule('#content::selection {color: #'+
              newForegroundColor+'; background: #'+
              newBackgroundColor+';}', 0);</pre>
<p></code></p>
<p>Note that I only tested this code in Chrome and Safari (I&#8217;m only targeting WebKit browsers for now), however it can work with Firefox with the correct &quot;moz&quot; prefixed style name. I haven&#8217;t yet tested or investigated IE.</p>
<p>If you know another way of changing text selection properties in JavaScript, let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2012/02/setting-text-selection-colors-in-javascript.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to Create a Custom File Input (For Use With the HTML5 File APIs)</title>
		<link>http://blogs.adobe.com/cantrell/archives/2012/01/how-to-create-a-custom-file-input-for-use-with-the-html5-file-apis.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2012/01/how-to-create-a-custom-file-input-for-use-with-the-html5-file-apis.html#comments</comments>
		<pubDate>Tue, 31 Jan 2012 19:42:08 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1114</guid>
		<description><![CDATA[I&#8217;m working on an HTML/JS application that lets users work with local files directly in the browser, and I&#8217;m using some new HTML5 APIs to access local files. It works great (in Chrome and Firefox, anyway &#8212; see note below), however my UI calls for a custom file input rather than the default (and usually [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on an HTML/JS application that lets users work with local files directly in the browser, and I&#8217;m using some new <a href="http://dev.w3.org/2006/webapi/FileAPI/">HTML5 APIs to access local files</a>. It works great (in Chrome and Firefox, anyway &#8212; see note below), however my UI calls for a custom file input rather than the default (and usually pretty ugly) button-and-path input. Fortunately, customization is easy in this case. The trick is to create your own UI treatment (in my case, just a link), then use the <code>click()</code> function on a hidden file input to bring up the file dialog.</p>
<p>In Firefox, you can use the <code>display:none</code> style as noted in this <a href="https://developer.mozilla.org/en/Using_files_from_web_applications">Mozilla Developer Network documentation</a>, however this won&#8217;t work in Chrome or Safari (although <code>FileReader</code> is currently not supported in Safari, you might as well think ahead for when it is). A better way of doing it, therefore, is to use <code>visibility:hidden</code>.</p>
<p>The only problem is that when something is hidden using its <code>visibility</code> property, it&#8217;s still actually in the DOM, and space is therefore allocated for it even though you can&#8217;t see it. If you want to get your file input completely out of the way, therefore, you can use something like this:</p>
<p><code></p>
<pre>&lt;input type=&quot;file&quot; id=&quot;fileInput&quot; onchange=&quot;handleFiles(this.files)&quot; style=&quot;visibility:hidden;position:absolute;top:-50;left:-50&quot;/&gt;</pre>
<p></code></p>
<p>Your file input will still be in the DOM (even though it&#8217;s hidden and off-screen), however it won&#8217;t take up any visual space.</p>
<p>Here&#8217;s the full HTML code:</p>
<p><code></p>
<pre>&lt;a href=&quot;javascript:onLoad();&quot;&gt;Load a File!&lt;/a&gt;
&lt;input type=&quot;file&quot; id=&quot;fileInput&quot; onchange=&quot;handleFiles(this.files)&quot; style=&quot;visibility:hidden;position:absolute;top:-50;left:-50&quot;/&gt;</pre>
<p></code></p>
<p>And here&#8217;s the JavaScript code:</p>
<p><code></p>
<pre>function onLoad() {
    id('fileInput').click();
}

function handleFiles(files) {
    var file = files[0];
    var reader = new FileReader();
    reader.onload = onFileReadComplete;
    reader.readAsText(file);
}

function onFileReadComplete(event) {
  // Do something fun with your file contents.
}</pre>
<p></code></p>
<p>Note that this code is only going to work in current versions of Chrome and Firefox, but is expected to work in future versions of IE (10) and Safari (6).</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2012/01/how-to-create-a-custom-file-input-for-use-with-the-html5-file-apis.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to Download Data as a File From JavaScript</title>
		<link>http://blogs.adobe.com/cantrell/archives/2012/01/how-to-download-data-as-a-file-from-javascript.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2012/01/how-to-download-data-as-a-file-from-javascript.html#comments</comments>
		<pubDate>Fri, 27 Jan 2012 17:36:04 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1108</guid>
		<description><![CDATA[I&#8217;m currently working on an HTML/JavaScript application that allows you to author content entirely on the client. I want to let users download that content and save it locally, but without bouncing it off a server. After some trial and error, I have it working fairly well using a data URI. Rather than explain it, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently working on an HTML/JavaScript application that allows you to author content entirely on the client. I want to let users download that content and save it locally, but without bouncing it off a server. After some trial and error, I have it working fairly well using a data URI. Rather than explain it, it&#8217;s probably easiest just to show the code:</p>
<p>HTML:</p>
<p><code>
<pre>&lt;a href=&quot;javascript:onDownload();&quot;&gt;Download&lt;/a&gt;</pre>
<p></code></p>
<p>JavaScript code:</p>
<p><code>
<pre>function onDownload() {
    document.location = 'data:Application/octet-stream,' +
                         encodeURIComponent(dataToDownload);
}</pre>
<p></code></p>
<p>The only limitation is that I can&#8217;t figure out a way to give the downloaded file a name (and have concluded that it&#8217;s not currently possible, though I&#8217;m happy to be proven wrong). I&#8217;ve only tested the code in Safari and Chrome, and in both cases, the file name defaults to &quot;download&quot; (with no extension). All the data is in the file, but it&#8217;s not a very intuitive experience for the end user.</p>
<p>I&#8217;ll be releasing the application shortly which should demonstrate why downloading data directly from the client can be useful. In the meantime, I&#8217;m curious if this is something any of you might use, and if so, if you think the file name issue should be fixed.</p>
<p>Let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2012/01/how-to-download-data-as-a-file-from-javascript.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>A Summary of the WebKit Developer Tools</title>
		<link>http://blogs.adobe.com/cantrell/archives/2012/01/a-summary-of-the-webkit-developer-tools.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2012/01/a-summary-of-the-webkit-developer-tools.html#comments</comments>
		<pubDate>Tue, 17 Jan 2012 20:00:25 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1099</guid>
		<description><![CDATA[I use the WebKit developer tools extensively in both Chrome and Safari, but it occurred to me the other day that I was probably only using a fraction of their capabilities. After researching them more fully, I was pleasantly surprised by how comprehensive they are, so I decided to make a quick list of all [...]]]></description>
			<content:encoded><![CDATA[<p>I use the WebKit developer tools extensively in both Chrome and Safari, but it occurred to me the other day that I was probably only using a fraction of their capabilities. After researching them more fully, I was pleasantly surprised by how comprehensive they are, so I decided to make a quick list of all the major developer-oriented features of WebKit that I know of. Even if you use the Chrome/WebKit dev tools regularly, there&#8217;s a good chance you&#8217;ll find one or two things below you haven&#8217;t been leveraging.</p>
<p><span id="more-1099"></span></p>
<h2>WebKit Developer Tools</h2>
<p>Each section below describes a section of the WebKit developer console.</p>
<p><strong>Elements</strong></p>
<ul>
<li>Traverse, inspect, and edit the DOM.</li>
<li>Inspect and edit CSS.</li>
<li>View a diagram of the CSS box model and edit its metrics.</li>
<li>View and edit a DOM element&#8217;s properties.</li>
<li>Manage DOM breakpoints. Breakpoints can break on:
<ul>
<li>Subtree modification.</li>
<li>Attribute modification.</li>
<li>Node removal.</li>
</ul>
</li>
<li>View an element&#8217;s event listeners.</li>
<li>Right-click on any element in a web page, and select &#8220;Inspect Element&#8221; from the context menu to bring it up in the developer console.</li>
<li>Note that edits are for testing purposes only and are not saved (though I believe there are extensions which make tracking your changes easier).</li>
</ul>
<p><strong>Resources</strong></p>
<ul>
<li>Allows you to inspect (and in some cases, edit) various elements of a web application:
<ul>
<li>Frames (all externally loaded files).</li>
<li>Databases (SQLite).</li>
<li>Local storage.</li>
<li>Session storage.</li>
<li>Cookies.</li>
<li>Application cache.</li>
</ul>
</li>
</ul>
<p><strong>Network</strong></p>
<ul>
<li>Detailed inspection of network metrics broken down by resource.</li>
<li>Metrics include:
<ul>
<li>Name of the resource.</li>
<li>Request method (GET, POST, DELETE, etc.).</li>
<li>Status (200, 404, etc.).</li>
<li>Type (content type, i.e. text/javascript, text/css, etc.).</li>
<li>Size.</li>
<li>Time in milliseconds.</li>
<li>Timeline waterfall (start and end time of all resource requests relative to each other, including latency).</li>
<li>Exactly when the <code>DOMContentLoaded</code> and <code>Load</code> events were fired.</li>
</ul>
</li>
<li>Resource types can be filtered (for instance, if you just want to watch images).</li>
<li>You can click on a resource to see a detailed view which includes:
<ul>
<li>HTTP headers (both request and response).</li>
<li>A preview of the resource (HTML source, image, etc.).</li>
<li>Cookies.</li>
<li>Detailed timing information including:
<ul>
<li>DNS lookup.</li>
<li>Connecting.</li>
<li>Sending.</li>
<li>Waiting.</li>
<li>Receiving.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>Scripts</strong></p>
<ul>
<li>View all the scripts being used by the current page.</li>
<li>Manage breakpoints.</li>
<li>Flow control (pause, resume, step over, step into, and step out).</li>
<li>View the call stack.</li>
<li>Inspect variables by scope.</li>
<li>Manage context-specific breakpoints:
<ul>
<li>DOM (see above).</li>
<li>XMLHttpRequest.</li>
<li>Event listener.</li>
<li>Workers.</li>
</ul>
</li>
</ul>
<p><strong>Timeline</strong></p>
<ul>
<li>Detailed breakdown of the timeline related to loading your site including:
<ul>
<li>Loading.</li>
<li>JavaScript parsing.</li>
<li>JavaScript execution.</li>
<li>Calculating styles and layout.</li>
<li>Rendering.</li>
<li>Events.</li>
</ul>
</li>
<li>Timeline of memory consumption.</li>
</ul>
<p><strong>Profiler</strong></p>
<ul>
<li>CPU: shows where execution time is spent.</li>
<li>Heap: shows memory distribution.</li>
</ul>
<p><strong>Audits</strong></p>
<ul>
<li>Various tests and diagnostics that can be run on a page or application.</li>
<li>Included audits:
<ul>
<li>Network Utilization
<ul>
<li>Recommends things like using gzip, leveraging browser caching, using proxy caching, and reducing cookie size.</li>
</ul>
</li>
<li>Web Page Performance
<ul>
<li>Recommends things like removing unused CSS rules, changing the order of scripts and styles, etc.</li>
</ul>
</li>
</ul>
</li>
<li>Extensibility APIs for creating your own audits.</li>
</ul>
<p><strong>Console</strong></p>
<ul>
<li>View parse errors and JavaScript execution errors.</li>
<li>Write to the console from within your code using the <code>console.log()</code> function (the new <code>alert()</code>).</li>
<li>Supports multiple strings and objects as arguments. Objects can be expanded and inspected.</li>
<li>Execute JavaScript directly from the console.</li>
<li>Enable pausing, or breaking, whenever a runtime error is encountered (as opposed to just logging it).</li>
</ul>
<h2>Task Manager (Chrome only)</h2>
<p>Similar to the Windows Task Manager or the Activity Monitor on OS X, the Task Manager shows metrics by tab, process, and extension. Fields include:</p>
<ul>
<li>Process ID.</li>
<li>Memory (shared and private).</li>
<li>JavaScript memory.</li>
<li>CPU.</li>
<li>Network throughput.</li>
<li>Frames per second.</li>
<li>Image cache size.</li>
<li>Script cache size.</li>
<li>CSS cache size.</li>
<li>SQLite memory.</li>
</ul>
<h2>Debugging APIs</h2>
<p>Below are all the APIs that I know of that can be used to programmatically debug and/or audit a web application:</p>
<ul>
<li><code>console.log</code>
<ul>
<li>Logs strings and objects to the console.</li>
</ul>
</li>
<li><code>performance.timing</code>
<ul>
<li>Networking metrics that reflect page load performance.</li>
</ul>
</li>
<li><code>performance.memory</code>
<ul>
<li>Fields:
<ul>
<li><code>jsHeapSizeLimit</code></li>
<li><code>totalJSHeapSize</code></li>
<li><code>usedJSHeapSize</code></li>
</ul>
</li>
<li>Requires the <code>&#45;enable-memory-info</code> command line flag.</li>
</ul>
</li>
<li><code>window.onerror</code> event handler
<ul>
<li>Allows global error registration.</li>
<li>Typical usage is to send the data to your server where it can be aggregated and reports can be generated.</li>
</ul>
</li>
<li><code>console.profile('name')</code>, <code>console.endProfile('name')</code>, and <code>console.profiles</code> (returns an array of <code>Profile</code> objects):
<ul>
<li>Programmatic ways of starting, stopping, and analyzing profile information.</li>
<li>Data can be captured and sent back to the server for aggregation.</li>
</ul>
</li>
<li><code>console.markTimeline()</code>
<ul>
<li>Programmatically add &#8220;marks&#8221; to your timeline view.</li>
</ul>
</li>
<li>Extensibility APIs for creating your own audits.</li>
</ul>
<h2>Remote Debugging</h2>
<p>Remote debugging allows you to debug a remote browser instance. This is nice on the desktop, but will become critical on mobile devices.</p>
<ul>
<li>Start Chrome with the <code>--remote-debugging-port</code> command line flag.</li>
<li>Starts a mini web server.</li>
<li>External browsers can connect to that port and profile tabs remotely.</li>
<li>Implemented at the WebKit level, so all WebKit browsers will get it.</li>
</ul>
<h2>Additional Resources</h2>
<p>Believe it or not, there&#8217;s actually more. If you haven&#8217;t gotten enough, check out these excellent resources:</p>
<ul>
<li><a href="http://paulirish.com/2011/a-re-introduction-to-the-chrome-developer-tools/">A Re-introduction to the Chrome Developer Tools</a> (by Paul Irish).</li>
<li><a href="http://www.youtube.com/watch?v=MllBwuHbWMY">Chrome Developer Tools for Speed</a> (by Paul Irish).</li>
<li><a href="http://www.youtube.com/watch?v=nOEw9iiopwI">Google Chrome Developer Tools: 12 Tricks to Develop Quicker</a> (by Paul Irish).</li>
<li><a href="http://www.andismith.com/blog/2011/11/25-dev-tool-secrets/">25 Secrets of the Browser Developer Tools</a> (Andi Smith).</li>
<li><a href="http://code.google.com/chrome/devtools/">Google Chrome Developer Tools</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2012/01/a-summary-of-the-webkit-developer-tools.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a Loading Spinner Animation in CSS and JavaScript</title>
		<link>http://blogs.adobe.com/cantrell/archives/2011/12/creating-a-loading-spinner-animation-in-css-and-javascript.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2011/12/creating-a-loading-spinner-animation-in-css-and-javascript.html#comments</comments>
		<pubDate>Wed, 14 Dec 2011 21:48:12 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1092</guid>
		<description><![CDATA[Update (12/20/2011): Now works in Firefox as well as Chrome and Safari. Since I&#8217;m not a very good designer, I usually try to do as much styling, design, and graphics in code as I can. For instance, when I wrote this mobile compass application in HTML, I did all the graphics programmatically using Canvas and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blogs.adobe.com/cantrell/files/2011/12/spinner_example.jpg" width="150" height="150" style="float:right; padding: 10px"/><strong>Update (12/20/2011):</strong> Now works in Firefox as well as Chrome and Safari.</p>
<p>Since I&#8217;m not a very good designer, I usually try to do as much styling, design, and graphics in code as I can. For instance, when I wrote <a href="http://blogs.adobe.com/cantrell/archives/2011/11/porting-an-air-application-to-html.html">this mobile compass application</a> in HTML, I did all the graphics programmatically using Canvas and CSS.</p>
<p>I&#8217;m now working on a project that requires one of those loading spinner animations that Apple seems to have made famous, so naturally, I started looking into ways to create one purely in code and/or CSS (no external assets). Fortunately, I found <a href="http://37signals.com/svn/posts/2577-loading-spinner-animation-using-css-and-webkit">a great post</a> on the Signal vs. Noise blog demonstrating exactly what I wanted to do. However, I decided to take it one step further, and write some JavaScript to generate both the required CSS and the HTML. The advantage of generating everything dynamically is that you can configure things like the size, color, and the number of bars in the animation at runtime.</p>
<p><a href="http://christiancantrell.com/adobe/spinner/">Here&#8217;s an example</a> of some randomly generated loading spinner animations which are 100% CSS and HTML generated by JavaScript (Chrome and Safari only for now). If you&#8217;re interested in the code, <a href="http://37signals.com/svn/posts/2577-loading-spinner-animation-using-css-and-webkit">here&#8217;s the original CSS from Signal vs. Noise</a>, and below is my port to JavaScript (view the source of <a href="http://christiancantrell.com/adobe/spinner/">the demo</a> to see how to use it). <strike>It only works in WebKit-based browsers for the time being, but I&#8217;ll update it as browser capabilities get better.</strike> It works in WebKit-based browser, and in Firefox.</p>
<p><a href="http://christiancantrell.com/adobe/spinner/">Check out the example.</a></p>
<p><code>
<pre>var Spinner = {
  SPINNER_ID: '_spinner',
  prefix: (navigator.userAgent.indexOf('WebKit') != -1) ? 'webkit' : 'moz',
  getSpinner: function(size, numberOfBars, color) {
    if (document.getElementById(this.SPINNER_ID) == null) {
      var style = document.createElement('style');
      style.setAttribute('id', this.SPINNER_ID);
      style.innerHTML = '@-'+this.prefix+'-keyframes fade {from {opacity: 1;} to {opacity: 0.25;}}';
      document.getElementsByTagName('head')[0].appendChild(style);
    }
    var spinner = document.createElement('div');
    spinner.style.width = size;
    spinner.style.height = size;
    spinner.style.position = 'relative';
    var rotation = 0;
    var rotateBy = 360 / numberOfBars;
    var animationDelay = 0;
    var frameRate = 1 / numberOfBars;
    for (var i = 0; i &lt; numberOfBars; ++i) {
      var bar = document.createElement('div');
      spinner.appendChild(bar);
      bar.style.width = '12%';
      bar.style.height = '26%';
      bar.style.background = color;
      bar.style.position = 'absolute';
      bar.style.left = '44.5%';
      bar.style.top = '37%';
      bar.style.opacity = '1';
      bar.style.setProperty('-'+this.prefix+'-border-radius', '50px', null);
      bar.style.setProperty('-'+this.prefix+'-box-shadow', '0 0 3px rgba(0,0,0,0.2)', null);
      bar.style.setProperty('-'+this.prefix+'-animation', 'fade 1s linear infinite', null);
      bar.style.setProperty('-'+this.prefix+'-transform', 'rotate('+rotation+'deg) translate(0, -142%)', null);
      bar.style.setProperty('-'+this.prefix+'-animation-delay', animationDelay + 's', null);
      rotation += rotateBy;
      animationDelay -= frameRate;
    }
    return spinner;
  }
}</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2011/12/creating-a-loading-spinner-animation-in-css-and-javascript.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Loading Data Across Domains with JavaScript</title>
		<link>http://blogs.adobe.com/cantrell/archives/2011/12/making-xhr-requests-across-domains.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2011/12/making-xhr-requests-across-domains.html#comments</comments>
		<pubDate>Wed, 07 Dec 2011 19:20:10 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1087</guid>
		<description><![CDATA[I&#8217;m working on a project now that makes heavy use of XHR (XMLHttpRequest) to load data from a server. I&#8217;m writing the HTML/JS portion of the application on my local machine, but my server development environment is on a remote server under a different domain. Typically cross-domain XHR request aren&#8217;t allowed due to browser security [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on a project now that makes heavy use of XHR (XMLHttpRequest) to load data from a server. I&#8217;m writing the HTML/JS portion of the application on my local machine, but my server development environment is on a remote server under a different domain. Typically cross-domain XHR request aren&#8217;t allowed due to browser security restrictions, however there are two easy work-arounds:</p>
<ol>
<li>JSONP</li>
<li>Cross-Origin Resource Sharing</li>
</ol>
<p><strong>JSONP</strong></p>
<p><a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> gets around the same origin policy by loading JavaScript from another domain into a dynamically generated <code>&lt;script&gt;</code> tag (script tags are not subject to the same origin policy which is what enables things like ads to be served from different domains). In your request (formed as the <code>src</code> attribute of the script tag), you typically specify a callback function that you have already defined in your application. The JavaScript that gets loaded into the dynamically generated script tag will call the specified function, passing in the requested JSON data.</p>
<p>(Note that JSONP requests are probably best handled by robust frameworks like the <a href="http://api.jquery.com/jQuery.getJSON/"><code>jQuery.getJSON()</code> function</a>.)</p>
<p>I&#8217;ve used JSONP in the past for things like <a href="http://christiancantrell.com/adobe/djreader/">this prototype client-side news reader</a>, but the project I&#8217;m working on now uses XML as well as JSON, so I decided to use a different approach.</p>
<p><strong>Cross-Origin Resource Sharing</strong></p>
<p>Cross-origin resource sharing is similar to <a href="http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html">cross-domain policy files</a> in the Flash word, but they are done through HTTP headers. The specification defines several different headers, however the only one I&#8217;ve needed so far is the response header <code>Access-Control-Allow-Origin</code>. Allowing my server to share resources with my local machine was as easy as adding the following line of PHP code before writing to the output buffer:</p>
<p><code>header('Access-Control-Allow-Origin: http://seeker.home');</code></p>
<p>(Seeker is the name of my development machine, named after the <a href="http://en.wikipedia.org/wiki/Seeker_(novel)">excellent Jack McDevitt novel</a>.)</p>
<p>Of course, once I move the client-side portion of my application (the HTML, JS, and CSS files) to my server, I can delete or comment this line out since the application will be served from the same domain from which it needs to request data. In the meantime, however, it&#8217;s made local development much easier.</p>
<p>Cross-origin resource sharing is part of the <a href="http://www.w3.org/TR/XMLHttpRequest2/">XMLHttpRequest Level 2 specification</a>, and is supported in all modern browsers.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2011/12/making-xhr-requests-across-domains.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding prependChild to Element</title>
		<link>http://blogs.adobe.com/cantrell/archives/2011/11/adding-prependchild-to-element.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2011/11/adding-prependchild-to-element.html#comments</comments>
		<pubDate>Wed, 30 Nov 2011 16:45:39 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1081</guid>
		<description><![CDATA[If you&#8217;ve ever done much DOM scripting, you have almost certainly used the appendChild function on Element. For instance, you might have done something like this: var hello = document.createElement('p'); hello.innerText = 'Hello, world!'; document.getElementById('myDiv').appendChild(hello); Nice and easy, but what if you want to prepend the child rather append? You could do this: var hello [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever done much DOM scripting, you have almost certainly used the <code>appendChild</code> function on <code>Element</code>. For instance, you might have done something like this:</p>
<p><code>
<pre>var hello = document.createElement('p');
hello.innerText = 'Hello, world!';
document.getElementById('myDiv').appendChild(hello);</pre>
<p></code></p>
<p>Nice and easy, but what if you want to <em>prepend</em> the child rather <em>append</em>? You could do this:</p>
<p><code>
<pre>var hello = document.createElement('p');
hello.innerText = 'Hello, world!';
var myDiv = document.getElementById('myDiv');
myDiv.insertBefore(hello, myDiv.firstChild);</pre>
<p></code></p>
<p>Or, you could just add a <code>prependChild</code> function to <code>Element</code>, like this:</p>
<p><code>
<pre>Element.prototype.prependChild = function(child) { this.insertBefore(child, this.firstChild); };</pre>
<p></code></p>
<p>Just make sure that the code above evaluates early on in your application initialization, and start prepending all you want. (Of course, if you&#8217;re using jQuery, <a href="http://api.jquery.com/prepend/">prepend is already well in hand</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2011/11/adding-prependchild-to-element.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Thoughts on Flash and HTML (as Expressed in an Email to &#8220;Tech News Today&#8221;)</title>
		<link>http://blogs.adobe.com/cantrell/archives/2011/11/my-thoughts-on-flash-and-html-as-expressed-in-an-email-to-tech-news-today.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2011/11/my-thoughts-on-flash-and-html-as-expressed-in-an-email-to-tech-news-today.html#comments</comments>
		<pubDate>Fri, 11 Nov 2011 21:32:39 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[HTML]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1078</guid>
		<description><![CDATA[I&#8217;m a big fan of the video and podcast Tech News Today. It&#8217;s one of the best technology shows I know of, and I seldom miss an episode. As some of you know, I sent them an email yesterday about our recent announcements around Flash and HTML, and they were kind enough to read some [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of the video and podcast <a href="http://twit.tv/tnt">Tech News Today</a>. It&#8217;s one of the best technology shows I know of, and I seldom miss an episode. As some of you know, I sent them an email yesterday about our recent announcements around Flash and HTML, and they were kind enough to read some if it on-air. It was way too long for them to read in its entirety, so I figured I&#8217;d post the whole thing here.</p>
<blockquote>
<p>As someone who has worked on the Flash Platform at Adobe for the last nine years, I just wanted to provide some additional context around yesterday&#8217;s announcement. Your coverage was very good, so no complaints, but I feel like it&#8217;s worth emphasizing a few things.</p>
<p>Part of Adobe&#8217;s story is enabling cross-platform solutions, but since Flash has never been supported on iOS, we weren&#8217;t able to deliver on that vision in the context of mobile browsers. With mobile browsers as good as they are now (the ICS browser looks amazing, and mobile Safari has always been awesome), it just makes more sense to use HTML.</p>
<p>In the context of installed applications, however, our story is stronger than ever. We recently released AIR 3 which is an extremely solid option for delivering installed applications through app stores across devices. Installed mobile applications is an area where we have been very successful delivering on our cross-platform vision, so that&#8217;s where we&#8217;re going to invest. Additionally, I think that model more closely matches the way we use our devices; I think mobile browsers are primarily used for accessing content, and the tendency is to use installed apps for more interactive content like applications and games.</p>
<p>Another point I want to make is in response to Sarah&#8217;s comment yesterday about Flash working better on some devices than others. That&#8217;s true. Getting Flash to work consistently across all the chipsets that we support (and with all the different drivers out there &#8212; some of which are better implemented than others) is a huge amount of work, and requires a lot of engineering resources. At some point, we had to ask ourselves if we wanted to be the kind of company that continues to use resources to pursue something we weren&#8217;t convinced made sense just because it&#8217;s what we&#8217;ve always done, or if we wanted to be more forward thinking. I think we absolutely made the right decision.</p>
<p>It&#8217;s also worth pointing out that we&#8217;re still investing heavily in Flash in the areas where it makes more sense like installed mobile and desktop applications, and the desktop browser. Specifically, the Stage3D APIs we introduced in AIR 3 are going to provide an in-browser gaming experience like nobody has ever seen (look for videos of Unreal running in the browser), and the new APIs for hardware accelerated video are going to mean higher quality video that uses less CPU and battery. These are areas that HTML5 has not yet fully addressed, so Flash can lead the way. We will continue to use Flash for doing things that HTML can&#8217;t, and for the things that HTML can do, we will embrace it.</p>
<p>That brings me to my last point: I think there&#8217;s this perception out there that Adobe dislikes HTML, and that yesterday was somehow a bitter concession. As someone inside the company, I can tell you that there are a lot of us who are very excited about what we can do with HTML5. Personally, I&#8217;ve been researching and working on HTML projects for quite some time at Adobe, and I&#8217;ve been working with a lot of very smart people who are as passionate about it as I am. There are definitely people out there (both inside Adobe and outside) who are passionate just about Flash, but I think it&#8217;s more accurate to say that the overwhelming majority of us are simply passionate about the web, and about building awesome experiences. Flash has always been about providing functionality that HTML couldn&#8217;t, however now that HTML5 can provide a lot of that functionality, we&#8217;re going to have a lot of fun seeing what we can do with it.</p>
<p>So in summary, look for Adobe to continue to push Flash forward in areas that HTML doesn&#8217;t yet address, to push HTML forward with contributions to WebKit and tooling, and to provide cross-platform solutions in whatever technology makes the most sense.</p>
</blockquote>
<p>If you want to hear it read on-air, it&#8217;s at the <a href="http://www.youtube.com/watch?feature=player_detailpage&#038;v=CzZR5YxaYXM#t=2706s" target="_new">45:00 mark</a> in the video below.</p>
<div align="center">
<iframe width="640" height="360" src="http://www.youtube.com/embed/CzZR5YxaYXM" frameborder="0" allowfullscreen></iframe>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2011/11/my-thoughts-on-flash-and-html-as-expressed-in-an-email-to-tech-news-today.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Building an Offline Mobile Web Application</title>
		<link>http://blogs.adobe.com/cantrell/archives/2011/11/building-an-offline-mobile-web-application.html</link>
		<comments>http://blogs.adobe.com/cantrell/archives/2011/11/building-an-offline-mobile-web-application.html#comments</comments>
		<pubDate>Fri, 04 Nov 2011 15:36:48 +0000</pubDate>
		<dc:creator>Christian Cantrell</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blogs.adobe.com/cantrell/?p=1070</guid>
		<description><![CDATA[If you&#8217;re interested in building a mobile web application that works offline and is virtually indistinguishable from a native installed application, this post explains most (if not all) of what you need to know. (To see an example of an offline mobile web application, see the post, Porting an AIR Application to HTML.) What is [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blogs.adobe.com/cantrell/files/2011/11/compass_icon_screenshot_rounded.jpg" width="250" height="199" style="float:right; margin: 5px;"/>If you&#8217;re interested in building a mobile web application that works offline and is virtually indistinguishable from a native installed application, this post explains most (if not all) of what you need to know. (To see an example of an offline mobile web application, see the post, <a href="http://blogs.adobe.com/cantrell/archives/2011/11/porting-an-air-application-to-html.html">Porting an AIR Application to HTML</a>.)</p>
<p><strong>What is an Offline Mobile Web Application?</strong></p>
<p>An offline mobile web application has the following properties:</p>
<ul>
<li>It&#8217;s written in HTML, CSS, and JavaScript, and it&#8217;s served from a web server.</li>
<li>It functions without an internet connection.</li>
<li>When users save the application to their home screen, they get a custom icon and start-up image (the image that is displayed briefly on iOS while the app is loading and initializing).</li>
<li>The application can be updated over the network just by opening it (as opposed to going through an app store).</li>
</ul>
<p><strong>The Components of an Offline Mobile Web Application</strong></p>
<p>There are four primary pieces of functionality that offline mobile web applications need:</p>
<ol>
<li><strong>Configuration</strong>. For iOS devices, there are a few tags you can add to your application to make it look and act much more like a native application.</li>
<li><strong>Custom icons and start-up images</strong>. To fit in with native applications, offline web applications should specify custom icons and start-up images for iOS.</li>
<li><strong>Caching</strong>. Offline web applications use the HTML5 application cache to make themselves available offline.</li>
<li><strong>Updating</strong>. Offline mobile web applications need to update the local cache when the application has changed on the server.</li>
</ol>
<p><strong>Configuration</strong></p>
<p>On iOS, you can use several different meta tags to make your mobile web application look and feel much more like a native application. For instance, to get rid of the browser chrome when your application is launched from the home screen (in other words, to tell iOS to use a minimal web control rather than full-blow Safari to display your application), use the following tag:</p>
<p><code>
<pre>&lt;meta name=&quot;apple-mobile-web-app-capable&quot; content=&quot;yes&quot; /&gt;</pre>
<p></code></p>
<p>To customize the look of the iOS status bar, you can use a meta tag with the &quot;name&quot; attribute set to &quot;apple-mobile-web-app-status-bar-style&quot;. In my <a href="http://www.htmlcompass.com">HTMLCompass example</a>, I wanted the status bar to be as unobtrusive as possible, so I configured it to be black and translucent like this:</p>
<p><code>
<pre>&lt;meta name=&quot;apple-mobile-web-app-status-bar-style&quot; content=&quot;black-translucent&quot;/&gt;</pre>
<p></code></p>
<p>Finally, it&#8217;s important to configure Safari&#8217;s viewport using a meta tag with the name &quot;viewport&quot;. In order to configure the viewport properly for my HTMLCompass example (including preventing the user from zooming in and out of the application), I use the following tag:</p>
<p><code>
<pre>&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0&quot;/&gt;</pre>
<p></code></p>
<p>For more information on configuring web applications on iOS, see Apple&#8217;s document, <a href="http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html">Configuring Web Applications</a>. For a detailed description of everything you can do with your application&#8217;s viewport, see <a href="http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html#//apple_ref/doc/uid/TP40006509-SW19">Viewport Settings for Web Applications</a>.</p>
<p><strong>Custom Icons and Start-up Images</strong></p>
<p>Creating custom icons for your application is an important part of making it look like it belongs installed on a device. It&#8217;s not strictly necessary, but default icons (or icons derived from screenshots) will not give your application a high-quality, polished look and feel. (Note that I believe this is currently only supported on iOS devices; Android seems to use your &quot;favicon&quot; as your application&#8217;s icon, instead.)</p>
<p>Specifying custom icons is as easy as including one or more link tags in the <code>&lt;head&gt;</code> section of your application. The only trick is to make sure that you specify different icons for different screen resolutions. On iOS devices, that currently means icons for pre-retina screens (iPhone 3G and 3GS), retina displays (iPhone 4 and iPhone 4S), and the iPad. Below are the tags referencing the various icons for my HTMLCompass example:</p>
<p><code>
<pre>&lt;!-- Home screen icons --&gt;
&lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;57x57&quot; href=&quot;icons/apple-touch-icon-57x57.png&quot; /&gt;
&lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;72x72&quot; href=&quot;icons/apple-touch-icon-72x72.png&quot; /&gt;
&lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;114x114&quot; href=&quot;icons/apple-touch-icon-114x114.png&quot; /&gt;</pre>
<p></code></p>
<p>Specifying start-up images is almost as easy, however in addition to taking different screen resolutions into account, you also have to take into account different orientations for the iPad (iPhones and iPods can&#8217;t start applications in landscape mode). Below are tags referencing the three start-up images I created for my HTMLCompass example (note that I didn&#8217;t bother making one for the iPhone 3G or 3GS):</p>
<p><code>
<pre>&lt;!-- iPad --&gt;
&lt;link rel=&quot;apple-touch-startup-image&quot; href=&quot;starts/ipad-landscape.jpg&quot; media=&quot;screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape)&quot; /&gt;
&lt;link rel=&quot;apple-touch-startup-image&quot; href=&quot;starts/ipad-portrait.jpg&quot; media=&quot;screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait)&quot; /&gt;
&lt;!-- iPhone (retina) --&gt;
&lt;link rel=&quot;apple-touch-startup-image&quot; href=&quot;starts/iphone-retina.jpg&quot; media=&quot;screen and (max-device-width: 640px)&quot; /&gt;</pre>
<p></code> (Note that the size of these images must be exactly correct for them to function as expected.)</p>
<p>There&#8217;s a little more to know about configuring and specifying application icons. For instance, iOS automatically makes your icons appear three-dimensional and glossy by applying filters, however if you decide that you&#8217;d rather add such effects yourself, it&#8217;s possible to specify that your icons are &quot;precomposed.&quot; For more information, see Apple&#8217;s documentation entitled <a href="http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html">Configuring Web Applications</a>.</p>
<p><strong>Caching</strong></p>
<p>Caching your application so that it&#8217;s available for offline use is surprisingly easy. You essentially place a manifest file on your server which lists all the files that you want saved to the application cache. Below is the <a href="http://www.htmlcompass.com/compass.manifest">manifest file</a> for <a href="http://www.htmlcompass.com">HTMLCompass.com</a>:</p>
<p><code>
<pre>CACHE MANIFEST

# Version: 1.04

CACHE:
index.html
icons/favicon.png</pre>
<p></code></p>
<p>You then need to reference the manifest file in your application&#8217;s <code>&lt;html&gt;</code> tag, like this:</p>
<p><code>
<pre>&lt;html manifest=&quot;compass.manifest&quot;&gt;</pre>
<p></code></p>
<p>That&#8217;s essentially it. For more information on the syntax of your manifest file (which supports additional functionality), see the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#manifests">cache manifest syntax section</a> of the WHATWG <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html">offline web application specification</a>.</p>
<p>Here are three important tips that will make working with cached web applications smoother:</p>
<ol>
<li>Don&#8217;t forget to configure the MIME type on your web server (as described <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#writing-cache-manifests">here</a>). If you don&#8217;t map the extension of your manifest file to the MIME type &quot;text/cache-manifest,&quot; you will not get the caching behavior you&#8217;re expecting.</li>
<li>I recommend adding a version comment to your manifest file (see example above). The version comment has no official use, however just making a change to your manifest file will cause your application to be re-downloaded. For example, if I change my index.html page without changing my manifest file, the local cache on the client will not be updated. After changing my index.html file, I can increment the version number in my manifest file which will cause the change to index.html to be picked up.</li>
<li>Once your application has been cached, the development process becomes more difficult. Specifically, after you make a code change, it will not show up in your browser until you update the cache with the new version. Rather than having to make a change to your manifest file in order to pick up your application changes, the best solution I&#8217;ve found is to simply change the reference to your manifest file in your <code>&lt;html&gt;</code> tag so that it points to something nonexistent. For instance, when I&#8217;m developing, I change the reference to my manifest file to compass.manifest.TODO. That causes a 404 which causes the application to be reloaded from the server rather than loaded from the cache. (The reason I append &quot;TODO&quot; is so I&#8217;ll find it while performing one last check of my code before checking it in.)</li>
</ol>
<p><strong>Updating</strong></p>
<p>Now that you have your application caching, you need to know how to update it. There are four simple steps to updating an offline web application:</p>
<ol>
<li>Change your manifest file so the browser knows to grab the new version (see previous section).</li>
<li>Listen for an event letting you know that the new version of your application has been downloaded and is ready.</li>
<li>Swap the old version for the new version.</li>
<li>Reload the page (optional).</li>
</ol>
<p>Telling clients that a new version of your application is ready is as easy as making a change to your manifest file (updating the &quot;version&quot; comment, most likely). In order to be notified of when the new version is downloaded and the cache is ready to be updated, simply listen for the <code>updateready</code> event on the <code>applicationCache</code> like this:</p>
<p><code>
<pre>window.applicationCache.addEventListener('updateready', ...);</pre>
<p></code></p>
<p>Inside your event handler, tell the application cache to update itself like this:</p>
<p><code>
<pre>window.applicationCache.swapCache();</pre>
<p></code></p>
<p><code>  </code> Updating your application cache is an asynchronous operation meaning<br />
  it happens in the background while the old version of your application loads, renders, and executes. That means even though you have just updated the cache with the new version of your application, the user will still see the old version. You can either do nothing (so that users will see the new version the next time they use the app), or you can programmatically refresh the page with code like this:</p>
<p><code>
<pre>window.location.reload();</pre>
<p></code></p>
<p>To put it all together, my HTMLCompass example has a function called <code>checkForUpdate</code> which looks like this:</p>
<p><code>
<pre>function checkForUpdate()
{
  if (window.applicationCache != undefined &amp;&amp; window.applicationCache != null)
  {
    window.applicationCache.addEventListener('updateready', updateApplication);
  }
}

function updateApplication(event)
{
  if (window.applicationCache.status != 4) return;
  window.applicationCache.removeEventListener('updateready', updateApplication);
  window.applicationCache.swapCache();
  window.location.reload();
}</pre>
<p></code></p>
<p>There are several other events thrown by the application cache that you can hook into in order to achieve various functionality. For instance, when your code detects that a new version of your application is available, you may choose to show the user a notification or even a progress bar indicating how much is still left to download. For a full list of application cache events, see the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#appcacheevents">event summary section</a> of the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html">offline web application specification</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.adobe.com/cantrell/archives/2011/11/building-an-offline-mobile-web-application.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

