<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Tales of a Developer Advocate]]></title>
  <link href="http://paul.kinlan.me/atom.xml" rel="self"/>
  <link href="http://paul.kinlan.me/"/>
  <updated>2013-02-04T12:15:05+00:00</updated>
  <id>http://paul.kinlan.me/</id>
  <author>
    <name><![CDATA[Paul Kinlan]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Bootstraping your own mobile web testing lab for Android Part 1]]></title>
    <link href="http://paul.kinlan.me/bootstraping-your-own-mobile-device-lab-part-1/"/>
    <updated>2013-02-04T11:08:00+00:00</updated>
    <id>http://paul.kinlan.me/bootstraping-your-own-mobile-device-lab-part-1</id>
    <content type="html"><![CDATA[<p>What do you do if you want to quickly test your sites on mutliple versions of Android at the same time?</p>

<p>There are couple of solutions, such as <a href="http://html.adobe.com/edge/inspect/">Adobe Edge Inspect</a>, but what if you want to create and manage your own in your own workflow?  I haven&#8217;t seen single solution yet.</p>

<p>Here is a simple shell script that I created that starts to get you on your way to your own testing lab.  It connects to every single Android device that is attached to your machine by using <code>adb</code> (Android Debugging tool).</p>

<p>The process is as follows (and please suggest better ways):</p>

<ul>
<li>Kill any existing adb servers</li>
<li>Get a list of attached devices</li>
<li>For each device set up port forwarding (required for <a href="https://developers.google.com/chrome-developer-tools/docs/remote-debugging">Chrome Dev tools</a>)</li>
<li>Fire Android intent to open the browser (with a url if one is on the command line)</li>
</ul>


<script src="https://gist.github.com/4706201.js"></script>


<p>It&#8217;s not a complete solution, but it is a nice way to start.  My ultimate goal is to have a <a href="http://www.xda-developers.com/android/adb-fully-working-on-raspberry-pi/">Raspberry PI</a> hosting adb and all the devices that I can attach to it with an attached proxy that will route all my devtools requests to the correct device.</p>

<p>How do you test across mutliple devices?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Traffic-lights with CSS]]></title>
    <link href="http://paul.kinlan.me/traffic-lights-with-css/"/>
    <updated>2013-01-04T12:28:00+00:00</updated>
    <id>http://paul.kinlan.me/traffic-lights-with-css</id>
    <content type="html"><![CDATA[<p>Just before Christmas I wanted to build a site that helped developers understand the impact that using Web Platform features would have on there potential reach.
For example, if I used WebGL what is my target reach and what additional features can I use without impacting my potential audience figures.</p>

<p>I launched <a href="http://iwanttouse.com">iwanttouse.com</a>. Sweet. Anyway, that is not the point of this post.  One of the features of this site is.</p>

<p>One of the core features I wanted to implement was a traffic light system that graded the features like a traffic light. Green = Good, Red = Bad, Amber = Be Warned.</p>

<p>My original implementation was just using some simple CSS classes.</p>

<pre><code>.good {
  color: green;
}

.ok {
  color: amber;
}

.bad {
  color: red;
}
</code></pre>

<p>I knew this was bad, but using RGB I couldn&#8217;t work out sanely how to grade between 255,0,0, 255,126,0 and 0,255,0 without having logic in my code that looked like:</p>

<pre><code>if (support &lt; 25%) then .bad
if (support &gt;25% and support &lt; 75%) then .ok
if (support &gt; 75%) then .good
</code></pre>

<p>added to that, I wanted the color to be more red than amber if it was at 35%.</p>

<p>Anyway, after a little chat with the awesome <a href="http://twitter.com/aerotwist">Paul Lewis</a>, he mentioned that <a href="http://www.css3.info/preview/hsla/">HSL</a> (Hue, Saturation, Light) color scheme would be good for this problem
because naturally the Hue value (0-359) rotates from Red, through Amber to Green (0 = Red, 45 = Amber, 90 = Green)</p>

<p><span style="color: hsla(0, 50%, 50%, 1)">Red = <code>color: hsla(0, 50%, 50%, 1)</code></span>
<span style="color: hsla(45, 50%, 50%, 1)">Amber = <code>color: hsla(45, 50%, 50%, 1)</code></span>
<span style="color: hsla(90, 50%, 50%, 1)">Green = <code>color: hsla(90, 50%, 50%, 1)</code></span></p>

<p>It is then simple given a value for percentage support to map that to 0-90 range and produce your traffic light colors.</p>

<pre><code>element.styles.color = "hsla(" + ((percentage / 100) * 90) + ", 50%, 50%)";
</code></pre>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Dear AppCache we need to talk.]]></title>
    <link href="http://paul.kinlan.me/dear-appcache/"/>
    <updated>2012-04-04T15:12:00+01:00</updated>
    <id>http://paul.kinlan.me/dear-appcache</id>
    <content type="html"><![CDATA[<p>It&#8217;s not me.  It&#8217;s you!</p>

<p>Ok. thats a little harsh.  Without AppCache we wouldn&#8217;t even be able to think about building Offline enabled web apps.  But it seriously does have some issues, one of which I am blogging about today has been not discussed in depth before (as far as I can tell).</p>

<p>Imagine you building an offline enabled app that integrates with registerProtocolHandler or registerContentHandler. These two API&#8217;s use query parameter substitution to pass data from the client page to the service page (http://mailfoo.com/createmail.php?t=paul.kinlan@gmail.com&amp;s=Test Message for example opens up your mail client at createmail.php when you click on a mailto link). This works well for purely online apps, but as we will see when used with apps built with AppCache you won&#8217;t get the experience you are expecting, at worst you could DoS your site.</p>

<p>Your createmail.php will likely render a manifest=&#8221;cache.manifest&#8221; attribute in your html element, which when visited is cached offline and works as expected. The problem lies in the fact that AppCache treats the entire URI (including query strings) as an identifier to the page, therefore if you have a unique query string each of these pages are downloaded and added to the AppCache group.</p>

<p>Ok, cool, but what does this mean? Well it means that http://mailfoo.com/createmail.php?t=paul.kinlan@gmail.com is cached separeately to http://mailfoo.com/createmail.php?t=paul.kinlan@hotmail.com, all the resources will be quickly fetched as the manifest has already got hold of the data and they are already cached in AppCache.</p>

<p>Whilst you are online, this is all gravy. It works beautifully. However now go offline and create an email to paul.kinlan@gmail.com (it works because it is cached), but try instead creating an email to paulkinlan@google.com(via a mailto link)&#8230; hmm, where did my app go? It is not there because it has not yet been cached for offline use. Big problem.</p>

<p>You thought that was bad? Now for the kicker.</p>

<p>You happily make and send 100&#8217;s of emails over a couple of weeksr. Whilst you are online, all works well. The developer of the app decides to upload a new version of their code so updates their app cache. What happens? Every single unique url (so every email you might have sent via a mailto) is requested and downloaded again (even if it is not in the manifest, it is in the app cache group). If I have sent 100 unique emails via mailto, then every single page with that query sting is fetched quickly by the browser&#8230; Seems like a good way to add a lot of load to your machine.</p>

<p>It is pretty hard to change a specifictation in flight so we need to start documenting patterns for building offline apps than we do today because AppCache is not easy to use, and there are lots of gotchas like this that make developers not even bother using the API.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The New iPad is the perfect name]]></title>
    <link href="http://paul.kinlan.me/the-new-ipad-is-the-perfect-name/"/>
    <updated>2012-03-18T00:00:00+00:00</updated>
    <id>http://paul.kinlan.me/the-new-ipad-is-the-perfect-name</id>
    <content type="html"><![CDATA[<p>I was thinking about this the other day. I remember being in the Apple store in Liverpool about 2 months ago and I distinctly remember hearing the following: &quot;Do you have any of the new iPads in?&quot; several times over the space of about 30 minutes (I was playing with MacBook Airs).</p> <p>Come to think of it there were several other products people asked for as &quot;the new X&quot;.</p> <p>It is pretty cool. No product name obsolescence. You go in to a store you ask for the new product, they give it to you.</p> <p>You either have the new one or the old one.</p> <p>I predict the iPad series will only ever now be known as iPad and The New iPad. I also believe they will do it for more products the next being The New iPhone.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[I am willing to pay someone to move my blog from Posterous.]]></title>
    <link href="http://paul.kinlan.me/i-am-willing-to-pay-someone-to-move-my-blog-f/"/>
    <updated>2012-03-18T00:00:00+00:00</updated>
    <id>http://paul.kinlan.me/i-am-willing-to-pay-someone-to-move-my-blog-f</id>
    <content type="html"><![CDATA[Posterous has been great for me, but now it is time to move it.

I don&#8217;t have the time to do this so I am very willing to pay someone a
modest fee for managing the move of my blog to a platform that meets the
following requirements:

Mandatory Requirements:
- not a hosted solution like Blogger or Tumblr
- static output (no database)
- can write posts in markdown, text or html
- all content can be managed through git.
- URL structure is kept exactly the same as now
- will keep all the posts that I imported into posterous from blogger.
- full control over templates

Nice to haves:
- preferably not a ruby based system

Not bothered about:
- any authoring or management front end.
- auto posting networks
- existing comments or future commenting systems
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[We need to kill off the localStorage API]]></title>
    <link href="http://paul.kinlan.me/we-need-to-kill-off-the-localstorage-api/"/>
    <updated>2012-02-28T00:00:00+00:00</updated>
    <id>http://paul.kinlan.me/we-need-to-kill-off-the-localstorage-api</id>
    <content type="html"><![CDATA[<div><span style="font-family: Arial,sans-serif; font-size: 13px; line-height: 18px; background-color: rgb(255,255,255);">It is a failure of the web, browser vendors and developers that we are in this situation, but w</span><span style="background-color: rgb(255,255,255); font-family: Arial,sans-serif; font-size: 13px; line-height: 18px;">e need to stop advocating for and building examples that use the LocalStorage API&#39;s, it is simply not a scalable API and the more we build for it the harder it will be for us to ween ourselves off it.  </span></div> <p /><div><span style="background-color: rgb(255,255,255); font-family: Arial,sans-serif; font-size: 13px; line-height: 18px;">LocalStorage has poor querying capabilities, terrible performance, small storage in many browsers, crazily inconsistent eventing and a nasty habit of locking.  It&#39;s saving grace is simple semantics and &quot;browser support&quot;.</span></div> <p /><div>Client-side and offline web-apps are not a reality with localStorage, and if we keep pushing it, we are never going to be in a situation where we have a compelling offline or client-side story.</div><p /><div>We need to bite the bullet, move on and start building compelling apps, examples and demos build around IndexedDB, that is our only future (I am still aggrieved that the web dropped WebSQL, it was simple and familiar) and we need to do this by stopping to support localStorage. Period.<p /> <div><span style="font-family: Arial,sans-serif; font-size: 13px; line-height: 18px; background-color: rgb(255,255,255);">To this effect, I have taken the BackboneJS example in TodoMVC (﻿by <a href="https://github.com/addyosmani/todomvc">Addy Osmani</a></span><span style="font-family: Arial,sans-serif; font-size: 13px; line-height: 18px; background-color: rgb(255,255,255);">) and <a href="https://github.com/PaulKinlan/todomvc/commit/39205e06c4553ceb0c455fbf7d1c69a801c281bb">added IndexedDB support</a></span><span style="line-height: 18px;"> u</span><span style="font-family: Arial,sans-serif; font-size: 13px; line-height: 18px; background-color: rgb(255,255,255);">sing the Backbone JS adapter b</span>y <a href="https://github.com/superfeedr/indexeddb-backbonejs-adapter">Julien Genestoux</a>.<span style="font-family: Arial,sans-serif; font-size: 13px; line-height: 18px; background-color: rgb(255,255,255);"> I quickly removed the LocalStorage interface, and in a couple of lines of config change I had IndexedDB support in.</span></div> </div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[On Vendor Prefixes]]></title>
    <link href="http://paul.kinlan.me/on-vendor-prefixes/"/>
    <updated>2012-02-09T00:00:00+00:00</updated>
    <id>http://paul.kinlan.me/on-vendor-prefixes</id>
    <content type="html"><![CDATA[<p>There is a lot of <a href="http://lists.w3.org/Archives/Public/www-style/2012Feb/0313.html">chatter about Mozilla considering</a> implementing some webkit specific prefixes - I encourage everyone to read &#8221;<a href="https://wiki.mozilla.org/Platform/Layout/CSS_Compatibility#questions_and_methodology">Platform/Layout/CSS compatibility</a>&#8221;</p>
<p />
<div>My <strong>personal</strong> take on this is &#8220;great&#8221; and I am glad they have the guts to start the conversation, but in my eyes it should only happen IFF the vendor is going to choose to stop supporting their existing prefix and start supporting the other parties prefix as what they agree to be the way they want the standard to move.&nbsp;</div>
<p />
<div>I know a lot of people who targeted mobile saw that the audience they needed to target were using almost exclusively a WebKit based browser and thus chose that as <em>the</em> platform to target. &nbsp;If the mobile device you want to target or your customers want you to target is pretty much a single choice then web developers naturally gravitate to the browser that is most popular and for a long time in the case of iPhone etc, WebKit was (up until recently) your only web platform you had to develop for.</div>
<p />
<div><a href="http://remysharp.com/2012/02/09/vendor-prefixes-about-to-go-south">Remy Sharp&#8217;s</a> blog post is a good summary of the situation, but I don&#8217;t agree with most of the propos<span style="font-family: arial, helvetica, sans-serif;">ed browser solutions. &nbsp;</span></div>
<p />
<div><span style="font-family: arial, helvetica, sans-serif;">To Quote:</span></div>
<blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex;">Browsers need to:
<ul>
<li>Fucking drop experimental prefixes. It&#8217;s unacceptable and a disservice to the developers working with your browser. You need to give timelines to dropping these things.</li>
</ul>
<ul>
<li>Non-production ready browsers should support experimental prefixes,&nbsp;production ready releases&nbsp;should not. If it&#8217;s Chrome 16 - the stable version - experimental support should not be baked in. The properties should be full available&nbsp;without&nbsp;the prefix.</li>
</ul>
</blockquote>
<div>
<div>On dropping vendor prefixes, yes but only if they commit to move to another one. &nbsp;The whole gradient syntax winded me up no end - if at this point WebKit had chosen to name it consistently with the -moz implementation and prefixed it so then we could have started to completely drop the old syntax that IMO would have been better. &nbsp;At the same time though we should be educating developers about the tooling available to make the vendor prefixing become a non-story (in most cases).</div>
<p />
<div>I had a little chuckle about &#8220;production ready browsers&#8221; - I don&#8217;t think this is sensible or feasible given the update cycles of browser and that developers want what they have chosen to implement to look ace in the browsers that they have chosen to make it look awesome in. &nbsp;If you have platform features that no other browser is going to support either now in the near future then we need to have a way to not have them in the base &#8220;namespace&#8221; - putting them in there is going to cause more problems.</div>
<p />
<div>Anyway, these are my thoughts and can be and sometimes are hogwash - my motto is &#8220;don&#8217;t hate, advocate&#8221; - and as Remy says&nbsp;&#8220;As developers we need to better educate.&#8221; to which I whole heartedly agree.</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Getting your app to support Web Intents on Chrome]]></title>
    <link href="http://paul.kinlan.me/getting-your-app-to-support-web-intents-on-ch/"/>
    <updated>2012-02-08T00:00:00+00:00</updated>
    <id>http://paul.kinlan.me/getting-your-app-to-support-web-intents-on-ch</id>
    <content type="html"><![CDATA[<p>Chrome just got Web Intents support in Dev and Canary builds (18 onwards). &nbsp;This is a huge milestone and I am very excited by this first step along the path of building a more connected web of apps.</p>
<p />
<div>A lot of developers have asked me how to get started as it seems some of the demos on <a href="http://demos.webintents.org">http://demos.webintents.org</a> don&#8217;t register correctly. &nbsp;I have a good answer for that - in short: Chrome doesn&#8217;t yet detect the intent tag, instead applications currently can only register their support for an action such as &#8221;<a href="http://webintents.org/share">share</a>&#8221; via the <a href="http://code.google.com/chrome/extensions/manifest.html">Chrome apps manifest</a>.</div>
<p />
<div>The longer version is a little more complex:</div>
<div><ol>
<li>Consensus over the introduction of a new tag in to the spec has not yet been reached.</li>
<li>Working with members of the DAP in the <a href="https://github.com/PaulKinlan/WebIntents/tree/master/tools/chrome">intents task force</a>, it is clear that discovery of applications and services shouldn&#8217;t only take place by detecting a tag on a web page. &nbsp;What happens if the service you want to &#8220;Share&#8221; a video too is a TV connected to your local network? Or an external native application wants to be able to support a &#8220;Save&#8221; action. &nbsp;To enable this important use case the User Agent should be able to determine the services it presents to users, and this is why this is allowed in the <a href="http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html#user-agent-behavior">specification (3rd paragraph)</a>.</li>
</ol></div>
<div>Bringing this closer to home, because the discovery and presentation of an app&#8217;s capabilities can be managed by the User Agent, and Chrome has the concept of extensions and installed apps we can quickly enable the intents feature by letting developers declare their support for actions in the manifest.</div>
<p />
<div>So what does the declaration in the Chrome apps/extension system look like? &nbsp;It is pretty easy, it is an entry into the manifest called &#8220;intents&#8221;. &nbsp;It looks like:</div>
<p />
<p>{<br />&nbsp;&nbsp;&#8220;name&#8221;: &#8220;Share to Gmail&trade;&#8221;,<br /> &nbsp;&nbsp;&#8220;version&#8221;: &#8220;0.0.0.2&#8221;,<br />&nbsp;&nbsp;&#8220;icons&#8221; : {<br />&nbsp;&nbsp;&nbsp;&nbsp;&#8220;16&#8221; : &#8220;favicon.ico&#8221;<br />&nbsp;&nbsp;},<br />&nbsp;&nbsp;&#8220;intents&#8221; : {<br />&nbsp;&nbsp;&nbsp;&nbsp;&#8221;<a href="http://webintents.org/share">http://webintents.org/share</a>&#8221; : {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;type&#8221; : [&#8220;text/uri-list&#8221;],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;title&#8221; : &#8220;Share to Gmail&#8221;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;path&#8221; : &#8220;/launch.html&#8221;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />}</p>
<p />
<div>It is that simple. &nbsp;The intent section includes a dictionary of supported action (<a href="http://webintents.org/share">http://webintents.org/share</a>) and in each action object there is an array of data types that the application or extension can handle, the friendly name to appear in the picker and a path to what should be opened when the user selects your app. &nbsp;The client-side code remains exactly the same as it would in a normal web app.</div>
<div>
<p />
<div>In the long term we want applications to be able to declare their capabilities and services directly through their html and this will be done with the Intent tag. &nbsp;However whilst the standardisation work continues we want to make sure that developers today can start building apps that can take advantage of the Web Intent system.</div>
<p />
<div>A lot more examples can be found on the&nbsp;<a href="https://github.com/PaulKinlan/WebIntents/tree/master/tools/chrome">Web Intents Github repository</a>.</div>
<p />
<div>Expect a lot more posts about how to build applications that love each other with Web Intents.</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Two years and counting at Google]]></title>
    <link href="http://paul.kinlan.me/two-years-and-counting-at-google/"/>
    <updated>2012-02-07T00:00:00+00:00</updated>
    <id>http://paul.kinlan.me/two-years-and-counting-at-google</id>
    <content type="html"><![CDATA[As of February 1st I have been at Google for two years! Yay!  It has been an amazing time and I am truly honored to work for such a company.<p /><div>A year ago (+1 week) I wrote about my <a href="http://paul.kinlan.me/my-first-year-in-google">first year experiences</a>, it was pretty crazy in my first year, not only did the scale of the work hit me overwhelm me, but so did the sheer number of excellent engineers and colleagues.  My overall feeling was one of awe.</div> <p /><div>My second year has taken that to the next level again!</div><p /><div>One of the highlights of the year was that I got to speak at Google IO - Mobile Web App development: Zero to Hero, where myself and <a href="http://www.softwareas.com">Mike Mahemoff</a> (with the help of <a href="https://plus.google.com/118075919496626375791/posts">Eric Bidelman</a> and <a href="http://smus.com/">Boris Smus</a>) built an app that worked across 5 different form factors using <a href="http://github.com/PaulKinlan/IOReader">one code base</a> - the awesome thing about this is that we built <a href="http://github.com/PaulKinlan/LeviRoutes">LeviRoutes</a> (a url routing framework) and <a href="http://github.com/PaulKinlan/FormfactorJS">FormfactorJS</a> (a form factor detection library).</div> <p /><div>I got to travel a lot too - I am trying to count all the countries that I have been too; it is a lot - USA, France, Spain, Portugal, Romania, Belgium, Germany, Poland, Netherlands, Czech Republic.  Whilst I was traveling I did a <a href="http://kinlan-presentations.appspot.com/index.html">lot of presentations</a> which is a really good way to meet people that I wouldn&#39;t normally get the chance to meet. I also managed to get completely misquoted on <a href="http://techcrunch.com/2011/11/24/chrome-getting-native-gamepad-webcam-and-webrtc-support-in-early-2012/">TechCrunch too</a> - I say misquoted, I didn&#39;t even say the words that they attributed to me.</div> <p /><div>The biggest thing for me was that <a href="http://paul.kinlan.me/web-intents-a-fresh-look">Web Intents became a real living and breathing project</a> and first native implementations have landed in Chrome, it has changed a lot since my first announcement late in 2010.  This is a huge change for users of the web and I am immensely proud to be working on the project and with some amazingly talented engineers (<a href="https://plus.google.com/117548600251804149016/posts">James Hawkins</a>, <a href="https://plus.google.com/116540516771641623238/posts">Greg Billock</a>, <a href="https://plus.google.com/107226275692313566931/posts">Rachel Blum</a>, Ben Smith and many others) and helping to define the specifications.  We have big goals for Web Intents so stay tuned.</div> <p /><div>One of my resolutions last year was to be in Liverpool a little more and <a href="http://www.liverpooldailypost.co.uk/ldpbusiness/business-local/2011/08/03/google-heads-to-liverpool-to-work-with-smes-92534-29166327/">I managed to do</a> that, it turns out that I unwittingly pre-announced another project (that I honestly had no idea was about to launch) I am glad it happened though, there are a huge swath of developers in the UK that are outside London and I don&#39;t think anyone reaches them properly and this gives me a chance to work with them.</div> <p /><div>So.  What is happening in the year to come?  It is hard to say, there are a lot of cool things happening, but I know two things for sure: we will keep working on making sure users&#39; experience of the web is improved through technologies such as <a href="http://webintents.org">Web Intents</a> and we will keep working with developers to build awesome sites and applications on the web and prove that the web is our future.</div> <p /><div>On to my third year! </div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Web Intents: A fresh look]]></title>
    <link href="http://paul.kinlan.me/web-intents-a-fresh-look/"/>
    <updated>2011-07-01T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/web-intents-a-fresh-look</id>
    <content type="html"><![CDATA[<p>We have a huge problem on the web today.  If I built an image
gallery application and I wanted to let users edit an image so that they can
remove red-eye from a photo I either have to build an application that edits
the images, or integrate with a 3rd party solution.  Doing this is hard and
stops you from building an awesome image gallery; and what happens if the
user has a favorite service that they already use to remove red-eye?
 Simple, you have a frustrated user.</p>

<p>We have a solution!</p>

<p>In December 2010 <a href="https://twitter.com/Paul_Kinlan/status/17998349231722497">I announced a project</a> called <a href="http://www.webintents.com">Web
Intents</a> whose goal was to allow developers to
build applications and services that could work with each other, but not
need to explicitly know about each other &ndash; the concept has heavily inspired
by the Intent system in Android, although the API bore no resemblance.  It
would allow you to build applications using just the functionality your
cared about, and then delegate the other functionality to the
users preferred choice of service.</p>

<p>After some conversations, <a href="http://paul.kinlan.me/so-what-is-happening-with-web-intents">I moved to try and support Web Introducer</a> as a
specification over Web Intents. For one reason or another this didn&rsquo;t quite
work out so I decided to plug away at revising the WebIntents work that I
started back in November.</p>

<p>It turns out there is a lot of interest internally with the idea of Web
Intents and how it can work in modern browsers.  We set up a small crack
team and after a flurry of work, speccing and prototyping how we think it
might look we have put a <a href="https://github.com/PaulKinlan/WebIntents">prototype API on to Github</a>.  <a href="http://examples.webintents.org/">Have a play</a>, it is really easy to get started.</p>

<p>So what changed?</p>

<p>A lot as it happens. It is not the same as the initial project that
I experimented with, although the goals are the same. We have an objective
to make the developer experience of the API so painless that most developers
can start integrating with applications in 5 minute of reading the spec &ndash; in
fact we want it so that most developers can just copy and past examples and
it will work with their service.  We have tried to drastically reduce the
API surface and make it so there is literally only one or two lines of code
you need to start an activity.</p>

<p>Service registration has been made even easier that my initial project
through the use of a new tag, for example:</p>

<div class="CodeRay">
  <div class="code"><pre>&lt;intent
  action=&quot;http://webintents.org/share&quot;
  type=&quot;text/uri-list&quot;
  href=&quot;share.html&quot;
/&gt;</pre></div>
</div>


<p>This small tag, that is included in the head of your application will signal
to the browser the intention to handle a &ldquo;share&rdquo; action for a selection of
URI&rsquo;s (think &ldquo;share this page&rdquo;), and will register it in the system so that
the user can choose it when a client application wants to provide &ldquo;share&rdquo;
functionality in their app.</p>

<p>When the service is chosen by the user, and the service is loaded the intent
data is passed to the open application and is available on the
<code>window.intent</code> object.</p>

<p>For clients to initiate an Activity it is easy too.  Simply declare an
intent and start the Activity as follows:</p>

<div class="CodeRay">
  <div class="code"><pre>var intent = new Intent();
intent.action = &quot;http://webintents.org/share&quot;;
intent.type = &quot;text/uri-list&quot;;
intent.data = &quot;http://paul.kinlan.me&quot;;

window.navigator.startActivity(intent);</pre></div>
</div>


<p>The system will take care of the service resolution for the action and
compatible data formats and give the user the choice of using
their favorite application to handle the &ldquo;share&rdquo; intent.</p>

<p>I have only just touched the surface of what you can do with the API.  There
are a lot of things that you can do with the API over and above what I have
described in this 5 minute overview.  A selection of examples can be found
at <a href="http://examples.webintents.org/">http://examples.webintents.org/</a> where we show you how to build
applications that solve some common use-cases. I particularly like the cloud
kitten service provided by the <a href="http://examples.webintents.org/intents/pick/index.html">&ldquo;pick&rdquo; example</a>.</p>

<p>We are working with Mozilla to define a common approach to solving the
challenges that web integrators face today. We are interested in hearing
your thoughts and we are still thrashing out the API so bits of it might
change but the intent is still the same.</p>

<p>My closing thoughts are: &ldquo;This project will fundamentally change and improve
the way we build applications on the web today for our users.&rdquo;</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[window.name]]></title>
    <link href="http://paul.kinlan.me/window-name/"/>
    <updated>2011-06-22T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/window-name</id>
    <content type="html"><![CDATA[<p>I have learnt a lot of the last couple of days about inter-window and
inter-iframe communication.  I documented <a href="http://paul.kinlan.me/webmessaging-is-broken">some of my frustrations</a> about Web Messaging API&rsquo;s and
an attempted work around.</p>

<p>For you to be able to pass data into a window (that isn&rsquo;t on your domain) so
that it is available before the onload event fires in the opened window, the
only sane way I have found is to set the window name via window.open.</p>

<p>Client:</p>

<div class="CodeRay">
  <div class="code"><pre>var w = window.open(&quot;list.html&quot;, &quot;some data&quot;);</pre></div>
</div>


<p>Service:</p>

<div class="CodeRay">
  <div class="code"><pre>window.onload = function () {  alert(window.name); };</pre></div>
</div>


<p>Now that we can pass data between the windows, you can quickly imagine that
you stringify a JSON object on open and parse it in the opened window.
 Pretty simple.</p>

<p>The good news is that the work-around works in FF, WebKit and Opera as is,
but not IE.</p>

<p>To get it working with IE, it takes a few of hacks so I thought it best to
document them here.</p>

<p>When you open a window via window.open, the second parameter is the name, in
IE it must only contain [A-Za-z0-9_], this means that you have to base64
encode the JSON object for it to be able to be sent across, but that is not
enough because Base64 encoding can only use certain characters.  Base64 will
also likely include an == at the end, which is not an allowed character.</p>

<p>However, IE doesn&rsquo;t include a btoa and atob function for managing base64, so
you will also need to <a href="http://www.stringify.com/static/js/base64.js">find a library to use</a>.</p>

<p>To encode the data I used the following:</p>

<div class="CodeRay">
  <div class="code"><pre>var winname = window.btoa(
  unescape(
    encodeURIComponent(JSON.stringify(obj))
  )).replace(/=/g, &quot;_&quot;)
var w = window.open(e.target.href, winname);</pre></div>
</div>


<p>To decode the data I used the following:</p>

<div class="CodeRay">
  <div class="code"><pre>var obj = JSON.parse(window.atob(window.name.replace(/_/g, &quot;=&quot;)));</pre></div>
</div>


<p>Pretty hacky, but it seems to work.</p>

<p>As always, if anyone has a better suggestion, or there are any obvious flaws
let me know.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[WebMessaging is broken]]></title>
    <link href="http://paul.kinlan.me/webmessaging-is-broken/"/>
    <updated>2011-06-21T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/webmessaging-is-broken</id>
    <content type="html"><![CDATA[<p>I have been working on a rather cool project recently that initially used a
lot of <a href="http://www.w3.org/TR/webmessaging/">WebMessaging</a> (postMessage etc)
to talk between all the components.  However, even though these API&rsquo;s look
simple and easy to grok there are some bizaare limitations and usage of them
is frustrating to say the least.</p>

<p>Ignoring the fact that Chrome passes structured clones, and Firefox passes
strings, that is a simple difference to resolve.  It is not even the fact
that WebKit supports MessageChannels and Entangled Ports and no one else
seems too.  These we can work around in sane ways.</p>

<p>The normal developers flow is as follows: open a window/iframe, get a
reference to that window, send it a message, have the frame or window handle
the message.</p>

<p>Client App:</p>

<div class="CodeRay">
  <div class="code"><pre>var w = window.open(&quot;test.html&quot;);
w.postMessage({ data: &quot;some more data&quot;}, &quot;*&quot;);</pre></div>
</div>


<p>Service App: test.html</p>

<div class="CodeRay">
  <div class="code"><pre>window.addEventListener(&quot;message&quot;, function(e) {
  // Do something with the data
}, false);</pre></div>
</div>


<p>This would be pretty simple and intuitive, something that nearly every
developer would be able to pick up in an instant.  But this isn&rsquo;t the case,
if you want to send a window a message you have to wait for it to load &ndash;
which might be a logical assumption, but given that if the page you are
opening is outside the origin of the opener, you can&rsquo;t easily tell when it
loads.  So the current solution is on the host page to postMessage back to
the window.opener, and for the opener to handle the message.</p>

<p>Client App:</p>

<div class="CodeRay">
  <div class="code"><pre>var w = window.open(&quot;test.html&quot;);
window.addEventListener(&quot;message&quot;, function(e) {
    if(e.data.state &amp;&amp; e.data.state != &quot;ready&quot;) return; // do nothing.
    // Send data
    e.source.postMessage({ data: &quot;some more data&quot;}, e.origin);
}, false);</pre></div>
</div>


<p>Service App: test.html</p>

<div class="CodeRay">
  <div class="code"><pre>window.addEventListener(&quot;load&quot;, function(e) {
    // tell the opener that it is ready to receive messages
    e.source.postMessage({ state: &quot;ready&quot; }, e.origin);
}, false);

window.addEventListener(&quot;message&quot;, function(e) {
    // Process data from opening window.
}, false);</pre></div>
</div>


<p>This is bonkers! Developers just want it to work.</p>

<p>There is a hack that allows you pass data to a window so that it is
available to the window as soon as the script starts executing.  It is
probably not safe nor is it likely to be secure.  When you open a window,
you can pass it data immediately using the name parameter on window.open()</p>

<div class="CodeRay">
  <div class="code"><pre>window.open(&quot;test.html&quot;, &quot;{ data: 'ABC123' }&quot;);</pre></div>
</div>


<p>And then on the opening page, you can read it back.</p>

<div class="CodeRay">
  <div class="code"><pre>var data = JSON.parse(window.name);</pre></div>
</div>


<p>There are problems here though:</p>

<ul>
<li> We have no real proof of where the data came from, we can check
window.opener but that is not enough</li>
<li> We have to ensure that the window.name is cleared down as soon as we
parse it, because it will be available for the life time of the application.</li>
</ul>


<p>This is a quick hack, that allows the opened window to read the data that
was passed to it as soon as it opened.</p>

<p>What are your thoughts?  Have you come across these limitations?  Have you
solved them in any other interesting ways?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Landing my first WebKit patch. OnPopState Lock and Load.]]></title>
    <link href="http://paul.kinlan.me/landing-my-first-webkit-patch-onpopstate-lock/"/>
    <updated>2011-06-07T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/landing-my-first-webkit-patch-onpopstate-lock</id>
    <content type="html"><![CDATA[<p>This is a story all about how my life got flipped turned upside down&hellip;..
wait what?!?! I can&rsquo;t start a blog post with The Fresh Prince.</p>

<p>Last week, when I was still in my 20&rsquo;s, I wrote a blog post about HTML5
History API <a href="http://paul.kinlan.me/html5-history-needs-another-event">needing a new event</a>.  This came about
because the <a href="http://github.com/PaulKinlan/leviroutes">LeviRoutes</a> framework
would work better if it could understand when state had been pushed via
History.pushState.  Whilst investigating pushState and adding some tests to
the LeviRoutes framework I wanted to be able to simulate an &ldquo;onpopstate&rdquo;
event.</p>

<p>Let&rsquo;s just quickly digress with a little bit about HTML DOM events.  HTML
defines a rich series of events that are fired when a user clicks on
something, the page loads or&hellip;.. well let&rsquo;s just say there are hundreds of
events.  Not only do the events get triggered when the user or system does
something, but the developer can easily <a href="http://www.w3.org/TR/2001/WD-DOM-Level-3-Events-20010823/events.html#Events-document">simulate events</a>.
 If you want to click on a button via script.  Simple:</p>

<div class="CodeRay">
  <div class="code"><pre>var evt = document.createEvent(&quot;MouseEvent&quot;);
var anchor = document.getElementById(......);
evt.initMouseEvent(&quot;click&quot;, true, true, window, 0, 0, 0, 0, 0, false,</pre></div>
</div>


<p>false, false, false, 0, null);</p>

<div class="CodeRay">
  <div class="code"><pre>anchor.dispatchEvent(evt);</pre></div>
</div>


<p>Why is this programatic dispatch important? You can build individual tests
that are responsive to the events that would fire to user events without
having to build a system that tries to automate the UI by say, managing the
mouse pointer through hardware control.</p>

<p>Digressions aside, I was building tests that would test my HTML5 History
handling logic without me having to physically invoke a History.pushState
command.  In summary, separating the physical navigation from my logic.</p>

<div class="CodeRay">
  <div class="code"><pre>var evt = document.createEvent(&quot;PopStateEvent&quot;);
evt.initPopStateEvent(&quot;popstate&quot;.....);
window.dispatchEvent(evt);</pre></div>
</div>


<p> This should have worked.  Instead all I got was:</p>

<div class="CodeRay">
  <div class="code"><pre>var evt = document.createEvent(&quot;PopStateEvent&quot;);
DOMException</pre></div>
</div>


<p>Which if you read the <a href="http://www.w3.org/TR/2001/WD-DOM-Level-3-Events-20010823/events.html#Events-DocumentEvent">Event specification</a>
is what occurs when an Event type is not implemented.  I quickly jumped
across to Firefox and tested the same code.  It worked.  So it must be a bug
in WebKit.</p>

<p>Now, this is where my real story starts, and what I hope will demonstrate
the power of Open Source software.</p>

<p>I was in a bind. I could raise a bug and hope someone might pick it up at
some point in the future, or I could raise a bug and try to fix it myself.
 I chose the latter.  I didn&rsquo;t think it would be hard &ndash; after all the Event
system is already in WebKit and PopStateEvent is already implemented, it is
only the hookup with createEvent that didn&rsquo;t.</p>

<p>Where do you start?  I started by <a href="http://www.webkit.org/building/checkout.html">downloading the latest WebKit code</a> and <a href="http://www.webkit.org/building/build.html">building it</a>.  In all this process took longer
than the actual fix.</p>

<p>Once I had a build, I decided to create a very simple test case to prove
that it is still broken.  With this in hand, I had a quick peek at the
Webkit code.  Google Code search is your friend here, I just searched for
&ldquo;<a href="http://www.google.com/codesearch?q=PopStateEvent&amp;exact_package=chromium&amp;hl=undefined&amp;vert=chromium">PopStateEvent</a>&rdquo;
and it returned a list of important places to look.</p>

<p>Inspecting PopStateEvent.cpp and PopStateEvent.h, I could see that there was
a create and initPopStateEvent methods so I was pretty sure I was in the
roughly the correct place.  I also knew that createEvent is on the document
object in the DOM, so I did a quick search for <a href="http://www.google.com/codesearch?q=createEvent&amp;exact_package=chromium&amp;hl=en&amp;vert=chromium">createEvent</a>
and there was a file called &ldquo;Document.cpp&rdquo;, this looked promising.  A quick
search in <a href="http://www.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/third_party/WebKit/Source/WebCore/dom/Document.cpp&amp;q=createEvent&amp;exact_package=chromium&amp;sa=N&amp;cd=8&amp;ct=rc">Document.cpp</a>
highlighted the area where the events are created, and there was a
suspicious lack of PopStateEvent.</p>

<p>Bingo!</p>

<p>I quickly raised a bug, on <a href="http://bugs.webkit.org/">http://bugs.webkit.org/</a> detailing the error with
a simple test case attached, and then went about fixing the code.  Raising
the bug seemed to take longer than the fix, which amounted to adding in a
condition for the type of event, adding in a parameterless constructor and
then calling it.</p>

<p>Pretty quick.  My own test case passed, so I had a strong indication that it
was fixed, but I knew if I submitted it without an automated test it would
probably get rejected.  The problem is that I had no idea how to build the
automated tests or where to put them.</p>

<p>I had a quick scan through LayoutTests, and in the &ldquo;fast&rdquo; directory there is
an &ldquo;events&rdquo; directory which seemed liked the logical place to start.  I
followed the examples of other tests, I created a simple test and an
&ldquo;expected&rdquo; results file and then gave the test runner a go.  Boom! it
failed. It took a little bit of looking, I found that the results of the
test run were stored in &ldquo;/tmp/layout-test-results/results.html&rdquo; and it gives
you a visual diff of the actual output vs the expected &ndash; it was a single new
line character that was causing the problem.</p>

<p>That was me done. I created the ChangeLog and attached it <a href="https://bugs.webkit.org/show_bug.cgi?id=62099">to the bug</a>, set r to ? (this was an
oddity that I had to learn about).  After the first review there were a
couple of changes I needed to make.  The second review indicated that I
updated the wrong ChangeLog and some other smallish issues.  But after that
it was ok and submitted.</p>

<p>And here it is: <a href="http://trac.webkit.org/changeset/88187">http://trac.webkit.org/changeset/88187</a>, it is not a complex
fix but it is one I am proud of, if all the ports include the fix then my
code will be used by the eleventy billion users of WebKit (ok &ndash; I have no
idea of the number of users, but I know it is very large number) and now I
can get on with fixing my LeviRoutes framework ;)</p>

<p>In my eyes, this is one of the powers of Open Source.  Rather than just
report a bug and hope someone picks it up, and then wait for the next major
release of the software to see if it is fixed, I have the power to go in and
fix the problem, and if it stands up to muster I can get the solution
published.</p>

<p>Beautiful!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[HTML5 History needs another event]]></title>
    <link href="http://paul.kinlan.me/html5-history-needs-another-event/"/>
    <updated>2011-05-31T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/html5-history-needs-another-event</id>
    <content type="html"><![CDATA[<p>I love the HTML5 History API, it makes developing applications
with a consistent URL scheme across server and client super simple, however
it doesn&rsquo;t come without its problems.</p>

<p>When developing the <a href="https://github.com/PaulKinlan/leviroutes">LeviRoutes URL routing</a> framework it
became obvious that we need some changes to the specification as-is.
The <a href="https://developer.mozilla.org/en/DOM/window.onpopstate">Mozilla documentation</a> reports that
onpopstate is called whenever the history object
changes, unfortunately this is not the case, and is not the case with the
spec either, the <a href="http://www.w3.org/TR/html5/history.html#event-popstate">HTML5 Spec</a>
indicates:
&ldquo;The popstate event is fired in certain cases when navigating to a session
history entry.&rdquo;, which you can logically assume to be only on a forward,
backwards navigation, not a replaceState or pushState.</p>

<p>This might sound odd.  There is no mechanism to detect change in url
<em>after</em>it changes.  You get notification via onpopstate when the user
navigates
forwards or backwards through your application, but not actually when it
changes.  This is apposed to onhashchange which does fire when the document
fragment changes.</p>

<p>This causes us problems.</p>

<p>LeviRoutes listens to changes in your URL, it allows you to build
applications that are responsive to the current URL, and are decoupled from
navigation.  So rather than have your code littered with &ldquo;if(url == &rdquo;/&ldquo;) {
doA(); } if (url == &rdquo;/categories&#8221;) { doB(); } you can now specify:</p>

<div class="CodeRay">
  <div class="code"><pre>var app = routes();
app.get(&quot;/&quot;, doA);
app.get(&quot;/categories&quot;, doB);</pre></div>
</div>


<p>Simple right?</p>

<p>It would be excellent if it was that simple, but it is not.  We don&rsquo;t know
when the URL changes via pushState.  This forces us o bind our logic in our
controller to call the same code that LeviRoutes would call when it detects
a change in URL via normal navigation.</p>

<p>Now I have to bastardise my code:</p>

<div class="CodeRay">
  <div class="code"><pre>var app = routes();
app.get(&quot;/&quot;, doA);
app.get(&quot;/categories&quot;, doB);

.....
function gotoA () {
    history.pushState({}, &quot;A&quot;, /);
    doA();
}
...</pre></div>
</div>


<p>Pretty messy right?</p>

<p>I would love to see an event &ldquo;onstatechanged&rdquo; (or perhaps, onpushstate and
onreplacestate) triggered when the user pushes or replaces state on to the
history object so that I can capture the code and return to my simple
routing logic.</p>

<div class="CodeRay">
  <div class="code"><pre>var app = routes();
app.get(&quot;/&quot;, doA);
app.get(&quot;/categories&quot;, doB);

function gotoA () {
    history.pushState({}, &quot;A&quot;, /);
}</pre></div>
</div>


<p>I am not the only person asking for this:
<a href="http://www.google.com/search?q=onpushstate">http://www.google.com/search?q=onpushstate</a></p>

<p>So, how am I going to solve this problem?  I am going to wrap the History
API and proxy pushState to call the natural pushState and also fire a new
custom event.  Hmph :\</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[When are we going to see the death of SVG?]]></title>
    <link href="http://paul.kinlan.me/when-are-we-going-to-see-the-death-of-svg-/"/>
    <updated>2011-05-17T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/when-are-we-going-to-see-the-death-of-svg-</id>
    <content type="html"><![CDATA[<p>I have this bizarre mixed feelings about SVG, I loathe it and love it at the same time (according to urban dictionary the word is <a href="http://www.urbandictionary.com/define.php?term=loave&amp;defid=4855182">loave</a>) and I hate myself for it - okay, hate is a strong word.</p>
<p />
<div>I constantly feel frustrated by its complexity, requirement for tooling (have you tried to create a path by hand) and half-arsed integration into the web of today. &nbsp;I see the &lt;svg&gt; element much like I see the &lt;object&gt; tag, that is a boundary that rarely if ever should be crossed by mere mortals, a semi-permeable barrier where only through reverse osmosis can we wrangle some of the elements in our usermode. (to be read as, we can script it and hook it up in our app but that is about it).</div>
<p />
<div>The way I see it, once you get in to &lt;svg&gt; it is like a context switch, the HTML DOM and the SVG DOM will never really truly mingle.</div>
<p />
<div>But SVG has some serious awesomeness too - for one it is scaleable, two is vector based&#8230;. can you guess the third? &nbsp;It has awesome graphical capabilities, you&#8217;ve seen the filters right and paths? There have been lots of project that I have worked on where I simply can&#8217;t build what I want because it is not available in the &#8220;web&#8221; sans SVG. &nbsp;I want to be able to apply filters with out importing a SVG declaration, I want to be able flow elements out along a path.</div>
<p />
<div>Why can&#8217;t path be a css property?</div>
<p />
<div>p {</div>
<div>&nbsp; display: svg; /* <a href="http://www.w3.org/1999/08/WD-SVG-19990812/styling.html">http://www.w3.org/1999/08/WD-SVG-19990812/styling.html</a> */</div>
<div>&nbsp; path:&nbsp;&#8220;M 100 100 L 300 100 L 200 300 z&#8221;;</div>
<div>}</div>
<p />
<div>Text inside the &lt;p&gt; will be rendered along the path. &nbsp;But what if &lt;p&gt; was a block element like a &lt;div&gt;? &nbsp;Even better all elements be they block or inline will be rendered along the path&#8230;&#8230; That is powerful!</div>
<p />
<div>For me this is better than what we have now. I don&#8217;t want to have to have &lt;p&gt;&lt;svg&gt;&#8230;&#8230;&lt;/svg&gt;&lt;/p&gt; when I want to do something awesome that SVG lets me do, that just doesn&#8217;t <em>scale.</em></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[App Cache and HTML5 History]]></title>
    <link href="http://paul.kinlan.me/app-cache-and-html5-history/"/>
    <updated>2011-05-17T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/app-cache-and-html5-history</id>
    <content type="html"><![CDATA[Whilst developing our latest app (<a href="https://github.com/PaulKinlan/ioreader">https://github.com/PaulKinlan/ioreader</a>) for a Google IO, we ran into several large is limitations with AppCache and HTML5 History that I wanted to share (and at somepoint hopefully solve).  <p /><div>Putting the current discussion of the issues with AppCache aside for a couple of minutes, there is no provision in HTML5 History to include pages &quot;pushStated&quot; into the current App Cache Group<p /> </div><div>Consider this flow:  We have a multi paged app with pages A and B when rendered from the server sharing the same AppCache and thus in the same group.<br /><ul><li>User visits page A, it uses an app cache, so everything is cached.</li> <li>User navigates from A to B, page B is added to the app cache group.</li><li>User goes offline</li><li>User refreshes A it is served from the Cache,  User refreshes B, it is served from the Cache.</li></ul><br />Update the AppCache, A and B are re-downloaded and cached [see: Death by App Cache].</div> <div><br />Now if we inject HTML5 History for the same flow:<br /><ul><li>User visits page A, it uses an app cache, so everything is cached.</li><li>User navigates from A to B (via pushState) &#8230;..  currently B is not added to the App Cache group.</li> <li>User goes offline</li><li>User refreshes A it is served from the Cache,  User refreshes B, fail, because not in the Cache.</li></ul>I believe that as URL&#39;s change if the master page is App Cached, the new URL&#39;s should be added to the App Cache group.  You are still in the same application, the state is just dynamically changed but in essence you are on a page that should be available offline.  The act of changing the URL client-side normally enforces you to generate the correct content on the server if the page was simple fetched. <div> <br />Death by App Cache: The problem that we also faced was as master entries are added to an App Cache group, when an update to the App Cache occurs, all those pages in the App Cache are refreshed, with more dynamic applications this could mean that 10&#39;s or 100&#39;s of pages are quickly downloaded by the App Cache software and thus can quickly cause a mini DDOS.<div> <br />I am interested to hear your thoughts.</div></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[IO Question: How long did it take to develop the app? #io2011]]></title>
    <link href="http://paul.kinlan.me/io-question-how-long-did-it-take-to-develop-t/"/>
    <updated>2011-05-14T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/io-question-how-long-did-it-take-to-develop-t</id>
    <content type="html"><![CDATA[One of the many question that we didn&#39;t get to answer in our talk - <a href="http://io2011-zerotohero.appspot.com/index.html">Mobile web development: Zero to Hero</a> - is &quot;<a href="http://goo.gl/mod/OuwY">How long did it take to develop the app</a>?&quot;.  Luckily, we have an answer: The first commit of the project was on the <a href="https://github.com/PaulKinlan/ioreader/commit/a42daa85023fb278dc98fb0201555e300b1eb552">3rd of March</a>, but that was mainly just a simple README file, the first commit of the server was <a href="https://github.com/PaulKinlan/ioreader/commit/b96a5f217a042ea4610972bc1bcbf227b73b6a65">25th of March</a> which is when we really started working on the code and began taking our ideas and basic concepts into a fully fledged solution<p /><div>You might think that just over a months worth of work went into this (it was, in theory), but it is a little more complex than that.  We developed 2 frameworks, <a href="https://github.com/PaulKinlan/leviroutes">LeviRoutes</a> and <a href="https://github.com/PaulKinlan/formfactor">FormfactorJS</a> and allowed us to push a lot of the common logic into a single controller.  <a href="http://io2011-zerotohero.appspot.com/index.html#36">Using FormfactorJS</a> it was possible to assign engineers to each distinct UI and have them work on it in isolation.  FormfactorJS was used to specialize the base controller that was in every single page.  If you look in our &quot;<a href="https://github.com/PaulKinlan/ioreader/tree/master/client/scripts">scripts</a>&quot; directory, you can see how we structured the project - <a href="https://github.com/PaulKinlan/ioreader/blob/master/client/scripts/controller.js">controller.js</a> is common across all interfaces, <a href="https://github.com/PaulKinlan/ioreader/blob/master/client/scripts/desktop/controller.js">desktop/controller.js</a> is then dynamically injected at run-time and using <a href="http://javascript.crockford.com/prototypal.html">prototypal inheritance</a> we added custom formfactor specific features (such as swipe detection in the case of tablet and mobile)</div> <p /><div>In total we had <a href="http://io2011-zerotohero.appspot.com/index.html#75">4 engineers working on the project</a>, each working on their own UI.  Each engineer spent roughly 20% of their time developing the parts of the UI that they were responsible for.</div> <p /><div>In all, it took just over a month of man effort to develop this application.</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[IO Question: WebSQL is dead or dieing, IndexedDB isn't there yet, what do you think about libraries like Lawnchair?]]></title>
    <link href="http://paul.kinlan.me/io-question-websql-is-dead-or-dieing-indexedd/"/>
    <updated>2011-05-13T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/io-question-websql-is-dead-or-dieing-indexedd</id>
    <content type="html"><![CDATA[A <a href="http://goo.gl/mod/VrlF">question</a> in our IO Talk: <a href="http://io2011-zerotohero.appspot.com/index.html#1">Mobile Web Development: From Zero to Hero</a> was with regards <p /><div>I will say this, I love LawnChair - I have used it a couple of times and it makes getting data in and out of your application very easy, it is based on the premis that you need to store objects against a key, and then get it out again, it allows you to use a richer querying syntax, but in many cases (as with our <a href="https://github.com/PaulKinlan/ioreader">IO Reader</a> app) you don&#39;t need anything more complex.</div> <p /><div>As to why I didn&#39;t use LawnChair (or any other wrapper) in IO Reader? I actually added the data caching layer later on in the project cycle, localStorage was supported well enough and I didn&#39;t want to introduce a new dependency in the code that late on.</div> <p /><div>As a developer that likes to get things done, I very rarely write code that will manipulate a given data source directly, instead I either use a project like LawnChair, or I use a simple wrapper that I have written that allows for flexible querying semantics on JSON based objects.</div> <p /><div>I am keen to hear your thoughts.  What are your favorite DataStore wrappers for Web apps?  Do you write to the bare metal?</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[IO Question: How are you dealing with AppCache relatively small storage limits?]]></title>
    <link href="http://paul.kinlan.me/io-question-how-are-you-dealing-with-appcache/"/>
    <updated>2011-05-13T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/io-question-how-are-you-dealing-with-appcache</id>
    <content type="html"><![CDATA[We had an <a href="http://goo.gl/mod/NSEW">awesome question</a> for our Google IO talk - <a href="http://io2011-zerotohero.appspot.com/index.html#1">Mobile Web Development: Zero to Hero</a> - that we didn&#39;t get time to answer live.<p /><div>How do we deal with the storage constraints imposed by modern browsers.  The answer is simple, App Cache is used mainly to store program code, that is just the CSS and JS (and also the page that requests the AppCache), our application never got that large.</div> <p /><div>We did make some basic optimisations, our production version ran compressed JS code - our <a href="https://github.com/PaulKinlan/ioreader/raw/master/run.sh">build process minified the JS</a> using uglifyJS.  We had the option to compress the CSS (but we chose not too for ease of development).  But in all honesty, our application never got that large.</div> <p /><div>If we struggled for space we would have moved into only AppCaching the form-factor specific code and assets, but it wasn&#39;t required.</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Google IO Q: Would one build a different HTML 5 app for keyboard devices and mobile (touch) devices? Why or why not?]]></title>
    <link href="http://paul.kinlan.me/google-io-q-would-one-build-a-different-html-/"/>
    <updated>2011-05-13T00:00:00+01:00</updated>
    <id>http://paul.kinlan.me/google-io-q-would-one-build-a-different-html-</id>
    <content type="html"><![CDATA[<a href="http://goo.gl/mod/871w">Another question</a> that we didn&#39;t get to answer in our talk - <a href="http://io2011-zerotohero.appspot.com/index.html#1">Mobile web development: Zero to Hero</a> - is basically the premis of the entire talk.  We believe that in a large number of cases that it is entirely possible to build applications using one semantic document structure, a large swathe of common core logic whilst specializing for a given formfactor.  <p /><div>From our talk, you can see that the User Interface is optimised for smartphone, tablet, desktop and TV - we believe that there are qualitatively different user interaction patterns in each form that it is important that you optimise for the different experiences, but for the developer experience it is not easy (or possible in some cases) to keep having to build one new app for each category of device that you want to target.</div> <p /><div><a href="http://io2011-zerotohero.appspot.com/index.html#30">Slides 30 to 41</a> describe how we came to solve this problem for our app.  The important code in our application is the <a href="https://github.com/PaulKinlan/ioreader/blob/master/server/client/scripts/controller.js">base controller</a> that describes all the common logic across all instances of our app, and then the form-factor specific <a href="https://github.com/PaulKinlan/ioreader/blob/master/server/client/scripts/desktop/controller.js">desktop</a> code or the <a href="https://github.com/PaulKinlan/ioreader/blob/master/server/client/scripts/phone/controller.js">smartphone</a> code that is injected in using the <a href="https://github.com/PaulKinlan/formfactor">FormfactorJS</a> library via our <a href="https://github.com/PaulKinlan/ioreader/blob/master/server/client/scripts/uis.js">UI detection code</a>.</div> <p /><div>It must be noted, that a lot of tablet based apps work quite well on desktop devices, there are some unique differences that I can see from usage between the two.  For example, lots of touch based tablet apps are built with horizontal scrolling as the primary mechanism for finding new content (think the NPR app, where you scroll left and right to find new stories), whilst on the desktop, many users appear to prefer the vertical scrolling of columns of data.  This I believe is because it is more natural to swipe left and right with your finger, whilst it is easier to use your mouse scroll wheel on your desktop; this pattern for design was one that I explicitly made in the Desktop version of <a href="https://github.com/PaulKinlan/ioreader">IO Reader</a>.</div> <p /><div>What are your experiences of developing for multiple formfactors?  I would love to hear them, and your thoughts on runtime form-factor detection.</div>
]]></content>
  </entry>
  
</feed>
