<?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>James Pearce</title>
	<atom:link href="http://tripleodeon.com/feed/?wpmp_switcher=desktop" rel="self" type="application/rss+xml" />
	<link>http://tripleodeon.com</link>
	<description>Living the mobile dream</description>
	<lastBuildDate>Mon, 14 May 2012 18:48:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
<cloud domain='tripleodeon.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>Moving on</title>
		<link>http://tripleodeon.com/2011/12/moving-on/</link>
		<comments>http://tripleodeon.com/2011/12/moving-on/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 14:00:19 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=697</guid>
		<description><![CDATA[Friday is my last day at Sencha. It&#8217;s been a great company to work for, with smart people, valuable products and a vibrant community. It&#8217;s not too much to say we&#8217;ve really led this year&#8217;s growth of interest in mobile web applications, HTML5, CSS3, and JavaScript. But for me, a new challenge. As of Monday, [...]]]></description>
			<content:encoded><![CDATA[<p>Friday is my last day at <a href="http://www.sencha.com/">Sencha</a>.<br />
<span id="more-697"></span><br />
It&#8217;s been a great company to work for, with smart people, valuable products and a vibrant community. It&#8217;s not too much to say we&#8217;ve really led this year&#8217;s growth of interest in mobile web applications, HTML5, CSS3, and JavaScript.</p>
<p>But for me, a new challenge. As of Monday, I&#8217;ll be Head of Mobile Developer Relations at Facebook.</p>
<p>Not much to say right now &#8211; I have a six-week <a href="https://www.facebook.com/note.php?note_id=177577963919">bootcamp</a> to get through &#8211; but it&#8217;s probably sufficient to say the company also has a few interesting ambitions in mobile.</p>
<p>So, thank you Sencha, for a brilliant experience. And hello Facebook: let&#8217;s see what we can do.</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2011/12/moving-on/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>First, Understand Your Screen</title>
		<link>http://tripleodeon.com/2011/12/first-understand-your-screen/</link>
		<comments>http://tripleodeon.com/2011/12/first-understand-your-screen/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 18:04:38 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mobile Web]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=671</guid>
		<description><![CDATA[I unashamedly maintain that there is so much more to being successful on the mobile web than dealing with screen size. But I do accept that dealing with screen size is at least a first step. Thank goodness then, that the matter of screen size is so simple and well understood. Really? As web developers, [...]]]></description>
			<content:encoded><![CDATA[<p>I unashamedly maintain that there is so much more to being successful on the mobile web than dealing with screen size. But I do accept that dealing with screen size is at least a first step.</p>
<p>Thank goodness then, that the matter of screen size is so simple and well understood.<br />
<span id="more-671"></span></p>
<p><strong>Really?</strong></p>
<p>As web developers, we will often need to know the screen size of the device we are displaying content on. Perhaps on the server, perhaps on the client, perhaps to be used as a clause in a media query.</p>
<p>But how best to measure it? And what are we measuring anyway? On the client-side, for instance, a variety of ways exist to determine screen and page size: things like <code>screen.width</code>, <code>window.outerWidth</code>, <code>document.body.clientWidth</code>, and so on. But these properties are infamously unspecified by any standards: so what do they all mean &#8211; and <strong>how reliable are they on mobile browsers</strong>?</p>
<p>Required reading at this point is <a href='http://www.quirksmode.org/mobile/tableViewport.html'>PPK&#8217;s viewport article</a>. With an article of tables from him that long, you know something&#8217;s up.</p>
<p>But last week <a href='http://www.sencha.com/blog/sencha-io-src-update/'>I pushed out an update to src.sencha.io</a> which allows client-side screen size parameters. Which parameters should mobile developers use? And when?</p>
<p><a target='table' href="/wp-content/uploads/2011/12/table.html"><img src="/wp-content/uploads/2011/12/table-248x173.png" alt="" title="table" width="248" height="173" class="alignright size-medium wp-image-683" style='margin-bottom:2em;border:1px solid #ccc' /></a></p>
<p>So for this blog post, I looked at a range of these metrics, and recorded their values for a variety of mobile browsers and page conditions. I&#8217;ve been working in mobile for far too long, but still, the amount of diversity in the results shocked me. Read on for the gory details, or skip to the end for the TLDR. I think there are some interesting findings.</p>
<h2>Methodology</h2>
<p>The tests comprised a very simple web page, containing several paragraphs of meaningless Latin, and a JavaScript function that runs to take screen measurements within the browser. The following properties are sought:</p>
<ul>
<li><code>screen.width</code></li>
<li><code>screen.availWidth</code></li>
<li><code>window.outerWidth</code></li>
<li><code>window.innerWidth</code></li>
<li><code>document.body.clientWidth</code></li>
<li><code>document.body.offsetWidth</code></li>
<li><code>@media device-width</code></li>
<li><code>@media width</code></li>
</ul>
<ul>
<li><code>screen.height</code></li>
<li><code>screen.availHeight</code></li>
<li><code>window.outerHeight</code></li>
<li><code>window.innerHeight</code></li>
<li><code>document.body.clientHeight</code></li>
<li><code>document.body.offsetHeight</code></li>
<li><code>@media device-height</code></li>
<li><code>@media height</code></li>
</ul>
<ul>
<li><code>window.orientation</code></li>
<li><code>@media orientation</code></li>
</ul>
<p>The CSS media query properties (<code>device-width</code>, <code>orientation</code>, etc) are taken programmatically by evaluating expressions with the <code>matchMedia()</code> function, supported in iOS v5.0 and Android v4.0.</p>
<p>I&#8217;m sorry to say that the tests were run on emulators rather than real devices, but covered iPhone (iOS v5.0 and iOS v4.3), Android v2.3, Android v4.0, and Opera Mobile v11.0. The Android and Opera simulators were set to use HVGA (320×480) so as to have conditions as consistent with the iPhone as possible. (Even though the actual physical screen of a retina iPhone is 640×960, this HVGA resolution is the one reported to the software APIs).</p>
<p>The tests were run with two different HTML document types &#8211; HTML5 and XHTML-MP &#8211; and also a third time with no doctype specified. The tests were also run both with and without a viewport meta tag to control the default width (constrained to &#8216;<code>device-width</code>&#8216;) and scaling. Additionally each device was tested with landscape as well as portrait orientation &#8211; making a total of 12 test combinations for each browser.</p>
<p>For the iPhone and Android browsers, PhoneGap-wrapped versions of the test pages were also run (without the viewport meta tag), and finally, for iOS v5.0, the iPhone&#8217;s &#8216;Add to Homescreen&#8217; technique was used (with the <code>apple-mobile-web-app-capable</code> meta tag) to launch portrait versions of the tests in a full-screen mode.</p>
<p>As if all those combinations were not enough, the properties were accessed four times during the lifecycle of the page: a) inline before the <code>&lt;body&gt;</code> tag, b) after the <code>&lt;/body&gt;</code> tag, c) on the document&#8217;s load event, and d) one more time, 250ms later. I had a hunch that the values &#8211; at least those relating to page height &#8211; might change throughout this lifecycle.</p>
<h2>Results</h2>
<p>The full set of results is available <a target='table' href="/wp-content/uploads/2011/12/table.html">here</a>. The various combinations of conditions are across the top, and operating systems (and measurements made) are down the left. Each cell shows the value returned from the relevant API call, and &#8216;<code>-</code>&#8216; is used where the call failed or returned an undefined value.</p>
<p>Where the value changed during the lifecycle of the page, slashes delimit the change, and a letter is used to indicate at which of the four measuring points the value changed. So for example, &#8216;<code>208/c:1962</code>&#8216; means that a value was 208 before the <code>&lt;body&gt;</code> and after the <code>&lt;/body&gt;</code>, but then it changed to 1962 for &#8216;c&#8217;, the document&#8217;s load event, and remained so 250ms later.</p>
<p>There&#8217;s a lot to digest in there, although you may at least have noticed &#8211; as I have &#8211; that homogeneity is scarce. You may notice some particularly strange results, particularly on Android, but also on iOS and Opera. Let&#8217;s analyze the data by slicing the findings by property measured, dicing by operating system, and trying to digest the whole sorry lot.</p>
<h2>Analysis</h2>
<h3><code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=screen.width&#038;c=">screen.width</a></code> &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=screen.height&#038;c=">.height</a></code></h3>
<p>These two properties are generally understood to return the physical dimensions of the screen upon which a browser is running. On desktop browsers, they will return you 1024×768, 1440×900, 1600×1200 and so on, regardless of how the actual browser window is sized. On mobile devices, one would expect the same behavior, and get full physical screen sizes.</p>
<p>Well, close. But no cigar.</p>
<p><a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11screen.w&#038;c=">Opera Mobile</a> and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40screen.w&#038;c=">Android v4.0</a> (as well as <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.w&#038;c=phone">v2.3 in a PhoneGap app</a>) behave most intuitively in this regard, and will indeed report 320×480 or 480×320 for portrait and landscape respectively.</p>
<p><a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50screen.w&#038;c=">iOS</a> also consistently reports the physical dimensions of the screen (320×480), but notably fails to flip them for a change or orientation. So be aware that in landscape mode, your browser&#8217;s width will actually, apparently, be reported to be larger than the screen&#8217;s.</p>
<p>Android v2.3, in a regular browser scenario, however, displays even more curious behavior. Its <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.w&#038;c="><code>screen.width</code></a> always starts off as 800 &#8211; which is clearly some sort of virtual viewport, rather than the physical screen. But when the document has an XHTML-MP doctype, or a constrained viewport (for any doctype), the <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.w&#038;c=:">value will switch</a>, by the time of the document load event, to be the 320 or 480 you might expect.</p>
<p>Now this might be tolerable if you remember to wait for documents to fully load before accessing this property, but even that caution is blown to the wind by <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=">Android v2.3&#8242;s <code>screen.height</code></a> behavior.</p>
<p>With a non-constrained viewport, a portrait orientation, and with no doctype, screen.height was reported during this test as <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=>1003<">1003</a>. With an HTML5 doctype, it also switched to 1003, but only after <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=498/d:1003">dallying at 498</a> until at some point <em>after</em> the document load event. With an XHTML-MP doctype, it also started out at 498, but <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=498/c:199">then dropped</a> to about 40% of that value (199) by the time of the document load. With a constrained viewport, behavior was stable as a function of doctype, but also demonstrated the 60% drop at document load: from <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=1003/c:401">1003 down to 401</a>.</p>
<p>Landscape-wise, the same sort of issues occur: with no doctype, screen.height is a <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=>402<">reliable 402</a>; and with an HTML5 doctype, the same value is also (<a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=372/d:402">eventually</a>) returned. The XHTML-MP doctype, or a constrained viewport, will cause the eventual value to be 241, but by way of <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=241<">various intriguing values</a>. Our constrained, HTML5 document, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=372/c:223/d:241">for example</a>, reported 372 before and after the <code>&lt;body/&gt;</code>, 223 on load, and 241 at some point afterwards.</p>
<p>Yes, these actual values are probably dependent upon the length of my particular test page itself, but remember that these are supposed to be the physical screen dimensions, folks!</p>
<p>Some semblance of normality returns to Android v2.3 in the PhoneGap environment. The <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.h&#038;c=phone">values of 455 and 295</a> are hardly accurate measures of physical screen size, either (since bizarrely they seem to take the 25 pixel status bar into account!), but at least they&#8217;re close, and hooray: take solace that the value does not change during the page lifecycle.</p>
<h3><code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=availWidth&#038;c=">screen.availWidth</a></code> &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=availHeight&#038;c=">.availHeight</a></code></h3>
<p>In the desktop world, the available width and height returned by these two properties still relate to the whole screen, rather than the browser&#8217;s window, but they take operating system chrome into account. The menu bar in OSX means that <code>screen.availHeight</code> is at least 26 pixels less than <code>screen.height</code>, for example &#8211; although the width values will probably be the same (unless you have a non-minimizing dock on the side of the screen).</p>
<p>In mobile, one might expect the available values to take into account any OS status bar height. Let&#8217;s see, shall we?</p>
<p>I need to caveat the Opera results here, since the simulator runs in a dedicated window without any &#8216;real device&#8217; chrome. But that should have implied that its available dimensions are the same as the screen&#8217;s &#8211; and this was not what was seen. In fact, the <code>availHeight</code> <em>is</em> reduced to <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11screen.availheight&#038;c=">369</a> from a height of 480, not by any OS chrome, but by the <em>browser&#8217;s</em> own rather fat chrome. This is not what is expected &#8211; even if, on a real device, it emerges that the OS chrome is deducted too.</p>
<p>And having labored over Android v2.3, above, there&#8217;s not much more to say here about that operating system either. Without exception <em>it</em> depressingly reports exactly the same values for <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.availwidth&#038;c=">availWidth</a></code> and <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.availheight&#038;c=">availHeight</a></code> as it did for width and height &#8211; although at least that means that the PhoneGap values are now correct! Android v4.0&#8242;s browser also reports the same available values as it did for total <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40screen.availwidth&#038;c=">width</a></code> and <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40screen.availheight&#038;c=">height</a></code>, but fortunately they were slightly more sensible to begin with. But bizarrely the PhoneGap app <em><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40screen.availheight&#038;c=phone">doesn&#8217;t</a></em> take the status bar height off as it <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23screen.availheight&#038;c=phone">does</a> for v2.3.</p>
<p>And then there&#8217;s iOS: it <em>does</em> successfully <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50screen.availheight&#038;c=">deduct 20 pixels</a> for the operating system&#8217;s chrome. But remember that orientation is ignored! So although a portrait <code>availHeight</code> is sensibly <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50screen.availheight&#038;c=460">460</a> (having dropped from 480), it is anti-intuitively the <em>width</em> in a landscape orientation that is reduced (from 320 to <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50screen.availwidth&#038;c=300">300</a>) by a bar at the <em>top</em> of the screen!</p>
<p>Quirks on all fronts. Sigh.</p>
<h3><code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=outerwidth&#038;c=">window.outerWidth</a></code> &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=innerwidth&#038;c=">.innerWidth</a></code></h3>
<p>In contrast to the <code>screen</code> properties, the <code>window</code> properties are understood to refer to the browser window itself. For desktop browsers, (at least, when they&#8217;re not running in full-screen mode), the outer dimensions will normally be smaller than those for the screen. The inner dimensions then further deduct browser chrome: window borders, toolbars, status bars, and so on, and so they are normally smaller still.</p>
<p>In mobile, we might expect the outer values to more or less match those for the available screen &#8211; since apps run full size.  And indeed, with <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=outerwidth&#038;c=">window.outerWidth</a></code>, we have a good news story.</p>
<p>iOS v5.0 uses <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerw&#038;c=">window.outerWidth</a></code> to redeem itself over the lack of the orientation&#8217;s effect on screen. It <em>is</em> 320 for portrait viewing, and 480 for landscape viewing. Bam.</p>
<p><a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11window.outerw&#038;c=">Opera</a> does the same. Bam. Astonishingly, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23window.outerw&#038;c=">Android v2.3</a> also nails it. Bam.</p>
<p>In fact, the only small blot that stops <code>window.outerWidth</code> being the model student is <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.outerw&#038;c=land">Android v4.0 in landscape</a>: the property often has the portrait value of 320 before the <code>&lt;body&gt;</code> tag is reached. However, this is arguably an edge case, and a very minor misdemeanor.</p>
<p>After that rousing news, it&#8217;s back to earth with a small bump for <code>window.innerWidth</code>. If your desktop experience had convinced you that <code>innerWidth</code> must be the same or smaller than <code>outerWidth</code>, you&#8217;ve now got the TARDIS-like experience of mobile viewports to enjoy.</p>
<p>Without dropping into classic viewport theory here, it&#8217;s sufficient to say that WebKit mobile browsers seem to use the boundary between the window&#8217;s &#8216;inner&#8217; and &#8216;outer&#8217; width and height properties to delineate the world of physical pixels and the world of viewport pixels: the latter a realm where zooming, pinching and tapping allow the mobile browser to sensibly scale web pages designed for much larger screens.</p>
<p>For those pages where the viewport&#8217;s behavior is constrained, perhaps through the use of meta tags, this is of little concern, since the mapping of the two worlds is 1:1. And indeed, in our tests, when such a tag is present, <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerw&#038;c=">innerWidth</a></code> takes exactly the same value as <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.outerw&#038;c=">outerWidth</a></code> &#8211; modulo the Android race conditions, at least.</p>
<p>Less well-known might be the fact that, for all these browsers, when an XHTML-MP doctype is present, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerw&#038;c=xh">the same is also true</a>. We&#8217;ve alluded to this already: the presence of this forces the viewport width to be the same as the physical width of the screen (either 320 or 480), while still allowing subsequent scaling.</p>
<p>And of course, PhoneGap&#8217;s default configuration is also to constrain the viewport, so the values there <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerw&#038;c=phone">also match</a>.</p>
<p>But when the viewport has <em><a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerw&#038;c=Non-">not</a></em> been constrained, and an <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerw&#038;c=l5">HTML5 doctype</a> (or <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerw&#038;c=none">none at all</a>) is used, <code>innerWidth</code> will suddenly start to represent values much larger than the physical screen: and represent the width of the viewport canvas upon which the page has been rendered.</p>
<p>On a portrait iPhone, for example, the default viewport is <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.innerw&#038;c=980">980</a> pixels. On a landscape iPhone it is, well, according to <code>window.innerWidth</code>, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.innerw&#038;c=981">981</a> (yes, really).</p>
<p>Android 2.3 and earlier used a different value of 800 for the default viewport width, and this is exposed as <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23window.innerw&#038;c=800">window.innerWidth</a></code> (as well as the vestigal value before document load for the constrained tests). With Android 4.0, the default viewport has been brought in line with the iPhone&#8217;s: <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerw&#038;c=980">980 pixels</a>.</p>
<h3><code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=outerh&#038;c=">window.outerHeight</a></code> &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=innerh&#038;c=">.innerHeight</a></code></h3>
<p>Mobile browsers normally have no vertical chrome, so apart from the matter of viewports, <code>outerWidth</code> and <code>innerWidth</code> values corresponded relatively nicely. However, they do have horizontal chrome elements: address bars at top, and toolbars at bottom. So we should expect the height to be reduced accordingly.</p>
<p>Opera, in a way, gets this right. We have already pointed out it surprisingly deducted the browser chrome to calculate its <code>screen.availHeight</code>. But since it then promptly uses the same value for <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11window.outerh&#038;c=">window.outerHeight</a></code> and <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11window.innerh&#038;c=">window.innerHeight</a></code>, it meets our expectations on the latter of these two properties at least.</p>
<p>For Android, <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.outerh&#038;c=">window.outerHeight</a></code> is also relatively deterministic. Again, there are timing wobbles, but after page load, the values are consistently <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.outerh&#038;c=455">455</a> (in portrait) and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.outerh&#038;c=295">295</a> (in landscape). The Android OS bar, as we&#8217;ve mentioned, is 25 pixels.</p>
<p>But it&#8217;s iOS <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=">that baffles</a> this time. Only in homescreen mode, with an HTML5 doctype (or none at all), does the browser report the expected <code>window.outerHeight</code> value of <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=:460">460</a>.</p>
<p>In all other cases, bizarre numbers come out. For iOS v5.0, for constrained portrait pages, it&#8217;s <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=356/c:445">356 that becomes 445</a>. For non-constrained portrait pages it&#8217;s <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=356/c:1602">356 that becomes 1602</a>. For constrained landscape pages it&#8217;s <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=208/c:667">208 that becomes 667</a>. For non-constrained portrait pages it&#8217;s <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=208/c:1702">208 that becomes 1702</a>. In PhoneGap, it&#8217;s <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=460/c:1602">460 that becomes 1602</a>, or <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=480/c:1202">480 that becomes 1202</a>. And for constrained homescreen apps, it&#8217;s <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=480/c:1602">480 that becomes 1602</a>.</p>
<p>The fact that this is the one property whose values significantly vary from <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios43window.outerh&#038;c=">iOS v4.3</a> to <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.outerh&#038;c=">iOS v5.0</a> also raises alarm bells.</p>
<p>Perhaps we could write a whole blog post to reverse engineer is going on here. 356 and 208 seem to have some plausibility, but apart from that &#8211; who knows? There&#8217;s no apparent Safari documentation for this property, and even WebCore&#8217;s own test suite describes the expected results as &#8216;<a href='http://opensource.apple.com/source/WebCore/WebCore-955.66/manual-tests/window-sizing.html'>empirical</a>&#8216;.</p>
<p>I think I can safely caution you never to use <code>window.outerHeight</code> in iOS and expect a meaningful answer.</p>
<p>After that, <code>window.innerHeight</code> seems relatively stable and predictable. In constrained (and XHTML-MP) scenarios in the regular iOS browser, it sits at that familiar <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerh&#038;c=356">356</a> value for portrait and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerh&#038;c=208">208</a> for landscape. This <em>is</em> the actual inner height of the browser window, sans browser chrome, as <a href="http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html#//apple_ref/doc/uid/TP40006509-SW1">per documentation</a>. (The fact that these two values are not the same amount less than the physical screen dimensions is due to the fact that the landscape toolbar is slightly shallower than the portrait one.)</p>
<p>This pattern is also consistent when the page is launched <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerh&#038;c=homescreenportraitconstrain">constrained from the homescreen</a> or in a <a target='table' href="/wp-content/uploads/2011/12/table.html?r=window.innerh&#038;c=phone">PhoneGap</a> application. Here, without any browser chrome at all, the values correctly return to the physical screen dimensions minus the 20 pixel tool bar.</p>
<p>However, this value is not as trustworthy when the page has a non-constrained viewport and an <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.innerh&#038;c=non-constrainedhtml5">HTML5</a> (or <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.innerh&#038;c=non-constrainednone">omitted</a>) doctype. In our test, <code>window.innerHeight</code> had values of 1091 and 425 for the two orientations &#8211; doubtless dependent upon the length of the content in our actual page &#8211; and hard to predict. As if to prove that point, in homescreen mode, this value <em>increases</em> to <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.innerh&#038;c=1409">1409</a>. Not particularly useful.</p>
<p>When we look at <code>window.innerHeight</code> for Android, the results appear to follow a similar pattern, but, as usual, are somewhat obfuscated by the fact they change throughout the page lifecycle. For constrained viewports, the two orientations&#8217; values are <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23window.innerh&#038;c=401">401</a> and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23window.innerh&#038;c=241">241</a> in Android v2.3 (where the address bar is 54 pixels high), and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=403">403</a> and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=243">243</a> in Android v4.0 (where the address bar is 52 pixels high), and the PhoneGap values are also <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=phone">as expected</a>, considering there is no address bar.</p>
<p>But again, the determinism disappears when the viewport is not constrained, the reported values as varied <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=1234">1234</a>, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=496">496</a>, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=1003">1003</a> and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.innerh&#038;c=402">402</a>. We can deduce that these are viewport lengths rather than window size, that they are content-dependent, and that they change between platform versions due to the updated viewport width &#8211; but again, their utility is more doubtful than in the constrained scenarios.</p>
<h3><code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=offsetw&#038;c=">body.offsetWidth</a></code>, <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=clientw&#038;c=">.clientWidth</a></code>, <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=offseth&#038;c=">.offsetHeight</a></code>, &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=clienth&#038;c=">.clientHeight</a></code></h3>
<p>We move onto our final set of JavaScript APIs, and we might hope that we are leaving the vagaries of BOM implementations and entering the consistency of the DOM &#038; CSSOM (although, sadly, these properties are still not under the purview of any W3C standard).</p>
<p>These four values should theoretically be available on all DOM elements: the &#8216;offset&#8217; dimensions include an element&#8217;s content, padding and border, while the &#8216;client&#8217; dimensions are the content and padding alone. Neither include the margin, as detailed in <a href="https://developer.mozilla.org/en/Determining_the_dimensions_of_elements">Mozilla&#8217;s documentation</a>.</p>
<p>In our case, we are querying these properties for the document&#8217;s body, and, since it has no border, the offset and client values should be the same. Our test pages add a CSS margin of 10 pixels, so on the desktop, we would expect its width, at least, to be 20 pixels less than <code>window.innerWidth</code>. Empirically, desktop browsers seem to use the two heights to represent the total length of the page, rather than the height of the window display. (I&#8217;d thought that would be <code>body.scrollHeight</code>, but that&#8217;s another story.)</p>
<p>How do mobile browsers fare? How does the viewport concept affect these values?</p>
<p>With <code>offsetWidth</code> and <code>clientWidth</code>, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50document.body.offsetw&#038;c=">iOS</a> and <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40document.body.offsetw&#038;c=">Android</a> work broadly as you would expect. The non-constrained viewports return measurements in the high 900s (and around 800s for <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android23document.body.offsetw&#038;c=">Android v2.3</a>), and the constrained pages in the low 300s (for portrait) and mid 400s (for landscape).</p>
<p>It&#8217;s notable how and when the choice of doctype affects these values though. With an HTML5 doctype, non-constrained viewport tests on both platforms report 20 pixels less than the viewport size for both values: <a target='table' href="/wp-content/uploads/2011/12/table.html?r=clientw&#038;c=non-constrainedhtml5">960 pixels regardless of orientation</a>.</p>
<p>With an <a target='table' href="/wp-content/uploads/2011/12/table.html?r=clientw&#038;c=xhtml">XHTML-MP doctype</a>, as we&#8217;ve previously mentioned, the viewport becomes the device width by default, and again 20 pixels are correctly deducted to give us values of 300 and 460 in landscape and portrait respectively. The same expected behaviour is seen with <a target='table' href="/wp-content/uploads/2011/12/table.html?r=clientw&#038;c=tconstrainedhtml5">HTML5 doctypes used on constrained viewports</a>.</p>
<p>What is slightly strange is when no doctype is used. In this case, again on both platforms in all scenarios, the <code>clientWidth</code> is the <a target='table' href="/wp-content/uploads/2011/12/table.html?r=clientw&#038;c=none">full viewport width</a> (980, 800, 480 or 320), and the <code>offsetWidth</code> is <a target='table' href="/wp-content/uploads/2011/12/table.html?r=offsetw&#038;c=none">reduced by the margin</a> (to 460, 780, 460, or 300). This seems systemic: as though the lack of doctype puts the browser into a mode where it interprets the body&#8217;s margin as a border.</p>
<p>Across all of our testing combinations, though, the <code>offsetHeight</code> and <code>clientHeight</code> values are the most bizarre set of results in the whole experiment.</p>
<p>There are three patterns on Android and iOS. Firstly, pages with <a target='table' href="/wp-content/uploads/2011/12/table.html?r=clienth&#038;c=none">no doctype</a> will always have <code>clientHeight</code> equal to <code>window.innerHeight</code> once the <code>&lt;/body&gt;</code> tag has closed &#8211; but the <code>offsetHeight</code> will be <a target='table' href="/wp-content/uploads/2011/12/table.html?r=offseth&#038;c=none">completely different</a>. Secondly, when there is a doctype, the <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=clienth&#038;c=html">clientHeight</a></code> and <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=offseth&#038;c=html">offsetHeight</a></code> are always the same, and nearly always regardless of what the doctype actually is. (The <a target='table' href="/wp-content/uploads/2011/12/table.html?r=clienth&#038;c=d:922">bizarre exception</a> is Android v2.3 where the HTML5 doctype on the non-constrained viewport causes both values to reduce dramatically at some point after the document load event). And finally, the <code>offsetHeight</code> value of the non-doctype test always produces the same values as the <code>clientHeight</code> and <code>offsetHeight</code> of the HTML5 equivalent.</p>
<p>Got that?</p>
<p>But what the values actually <em>are</em> seems extremely non-deterministic. We&#8217;ve already commented on the arbitrary nature of <code>window.innerHeight</code> which the non-doctype results seem to echo. But despite the doctype, orientation and viewport size, the meaning of these values would seem very hard to assess. The best we can say is that when <code>clientWidth</code> or <code>offsetWidth</code> go up, <code>clientHeight</code> or <code>offsetHeight</code> go down (as seems sensible), but that no attention seems to be paid to our 20 pixel margin.</p>
<p>Again, properties best left alone, I think.</p>
<p>In contrast to iOS and Android, which use window outer and inner dimensions as the point of delineation between physical pixels and the viewport, Opera Mobile&#8217;s strategy seems to have been to to stay in the world of real pixels until this last <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11doc&#038;c=">document.body</a></code> set of measurements, and finally we get a sense of how it sizes the viewport.</p>
<p>The default viewport width seems to be <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11doc&#038;c=850">850</a> pixels, but although Opera has, until now, remained oblivious to the pages&#8217; doctypes, the values seem to suddenly be very dependent upon them. With an HTML5 doctype on a non-constrained viewport, both <code>clientWidth</code> and <code>offsetWidth</code> are <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11doc&#038;c=830">830</a> (which probably has had the 20 pixel margin deducted), and with XHTMLMP, we get <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11doc&#038;c=300">300</a> or <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11doc&#038;c=460">460</a> (which would be consistent with a constrained viewport, also minus margins).</p>
<p>But with no doctype and no viewport constraint, in either portrait or landscape, we get <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11document.body.clientWidth&#038;c=non-constrainednone">850</a> for <code>clientWidth</code> (i.e. no padding) and&#8230; for <code>offsetWidth</code>, <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11document.body.offsetWidth&#038;c=non-constrainednone">2048</a>! What?</p>
<p>And finally, as they were for iOS and Android, the <code>clientHeight</code> and <code>offsetHeight</code> are a fairly disparate bunch of values. The only assumptions we can make are that a) constrained <code>clientHeight</code> with no doctype will be <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11document.body.clientheight&#038;c=369">the same as</a> <code>window.innerHeight</code> after the <code>&lt;/body&gt;</code> tag; that b) <code>clientHeight</code> and <code>offsetHeight</code> for constrained HTML and any type of XHTML-MP will <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11document.body.clientheight&#038;c=html">all be the same value</a> for a given orientation (and that non-constrained HTML5 will also eventually converge on that value sometime after the document load event); and c) that the values themselves will be more or less unpredictable.</p>
<p>But perhaps not as meaningless as the offsetHeight for non-constrained doctype-less pages. It&#8217;s consistent. But a highly unlikely <a target='table' href="/wp-content/uploads/2011/12/table.html?r=opera11document.body&#038;c=40960">40960</a> &#8211; which must surely, more or less, mean <code>undefined</code>!</p>
<h3>@media <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=@mediadevice-w&#038;c=">device-width</a></code> &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=@mediaw&#038;c=">width</a></code>, <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=@mediadevice-h&#038;c=">device-height</a></code> &#038; <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=@mediah&#038;c=">height</a></code></h3>
<p>We conclude the menagerie of screen dimensions by looking at the values used in CSS3 media queries. These are used as &#8216;features&#8217; in declarations which are used to conditionally load stylesheets or apply the rules within them. Media queries are a staple of contemporary web design, and perhaps should be understood by designers as much as the other properties above need to be understood by developers handling layouts.</p>
<p>Finally, we have some properties which <em>are</em> defined by <a href="http://www.w3.org/TR/css3-mediaqueries/#width">a standard</a>.</p>
<p>Because, for this test, we needed to evaluate these values in JavaScript, we use the <code>matchMedia</code> function and varied the operand until it returned true. This does mean we only have results for those devices which support that API call: namely iOS v5.0 and Android v4.0.</p>
<p>Well it&#8217;s nice to end with some good news. In both platforms, in all conditions, @media <code>device-width</code> always returns the same value as <code>screen.width</code>, and <code>device-height</code> always returns the same value as <code>screen.height</code>. There&#8217;s no matchMedia support in Opera, but I&#8217;ll assume the same would be true.</p>
<p>This is great &#8211; but of course don&#8217;t forget the main issue afflicting <em>those</em> measurements: the lack of rotated values in iOS and Android 2.3&#8242;s wacky 800 viewport value which I&#8217;ll postulate may be echoed here too.</p>
<p>@media <code>width</code> and <code>height</code> also track other JavaScript properties in both platforms. @media <code>width</code> is <em>almost</em> always equal to <code>window.innerWidth</code> (except in non-constrained landscape mode in iOS v5 when the former is <a target='table' href="/wp-content/uploads/2011/12/table.html?r=@media&#038;c=980">980</a> and the former that curious <a target='table' href="/wp-content/uploads/2011/12/table.html?r=innerWidth&#038;c=981">981</a>). @media <code>height</code> is always equal to <code>window.innerHeight</code>.</p>
<p>(It&#8217;s not so clear whether this pattern would be followed by Opera too, were we able to measure it this way. To confirm, it would require a CSS-based test harness &#8211; perhaps another study.)</p>
<p>But there are a couple of things worth saying about this observation. Firstly, the <code>window.innerWidth</code> and <code>window.innerHeight</code> values themselves are something of a bit of a mixed bag. See the earlier discussions above.</p>
<p>Secondly, it&#8217;s interesting to note that the <code>matchMedia</code> result changes with page lifecycle in the same way that the regular JavaScript measures do. This may mean that media queries change their results as the page loads &#8211; I don&#8217;t know how to predict when these parametric CSS rules are evaluated &#8211; and I imagine this might create conditions under which certain resources referred to in the CSS, loaded early in the page (when the size is evaluated to one thing), might turn out to have been unneccessary later in the page&#8217;s life (when the size is evaluated to quite another thing).</p>
<p>Hardcore browser theory &#038; probably more testing required.</p>
<h3><code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=.orien&#038;c=">window.orientation</a></code> &#038; @media <code><a target='table' href="/wp-content/uploads/2011/12/table.html?r=aorien&#038;c=">orientation</a></code></h3>
<p>As a final aside, note that we also measured orientation results. <code>window.orientation</code> returns the number of degrees (0 for portait, 90 for landscape), and is <a target='table' href="/wp-content/uploads/2011/12/table.html?r=ios50window.orien&#038;c=">flawless in iOS</a>, and set correctly after <code>&lt;/body&gt;</code> <a target='table' href="/wp-content/uploads/2011/12/table.html?r=android40window.orien&#038;c=">on Android</a>. (Just remember not to evaluate orientation before the <code>&lt;body&gt;</code> &#8211; it&#8217;s likely still to be 0 in landscape mode)</p>
<p>Opera does not seem to support the API.</p>
<p>The media query equivalent is also apparently fine (where measurable). The only Android timing quirk here is <a target='table' href="/wp-content/uploads/2011/12/table.html?r=&#038;c=b:p">PhoneGap in portrait</a> which thinks it&#8217;s landscape at first. I guess nothing&#8217;s perfect.</p>
<h2>Summary</h2>
<p>Wow. Painful, on the whole.</p>
<p>Let&#8217;s see what we can briefly conclude. I&#8217;m not going to go back through each of the properties, but a couple of things jumped out at me.</p>
<ul>
<li><strong>Doctypes matter</strong> &#8211; you may have no intention of using an XHTML-MP doctype, but if you forget your HTML5 one, some measurements are affected.</li>
<li><strong>Default viewports vary</strong> from 980 through 850, to 800, depending on platform. Be aware that Android&#8217;s default has changed between v2.3 and v4.0.</li>
<li><strong>Page lifecycle matters</strong>: even if you aren&#8217;t stupid enough to run measurement code before the <code>&lt;body&gt;</code>, it can still change radically afterwards, at the document load event, or &#8211; most painfully &#8211; <a target='table' href="/wp-content/uploads/2011/12/table.html?r=&#038;c=d:">sometime after that</a>.
<li><strong>Race conditions</strong> seem more common on Android than on iOS &#8211; I admit this could also be affected by the poor performance of the platform&#8217;s emulator</li>
<li><strong>Height measurements are probably too nerve-wracking</strong> to use &#8211; as might be expected. Except in iOS, where you&#8217;ll need <code>height</code> to get width.
<li><strong>Nothing much is standardized</strong> and where viewports are involved, the chaos of interpretation ensues. That <code>matchMedia</code> provides a JavaScript API into the (standardized) CSS3 properties might be a chink of light.
</ul>
<p>But overall, the message should be: don&#8217;t take anything for granted. Mobile diversity is, unsurprisingly, still with us with a vengeance &#8211; even for apparently simple things like screen size.</p>
<p>Check out the <a target='table' href="/wp-content/uploads/2011/12/table.html">table</a> again, get a little scared, choose your APIs carefully, and test on real devices* like crazy.</p>
<p>(* yes, yes, I still realize this whole experiment is underpinned by the ultimate sin of using emulators <img src='http://tripleodeon.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  )</p>
<p>Thoughts? War stories? Techniques? Fears? <strong>Comments welcome.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2011/12/first-understand-your-screen/feed/</wfw:commentRss>
		<slash:comments>54</slash:comments>
		</item>
		<item>
		<title>Bacon Off</title>
		<link>http://tripleodeon.com/2011/11/bacon-off/</link>
		<comments>http://tripleodeon.com/2011/11/bacon-off/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 22:30:38 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=644</guid>
		<description><![CDATA[Dave Kaneda and I wandered along to the Facebook Mobile Hack last week. We spend a lot of time attending, speaking at, and sponsoring hackathons, but wanted to have a go at getting involved for ourselves. Consider it SenchaCon decompression or something. The event as a whole was excellent &#8211; some great sessions and a [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://9-bits.com/'>Dave Kaneda</a> and I wandered along to the Facebook Mobile Hack last week. We spend a lot of time attending, speaking at, and sponsoring hackathons, but wanted to have a go at getting involved for ourselves. Consider it <a href="http://secure.lenos.com/lenos/sencha/SenchaCon2011/">SenchaCon</a> decompression or something.<br />
<span id="more-644"></span></p>
<p>The event as a whole was excellent &#8211; some great sessions and a strong focus on using HTML5 for mobile apps. Facebook&#8217;s new graph API, for example, encourages developers to think about how to semantically describe users&#8217; contextualized activities (how many sedentary web users do you see in this <a href='http://www.youtube.com/watch?v=q3b94kFBah8'>video</a>?). All part of an exciting mobile future for the web&#8217;s next decade.</p>
<p>Team Sencha was probably rather too ambitious. But after several frantic hours, we managed something that more or less worked.</p>
<p><img src="http://tripleodeon.com/wp-content/uploads/2011/11/bacon1-500x266.png" alt="" title="bacon1" width="500" height="266" class="alignnone size-large wp-image-645" /></p>
<p>Our app was to be <strong><a href='https://github.com/jamesgpearce/BaconOff'>BaconOff</a></strong>, a two player game to match actors from your Facebook-liked movies against each other based on their <a href="http://en.wikipedia.org/wiki/Six_Degrees_of_Kevin_Bacon#Bacon_numbers">Bacon Number</a>, Top-Trumps-style. The server-side, node.js, hosted and deployed easily to Heroku, and which handles the Facebook authentication, delivers a Sencha Touch app, containing an access token, to the browser. (No doubts at all this can be more elegant and secure).</p>
<p>The first thing the app does is <a href="https://github.com/jamesgpearce/BaconOff/blob/master/client/app/stores/movies.js#L30">pull</a> a list of your favorite movies from Facebook. Once loaded, each movie record <a href="https://github.com/jamesgpearce/BaconOff/blob/master/client/app/stores/movies.js#L11">calls imdbapi.com</a>, a wrapper around IMDB&#8217;s database, and fetches four actors from each of your favorite movies.</p>
<p>Those actors are then created as a further type of model, each of which has a <a href="https://github.com/jamesgpearce/BaconOff/blob/master/client/app/stores/actors.js#L7">bacon-number-fetching method</a>. We hoped to use YQL to get the values from <a href="http://oracleofbacon.org/">Oracle of Bacon</a>, but it was barred by a robots.txt condition. Slightly cheekily, we used our node backend to <a href="https://github.com/jamesgpearce/BaconOff/blob/master/web.js#L54">proxy a request</a> to that server anyway, and then handle the common condition of there being more than one entry for each actor&#8217;s name.</p>
<p><img src="http://tripleodeon.com/wp-content/uploads/2011/11/bacon2-266x500.png" alt="" title="bacon2" width="250" height="469" class="alignnone size-large wp-image-647" /><img src="http://tripleodeon.com/wp-content/uploads/2011/11/bacon3-266x500.png" alt="" title="bacon3" width="250" height="469" class="alignnone size-large wp-image-647" /></p>
<p>In the meantime, and no thanks to me, we had a sweet UI and CSS3-animated loading screen &#8211; all Sass goodness from Mr Kaneda of course.</p>
<p><iframe src="http://baconoff.herokuapp.com/loading.html" width='200' height='200' style='border:0;margin:auto;display:block'>//</iframe></p>
<p>We&#8217;d hoped to avoid having state stored anywhere on the server or in the client, using the social graph alone. Eventually we figured it was unavoidable, and quickly had to write a game state storage layer on the server side. It uses a contemporary storage platform known as&#8230; the <a href="https://github.com/jamesgpearce/BaconOff/blob/master/web.js#L93">file system</a>. Ahem.</p>
<p>From here on, with time running out, and with a flying visit required to my son&#8217;s (excellent!) school play on the other side of El Camino, code started sprawling as we dashed for something demonstrable.</p>
<p>APIs for <a href="https://github.com/jamesgpearce/BaconOff/blob/master/web.js#L100">starting</a>, <a href="https://github.com/jamesgpearce/BaconOff/blob/master/web.js#L121">listing</a>, and <a href="https://github.com/jamesgpearce/BaconOff/blob/master/web.js#L136">playing</a> games quickly followed, and views on the client side emerged to allow <a href="https://github.com/jamesgpearce/BaconOff/blob/master/client/app/views/friends.js">competitor</a> and <a href="https://github.com/jamesgpearce/BaconOff/blob/master/client/app/views/chooseActor.js">actor</a> selection, as well as the game&#8217;s <a href='https://github.com/jamesgpearce/BaconOff/blob/master/client/app/views/home.js'>home screen</a>.</p>
<p>We added the <a href="https://github.com/jamesgpearce/BaconOff/blob/master/views/home.ejs#L47">Facebook JavaScript library</a> relatively late in the day to allow competitor selection and request; (in retrospect we should have based the whole app around this library from the start &#8211; what were we thinking?). And then tried, and failed, to make the frictionless sharing of the game progress <a href='https://github.com/jamesgpearce/BaconOff/blob/master/client/app/app.js#L77'>post to the timeline</a>: I just couldn&#8217;t find the relevant permissions settings in the last 30 seconds before we went on stage. This was a shame, because we&#8217;d had the nouns and verbs configured ages before!</p>
<p>At somewhere approaching 1am, we finally got to demo the app, and for those two minutes it more or less worked. There was only one hack required to make the walkthrough work: I&#8217;d been working on the assumption that players would be keyed by name, while Dave (and, it turns out, Facebook) that they would be keyed by ID. A small <a href="https://github.com/jamesgpearce/BaconOff/blob/master/client/app/app.js#L46">hardcoded line</a> covered that up &#8211; albeit at the expense of making every game ever appear to be against Dave himself. With that in mind, I&#8217;ll decline to link to a live running version. Screenshots only <img src='http://tripleodeon.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><img src="http://tripleodeon.com/wp-content/uploads/2011/11/bacon4-266x500.png" alt="" title="bacon4" width="250" height="469" class="alignnone size-large wp-image-653" /><img src="http://tripleodeon.com/wp-content/uploads/2011/11/bacon5-266x500.png" alt="" title="bacon5" width="250" height="469" class="alignnone size-large wp-image-654" /></p>
<p>So yes, in retrospect, far too ambitious. Hacking time was supposedly limited to 6 hours, and we&#8217;d needed a few more than that. I rather wish now that we&#8217;d just done a Social Compass app and stuck some avatars on top of a simple <a href="http://tripleodeon.com/2011/10/taking-a-new-device-api-for-a-spin/">webkitCompassHeading</a> event handler or something. We weren&#8217;t expecting to win anything (there&#8217;s no doubt the well-prepared entries were far superior <img src='http://tripleodeon.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) &#8211; and let&#8217;s just say that this was an expectation firmly met.</p>
<p>But it was a lot of fun being on the other side of the stage for once. And it&#8217;s interesting to see how far you can get on something completely new in a short time period if you put your mind to it. I guess that&#8217;s the whole point; code quality be damned&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2011/11/bacon-off/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Taking a new device API for a spin</title>
		<link>http://tripleodeon.com/2011/10/taking-a-new-device-api-for-a-spin/</link>
		<comments>http://tripleodeon.com/2011/10/taking-a-new-device-api-for-a-spin/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 19:00:52 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Device APIs]]></category>
		<category><![CDATA[Mobile Web]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=633</guid>
		<description><![CDATA[I love Device APIs, even the non-standard ones. I think they are going to hoist the web up onto its next level of innovation, usage, and ubiquity. I was pleased to discover that iOS5 includes a new one, tucked away as a new property, webkitCompassHeading, mentioned by Apple on the W3C lists a little while [...]]]></description>
			<content:encoded><![CDATA[<p>I love Device APIs, even the non-standard ones. I think they are going to hoist the web up onto its next level of innovation, usage, and ubiquity.<br />
<span id="more-633"></span></p>
<p>I was pleased to discover that iOS5 includes a new one, tucked away as a new property, <code>webkitCompassHeading</code>, mentioned by <a href="http://lists.w3.org/Archives/Public/public-geolocation/2011Jul/0014.html">Apple on the W3C lists</a> a little while back.</p>
<p>Previously this event&#8217;s orientation data was great for relative rotation, but its absolute value was arbitrary with respect to the real world. The new property gives a heading that is meaningful for real-world navigation. (There is also a <code>webkitCompassAccuracy</code> property that tells you how well it is doing.)</p>
<p>So I lashed up <a href="http://jamesgpearce.github.com/compios5/">Compios5</a>, a small web-based compass application, to show it off. It requires, of course, a real iOS5 device to work. (It&#8217;s been tested on iPhone 4 hardware. Should work fine on iPhone 4S. Layouts are probably slightly strange on the iPad.)</p>
<p><img class="alignnone size-large wp-image-634" title="compios5" src="http://tripleodeon.com/wp-content/uploads/2011/10/Screen-Shot-2011-10-14-at-11.21.36-AM-500x266.png" alt="" width="500" height="266" /></p>
<p>The compass itself is created entirely with CSS, with a few programmatically created elements for the labels and arrows. Designers: please issue pull requests to make it look nicer!</p>
<p>The code is <a href="https://github.com/jamesgpearce/compios5">here</a>. A couple of implementation notes:</p>
<ul>
<li>There&#8217;s easing on the rotation to make it a little less jerky, but this has to be turned off whenever the compass spins through north. CSS transitions do not wrap-around transforms.</li>
<li>window.orientation needs to be added to the heading so that a landscape view still points to physical north.</li>
<li>Media queries detect orientation so that the compass stays in the center of the screen. It&#8217;s not quite stationary on a portrait-&gt;landscape flip, but great the other way.</li>
</ul>
<p>As I said, this won&#8217;t work on any device apart from a real iPhone. There&#8217;s no way to simulate heading changes in the iOS simulator that I can find. But if you&#8217;ve upgraded, or have a shiny new iPhone 4S, please take it for a whirl.</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2011/10/taking-a-new-device-api-for-a-spin/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Of Sites and Apps</title>
		<link>http://tripleodeon.com/2011/09/of-sites-and-apps/</link>
		<comments>http://tripleodeon.com/2011/09/of-sites-and-apps/#comments</comments>
		<pubDate>Sat, 10 Sep 2011 23:13:17 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=621</guid>
		<description><![CDATA[Users probably don&#8217;t care what&#8217;s a web site and what&#8217;s a web app. But I believe web practitioners should, if only to know when certain best practices apply, and when they don&#8217;t. But does an established distinction exist between the two genres of experience? Not as far as I know. Is it to do with [...]]]></description>
			<content:encoded><![CDATA[<p>Users probably don&#8217;t care what&#8217;s a web site and what&#8217;s a web app. But I believe web practitioners should, if only to know when certain best practices apply, and when they don&#8217;t.</p>
<p>But does an established distinction exist between the two genres of experience? Not as far as I know. Is it to do with creation versus consumption? Linkability? User experience? Or the architecture underlying the way they are built?<br />
<span id="more-621"></span></p>
<p>Personally I think there <em>is</em> a way to clearly delineate the two types of experience, but I&#8217;m also sure it&#8217;s not the only way to do so, and that the distinctions are very likely to vary with individual&#8217;s perspective. I&#8217;m unabashedly trawling for debate.</p>
<p><code>&lt;tldr&gt;</code></p>
<p>There&#8217;s one notable result of the disruption that mobile is wreaking upon the way we think about the web. The blogosphere, the conference circuit and various online communities &#8211; not to mention boardrooms up and down the country &#8211; are abuzz with hypotheses regarding the &#8220;One True Way&#8221; to do something, the &#8220;Dawn of&#8221; this, or the &#8220;Death of&#8221; that.</p>
<p>No doubt I&#8217;m a part of this. It&#8217;s quite fun. (Although let&#8217;s be honest, none of us really has a clue about how mobile&#8217;s going to play out eventually.)</p>
<p>In the real world, such binary proclamations are less useful than we like to think. Building mobile and web experiences for real users, real business &#8211; and with real constraints of many kinds &#8211; is not at all easy. Being buffeted around by voguish black-and-white philosophies (or even the outmoded ones) is of reduced benefit when you&#8217;re really trying to navigate the shades of gray in between.</p>
<p>One of the shadiest boundaries to have to consider when using web technologies is that netherworld that lies between &#8216;web application&#8217; and &#8216;web site&#8217;. As far as I can tell, there aren&#8217;t established definitions that help us decide what is one and what is another &#8211; let alone a decision tree that developers and designers can follow to decide what sort of experience they should deliver to their users in different circumstances.</p>
<p>On one hand, the differentiation between these two things seems rather academic. If a user can access what I want them to access, and can do what I want them to be able to do, then who cares how we label that experience? It&#8217;s the web right? (Stop reading now.)</p>
<p>But again, this belies the subtlety of the real world, and especially in mobile. It&#8217;s 2011: iPhone-plus-four. Users want apps. Marketers want apps. Boardrooms want apps. This is, we&#8217;ve been trained to believe, the way in which we enhance our phones&#8217; capabilities and access information in elegant, consistent ways. We can assert as much as we want that users should only be using their devices&#8217; web browsers, but apps sell, and will continue to.</p>
<p>Of course, many of these apps are written with native technologies, and distributed via non-web-based stores. This article is not about them: they are likely to become evolutionary dead-ends. But if the web is to succeed as a distribution medium &#8211; and as a stack of technology &#8211; it will have to rise to match the expectation that&#8217;s been set. It will have to provide what is needed to create and deliver app-like experiences, just as well as it can classical site- and document-based content.</p>
<p>The good news is that smarter people than me have long seen this coming. Although much of HTML5 (the markup specification) is about improving the semantic qualities of web documents, HTML5 (the suite of related APIs and technologies) is unashamedly focussed on enabling web applications of increasing complexity. And with browser vendors now competing on such metrics as JavaScript performance and API completeness (rather than how well they support the &lt;aside&gt; tag or somesuch), it seems we should expect to see ever more advanced web apps in the future.</p>
<p>Nevertheless, in frequent discussions about the mobile web, its best practices, and its tools, you&#8217;ll hear many arguments qualified with clauses like &#8220;oh, but things are different if you&#8217;re building an app&#8221; or &#8220;this is a better technique for traditional sites&#8221;. I know, because I do too.</p>
<p>And so, as we enter conference season again, I thought it might be interesting to see if there&#8217;s any consensus about what these two things even are, and how we can differentiate between them. What is a mobile web app? And when is it not a mobile web site?</p>
<p>For me, there are a few possible vectors that we can consider.</p>
<p><strong>Creation versus Consumption</strong></p>
<p>Imagine a large structured collection of interlinked documents, where the user is essentially limited to a read-only interaction (give or take the odd comment form or search box). There&#8217;s no doubt that such a thing should be classified as a site. Blogs, news sites, academic papers &#8211; these are clearly the heartland of the classical web. Online stores too? Probably.</p>
<p>But what about micro-blogging services? Photo-sharing? Online email clients, document editors, IDEs even? Games? It seems debatable as to whether one should classify twitter.com as a site or an app (especially on a mobile device), but I am most certainly using an application when I&#8217;m logged into GMail, Google Docs, or playing Angry Birds &#8211; let alone working in some web-based data admin interface.</p>
<p>Interestingly, this second category of experiences all seem to be read-write (or at least, highly interactional). So can we classify sites as being read-only and apps as being read-write? That certainly seems simple enough: sites are to consumption as apps are to creation.</p>
<p>Does this feel right? One problem here is that there are some beautiful and enjoyable app-like experiences &#8211; Flipboard comes to mind &#8211; which are clearly oriented towards consumption. (But then again, maybe the logic is backwards here… perhaps Flipboard is what the web <em>site</em> of the future should look like, though Gawker&#8217;s infamous app-like blog felt clunky). And how would you classify Facebook? Entirely user-generated content, but it still looks and feels quite like a site.</p>
<p><strong>Linkability</strong></p>
<p>If you are launching an experience from a desktop or homescreen icon, it is easy to feel that you are in a sandboxed and closed environment whose boundaries are explicit and inescapable. If you start your experience by entering a URL into a browser, conversely, you&#8217;re more likely to feel that you are at the start of journey &#8211; one where every link clicked can immediately take you to another page or another site or another domain, across the web&#8217;s endless interlinked landscape with no boundaries.</p>
<p>So does this serve as a way to distinguish between site and app? Most native apps certainly do have impermeable boundaries: outbound and especially inbound. Even the iPhone Twitter app opens up links in a modal, embedded web view rather than spawning a new Safari window (much to <em>my</em> frustration, at least).</p>
<p>But web apps? Need these be silos? No, of course not. They&#8217;re still running in a browser, and (unless in hybrid environment) hanging off a URL like any web site does. There&#8217;s no reason for a web app not to contain links that lead you off to other parts of the web, either in new browser tabs or the present one. While reliable deep-linking back into web apps seems to be less commonplace, this is more a function of implementations and browser&#8217;s fragmented History APIs than some fundamental flaw in the web&#8217;s architecture. (I never shared purists&#8217; distaste of hash-bangs, for example. These are a symptom of developers trying to make this inbound linkability and bookmarkability work for single-page web apps: fixing the web, not breaking it.)</p>
<p>So, like others, I&#8217;d definitely hold up linkability as a huge advantage of web apps over native apps &#8211; but not as a reliable way to distinguish between web apps and web sites.</p>
<p><strong>User Experience</strong></p>
<p>Another way we might classify apps and sites is by assessing the user interface and experience presented. What are the visual cues that an app&#8217;s an app, and a site&#8217;s a site?</p>
<p>The use of fixed toolbars is certainly an obvious one: at the top, containing a title and maybe a back button; at the bottom a series of large tab-navigating buttons within easy thumb-reach. This is a UI/UX paradigm that, pioneered by iOS, emerged entirely from the native application world, and which, before 2007, had absolutely no precedent in the classical or mobile web worlds.</p>
<p>Ditto disclosure lists. Ditto sliding transitions between master and detail records. Ditto action sheets, spinners, and momentum-based scrolling. Ditto even the disablement of pinch &amp; zoom on document-like content (controversial to some, and yet understandable if you argue that viewport zooming was merely the browser&#8217;s way of dealing with legacy, not-made-for-mobile web content in the first place).</p>
<p>Many developers work hard to bring these platform behaviors in their web apps. And many web frameworks work hard to make it easy for them to do so. (My employer is one of those, of course.) Many rightly blanche at the thought of slavishly mimicking a particular operating system &#8211; nothing looks dafter than iOS pinstripes in an Android browser &#8211; but the point is that many of these generalized UX characteristics are highly suitable for one-handed, touch-based interactions. No-one will claim that legacy desktop web sites (often replete with tiny mouse-centric sidebar menus and table layouts) can ever match a dedicated app-like user experience. Responsive web sites can indeed improve this greatly, with navigation often flowing to the top or bottom of documents for certain screen sizes. But still, these sites are rarely mistaken for apps.</p>
<p>Because the visual appearance is the &#8220;I somehow just know this is an app&#8221; argument, and one that users might particularly relate to, I do give the UI/UX distinction a lot of credence. But still, it&#8217;s a very fuzzy boundary. What if my site displays a fixed toolbar, but no back button? What if my list looks like hyperlinks instead of tappable disclosures? What if I style plain scrolling instead of momentum? This is a question that the likes of jQuery Mobile have pondered too, in an attempt to follow a site-like, progressive enhancement philosophy. Nevertheless plenty of developers are undoubtedly going to describe the results as apps.</p>
<p><strong>Architecture</strong></p>
<p>So this leaves us looking for a more technical distinction. Is there an architectural, boxes-and-arrows argument that might clarify the difference?</p>
<p>The web we&#8217;ve known and loved for almost 20 years &#8211; undoubtedly a web of sites! &#8211; is unashamedly thin-client in design. Web servers do all the heavy lifting, hosting the storage, business logic, and the construction of the user interface that the user sees. Indeed it is surprising that we&#8217;ve had to suffer so much browser inconsistency over the years considering that all they&#8217;ve had to do is turn a stream of <code>&lt;</code> and <code>&gt;</code> into pixels.</p>
<p>But the rise of the use of AJAX was a clue that this architecture wasn&#8217;t always particularly elegant. A user clicks a link to another page on your site? That might mean a whole set of HTTP connections (again), a blocked server thread (again), a clutch of database connections (again), the execution of a bunch of business logic (again), the generation of a whole new slab of markup (again), and its dispatch back across the wire (again). And that&#8217;s all before expecting the browser to re-render the entire user interface (again).</p>
<p>I love URLs, hyperlinks and SEO as much as the next man, but that&#8217;s some price to pay to simply display a new record of content.</p>
<p>On the other hand, consider an architecture in which the browser is given far more autonomy and responsibility. Think &#8220;AJAX++&#8221;, perhaps, where not only fragments of the DOM are elegantly updated, but where the entire application can reside and execute in the browser.</p>
<p>The big breakthrough here, of course, has been HTML5&#8242;s storage APIs, which allow JavaScript in the browser&#8217;s environment to persist reasonable amounts of keyed data throughout or between sessions. This finally brings honest statefulness to our previously stateless browser clients.</p>
<p>On top of this, mature JavaScript runtimes and frameworks happily allow the creation of robust business logic to be applied to this data. DOM manipulation, made reliable and fast by contemporary browsers (and commoditized by libraries for others) means that you can programmatically construct and manipulate entire user interfaces in the browser &#8211; in the extreme case, bootstrapping them up from a <code>&lt;body/&gt;</code>-like document whose main purpose is merely to include a <code>&lt;head&gt;</code> of the linked resources required to execute.</p>
<p>This is the world of the thick web client &#8211; or &#8216;Rich Internet Application&#8217; in slightly out-moded nomenclature. A world in which patterns like MVC can be used again to describing client-side behavior, as well as a server-side technique. With this approach, once a client-side application has loaded its resources and is up and running, it can function more or less independently of the server that originally provided those resources, and creates and maintains a DOM that looks very different to that originally sent in the HTML&#8217;s markup.</p>
<p>(One might wish to argue that GMail is really just a site comprising a set of documents. Conceptually, perhaps. But comparing the app&#8217;s view-source with an inspected DOM tree will present a dramatically different perspective.)</p>
<p>With perhaps the exception of simple games, these applications nearly always need to bind back to some sort of web-based data API. As required, though, they can then easily cache that offline in their own data stores, greatly increasing the responsiveness and user-experience of the application, and making the prospect of continued offline operation a reality. This is a bold new step for the web. Not the web as constantly humming HTTP-pipes, but undoubtedly the web as stack of standardized, open technologies, working in interesting and evolutionary new ways.</p>
<p>I don&#8217;t want to give the impression that I feel this type of architecture should be used for all web experiences, nor even that it&#8217;s easier to build. Creating apps this way can be a daunting experience for many. Using imperative APIs may seem like a step too exotic next to the familiarity of declarative markup-based documents generated from a server. Your mileage will most certainly vary, and definitely some sorts of experience are better suited by one approach, others by the other. No binary proclamations implied.</p>
<p><code>&lt;/tldr&gt;</code></p>
<p>But the point is that perhaps this is the watershed that we are looking for: a relatively clear definition between web site and web application.</p>
<p>The former we can define as an experience constructed on a thick server, delivered, with declarative markup, to thin browser clients, which then render what they&#8217;re told. Sprinkle on some progressive enhancement to maximize the user-experience and increase the chances of delivering a suitably degraded experience to legacy browsers.</p>
<p>The latter, on the other hand, is an experience constructed on a thick browser client, from imperative instructions dispatched, probably only once, from a thin server (or, in the case of a hybrid app, even no server at all). The philosophy of progressive enhancement survives &#8211; perhaps better characterized as &#8216;feature detection&#8217; in this programmatic environment &#8211; although such apps often assume a certain higher baseline of browser capability. Local storage is utilized, MVC-like patterns are followed, concerns of data, logic and presentation are completely separated, and markup, if present at all, might be used merely for templates to be applied to that data.</p>
<p><strong>So&#8230;</strong></p>
<p>&#8230;yes, I&#8217;m a developer. I think in boxes and arrows. But as a relatively unambiguous classification criteria, this final, architectural distinction works best for me. Assuming you agree that such classification matters at all (in particular to those developing such experiences), how does this suit as a working hypothesis?</p>
<p>Discuss, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2011/09/of-sites-and-apps/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Whoops and hashbangs</title>
		<link>http://tripleodeon.com/2011/06/whoops-and-hashbangs/</link>
		<comments>http://tripleodeon.com/2011/06/whoops-and-hashbangs/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 07:42:26 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Observations]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=606</guid>
		<description><![CDATA[Three people in the last week have told me I should be blogging more. Flattered, and probably more helpfully than leaving nuggets of half-baked comments on everyone else&#8217;s, I&#8217;ll do my best. I dust off the cobwebs by apologizing for a tweet in which I misattributed Scott Jehl. No thanks to strange avatar positioning, I [...]]]></description>
			<content:encoded><![CDATA[<p>Three people in the last week have told me I should be blogging more. Flattered, and probably more helpfully than leaving nuggets of half-baked comments on everyone else&#8217;s, I&#8217;ll do my best.<br />
<span id="more-606"></span><br />
I dust off the cobwebs by apologizing for a <a href="http://twitter.com/#!/jamespearce/status/75709304145063937">tweet</a> in which I misattributed Scott Jehl. No thanks to strange avatar positioning, I thought he&#8217;d made a <a href="http://danwebb.net/2011/5/28/it-is-about-the-hashbangs#comment-7617">provocative comment</a> about the destiny of URLs on a post about everyone&#8217;s favorite topic, the hashbang.</p>
<p>(Hopefully I&#8217;m not the only one who can barely see <code>#1e1e1e</code> on <code>#141414</code>)</p>
<p>It did sound out-of-character from a champion of jQuery projects, and perhaps I was tempted to acknowledge the comment because it seemed such an extreme position from him. Sorry Scott!</p>
<p><img src="http://tripleodeon.com/wp-content/uploads/2011/06/quote-500x129.png" alt="" title="quote" width="500" height="129" class="alignnone size-large wp-image-607" /></p>
<p>But onto the comment itself. Why did I take a shine to it? It certainly takes a provocative stance.</p>
<p>&#8220;We are long past the point where URLs have any utility&#8221; is strong language. I of course enjoy the benefits of links and URLs myself every day, and I&#8217;m sure the <a href="http://dakliegg.wordpress.com/">commenter</a> does too: bookmarks, links, emailed or tweeted, the ability to return through a browser&#8217;s history, open new browser tabs with target content and so on. All very useful. All very <a href='http://www.w3.org/Provider/Style/URI'><i>cool</i></a>.</p>
<p>But does this mean that the URL is so sacred we can&#8217;t discuss its role and relevance in the real world? Think about whether it&#8217;s actually doing its job? Wonder whether it&#8217;s productive to shield it from the creative ways in which the web is evolving? And, as this commenter did, consider whether search engines are in fact coping with these changes effectively?</p>
<p>(Heretical to most people&#8230; but the sort of thing I like to think about &#8211; probably <i>for</i> that reason, actually. And what else are blogs for, anyway?)</p>
<p>So, yes, yes; URLs are used as a key for locating documents and resources across the web. That is all well and good. But I&#8217;m thinking; what happens when the web hosts things other than documents and resources? Like applications? Like games? Like physical objects? What happens when we need to serve humans based on <i>other</i> signals, such as their location, the time of day, their context, their intent?</p>
<p>It might <i>just</i> be possible, as the commenter asserts, that a single string-based identifier is not, in fact, sufficient to describe the infinite things that a 21st century, multi-dimensional web can do, offer, and represent.</p>
<p>I&#8217;m not completely sure. But I am convinced (and excited) that the web is evolving in these sorts of ways. Client-side applications, for example, seem to be a perfectly valid and compelling architectural way to use web technologies. And yet what role does the URL play there? Obviously as an entry point to the app as a whole, but then what? Does Tim Berners Lee&#8217;s plea require me to use a URL to describe every possible state, every view and every data point within it?</p>
<p>Documentistas would have it so. I can&#8217;t possibly build anything for the web without every piece of it being addressable like a document. Users must be able to deep-link into any <strike>docu</strike> state of my application. These URLs must return content to robots too &#8211; because where would we be without web crawlers? &#8211; and of course it all needs to degrade nicely for legacy browsers and screen readers. In fact, I may as well just fake the whole thing with server-side markup and progressive enhancement anyway. Many do.</p>
<p>But if I&#8217;m an applicationista, I create true client-side web applications, probably programmatically. I use little, if any, content-bearing markup, and I provide a suite of complex functionality to users, and pull in content from server- or cloud-based APIs in my own particular way. I acknowledge that my application needs to be accessible somehow, but in the corresponding state machine, the concept of a linkable document can quickly become tenuous, if not entirely inappropriate. Yes, I could conceivably use URLs to describe the finite states of a game of tic-tac-toe. But is there a http://angrybirds.com/level4 ? Or a http://angrybirds.com/level4/just-before-the-red-bird-hits-the-big-block ? Not that I know of.</p>
<p>If this web of applications is our new operating system, I see URLs as our command line switches. They can open apps, and sometimes drop you into well-understood states within that app. But by no means is the developer obliged to let any user reproduce any arbitrary state within it. A desktop developer can choose to let users launch a classic native application with certain pre-defined states &#8211; start this tool with a particular file open, for example &#8211; but does so in a very controlled and discoverable way. No native OS I know mandates that an application&#8217;s command line switches must be capable of describing all of its possible states. So why should the web?</p>
<p>In reality, certain web apps will benefit from deep-linkability, but many do not at all. And just because a large part of the web (the documenty bit) holds URLs self-evident and axiomatic might not mean that a different, growing part of the web (the applicationy bit) must do so too. Nick Morgan, admittedly <a href='http://skilldrick.co.uk/2011/05/the-end-of-progressive-enhancement-revisited'>opining on a subtly different topic</a>, states:</p>
<blockquote><p>The problem is that because everyone building stuff online is using the same technologies, there can be a tendency to think that there is one true way of using those technologies, independent of what they’re being used for.</p></blockquote>
<p>And this is the crux. We might all be using web technologies (HTML, JavaScript, CSS and the like), but in radically different architectural configurations, and best practices for some may not be good rules for others. What this touches on might be the primary root cause of the hashbang debate (if not also others): the web is being used in challenging and unexpected ways and we&#8217;re finding it hard to re-examine practices and principles that were intended for a different age.</p>
<p>Yes, hashbangs are ugly. A hack. Sometimes they&#8217;ll need to be replaced with judicious use of the HTML5 History API. But other times they&#8217;ll need to be removed altogether: &#8220;<i>it depends</i>&#8220;.</p>
<p>But I believe that their usage &#8211; and the debate that has raged over that usage &#8211; tells us more about the culture of the web and those who create things for it than it does about syntactic purity or semantic elegance. It has shown us that we still find it hard not to think about the web in terms of documents, and that a web of applications can seem strange and opaque. And maybe that we are in a tighter symbiosis with search engine crawlers than we&#8217;d like to admit. Is that <i>really</i> what is meant when we&#8217;re told we risk breaking the web?</p>
<p>(It might be no co-incidence that our greatest cognitive dissonance occurs when we see something that probably should have remained document-based turned into an application, such as Gawker&#8217;s blogs. I notice that the vehemence of this debate never erupted over the non-linkability to arbitrary internal state of my GMail inbox, or to my high score on <a href='http://entanglement.gopherwoodstudios.com/'>Entanglement</a> for example. But I&#8217;m trying not to miss the wood of the web&#8217;s ambition for the trees of one particular implementation.)</p>
<p>Probably drawing ire, or confusion, from most at this point, I guess I leave it there. Please file under &#8216;verbose trolling&#8217;, and yes, for a developer, I&#8217;m veering dangerously close to amateur anthropology.</p>
<p>But let me finish with the commenter&#8217;s radical assertion that search engines &#8216;have long given up on indexing the web&#8217; &#8211; crazy, surely: they still seem to do a great job with documents.</p>
<p>But applications? I&#8217;m not so sure. He might be on to something here. We&#8217;ve clearly got a long way to go in terms of describing and indexing application state, purpose and functionality on the web &#8211; without resorting to human curation. I&#8217;ve heard of these things called app stores, for example&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2011/06/whoops-and-hashbangs/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Mobile, One Web, RWD &amp;c &#8211; an unbuffered comment</title>
		<link>http://tripleodeon.com/2010/12/mobile-one-web-rwd-c-an-unbuffered-comment/</link>
		<comments>http://tripleodeon.com/2010/12/mobile-one-web-rwd-c-an-unbuffered-comment/#comments</comments>
		<pubDate>Thu, 09 Dec 2010 19:52:00 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[dotMobi]]></category>
		<category><![CDATA[Mobile Web]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=601</guid>
		<description><![CDATA[Jeremy Keith&#8217;s blog post entitled &#8216;One web&#8216; is good summary of many of the points of view around designing and developing web sites and services for mobile devices. I think he has a staggered commenting system, so I thought I&#8217;d share my response here in the meantime. Don&#8217;t worry; it&#8217;s not inflammatory (or at least, [...]]]></description>
			<content:encoded><![CDATA[<p>Jeremy Keith&#8217;s blog post entitled &#8216;<a href="http://adactio.com/journal/1716/">One web</a>&#8216; is good summary of many of the points of view around designing and developing web sites and services for mobile devices. I think he has a staggered commenting system, so I thought I&#8217;d share my response here in the meantime. Don&#8217;t worry; it&#8217;s not inflammatory (or at least, is not meant to be!)<br />
<span id="more-601"></span><br />
I&#8217;m still convinced there&#8217;s something bigger going on here.</p>
<p>The (paraphrased) &#8216;one-url-for-one-document&#8217; mantra is great when the web is one of essentially immutable documents.</p>
<p>But isn&#8217;t it time to bust through this assumption? &#8211; as we (and even consumers) start to think of the web as being more one of apps? One which should flex and adapt to give the user the best experience (by which I include content, functionality as well as user interface and pixels) possible, given everything we can divine about the human using it?</p>
<p>If an application is to provide the service that its user needs, the more clues about what that human is doing the better. If they are using a mobile device, there&#8217;s already a big clue about what that user&#8217;s state might be. I&#8217;m intrigued by things like Nokia&#8217;s Situations project too, as it permits more insight into what the user is doing, where they are, and what state of mind they&#8217;re in. Imagine how you might be able to optimize a web experience &#8211; to the human &#8211; given such clues!</p>
<p>So as you can tell, I&#8217;m excited about this. A far more fluid web that is truly responsive like this. Responsive to human context (in all its possible forms) and not just the temporary challenge of smaller numbers of pixels. It&#8217;s not that I&#8217;m not a fan of RWD &#8211; just that it&#8217;s far too superficial to help move the web to this higher plane.</p>
<p>However, I also still believe in &#8216;thematic consistency&#8217;, by which the W3C means that the same URL should get you to the same content. BUT that is not the same as saying that the same users actually want to use the same content or that web providers want to give it to them.</p>
<p>In practical terms, this might mean promoting or demoting certain types of content that the designer thinks are more or less useful for users known to be in the mobile context. (I&#8217;ve talked about promoting &#8216;contact us&#8217; from the conventional end-of-secondary-menu to front-and-foremost on mobile sites, for example.)</p>
<p>But why not create entirely separate services? I certainly don&#8217;t find it condescending when a user-interface designer has thought about what I actually want to do in a given context. More likely I&#8217;ll be thrilled.</p>
<p>And by the way, with this point of view, separate URLs or domains are entirely consistent: &#8220;we don&#8217;t mind which device you actually use, but you should be aware that the content on our mobile URL is better suited to humans on the move&#8221;.</p>
<p>Finally I should add that this is really nothing more controversial than using country-code top level domains. The reason there is an amazon.co.uk is because users in the &#8216;UK context&#8217; want (or need to be given) different content and functionality. No-one ever complains about detecting IP ranges to encourage users from different countries to go to the best service for their likely location.</p>
<p>I&#8217;m a proud citizen of Mobile Web country <img src='http://tripleodeon.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2010/12/mobile-one-web-rwd-c-an-unbuffered-comment/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>A Web of Sync</title>
		<link>http://tripleodeon.com/2010/12/a-web-of-sync/</link>
		<comments>http://tripleodeon.com/2010/12/a-web-of-sync/#comments</comments>
		<pubDate>Thu, 09 Dec 2010 04:52:52 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=586</guid>
		<description><![CDATA[I&#8217;m excited about how the rise of HTML5 (and related technologies) will change the way we think about the web, and how they will further encourage developers to build richer applications instead of mere document-oriented sites. (At Sencha, for example, we spend a lot of time thinking about what this really means, and how it [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m excited about how the rise of HTML5 (and related technologies) will change the way we think about the web, and how they will further encourage developers to build richer applications instead of mere document-oriented sites.</p>
<p>(At Sencha, for example, we spend a lot of time thinking about what this really means, and how it changes the skills, tools and frameworks we&#8217;ll all need to be effective web practitioners)</p>
<p>But here, I&#8217;d like to consider three particular changes that are happening, and one particularly overlooked impact they might have.<br />
<span id="more-586"></span><br />
The first is the rise of powerful application architectures on the client side. Sencha has added Model-View-Controller support in both Ext JS 4 and Sencha Touch, for example, and this makes it possible to implement entire data schemas, rich business logic, and well-structured user interfaces &#8211; entirely on the client side. (Other frameworks are following a similar path: SproutCore, JavaScriptMVC and so on)</p>
<p>Secondly, the way in which HTML5 provides support for local and offline storage makes the autonomy of these apps a real possibility. Viewing, filtering and manipulating data can still be performed in the browser, even when completely disconnected from the server (or the entire network, in the case of a mobile device that loses coverage).</p>
<p>Finally, there are the possibilities of being able to use Javascript on the server-side of the web. The rise of interest in node.js, for example, is largely prompted by the opportunity to be able to use the same programming language throughout the entire web stack.</p>
<p>But such changes mean that this stack is changing shape.</p>
<p>Historically, the entire logic of delivering web-based services to browsers was built on the server-side. Databases, security layers, business logic, user interface creation &#8211; all of this was within the realm of the web server, and the browser merely took the resulting HTML and dumbly rendered it for the user.</p>
<p><img style='border:1px solid #999' src="http://tripleodeon.com/wp-content/uploads/2010/12/Web-of-Synchronization.0011-500x319.png" alt="" title="Web of Synchronization.001" width="500" height="319" class="alignnone size-large wp-image-593" /></p>
<p>Of course, this is incredibly inefficient: the entire stack is executed (and a whole page of HTML generated) for almost every single user interaction. To mitigate this, web developers turned to AJAX &#038; AHAH to start placing more of the user interface logic in the client&#8217;s runtime environment, and to reduce the size of the payloads involved. The stack started to span both the server and client sides of the picture.</p>
<p><img style='border:1px solid #999' src="http://tripleodeon.com/wp-content/uploads/2010/12/Web-of-Synchronization.002-500x319.png" alt="" title="Web of Synchronization.002" width="500" height="319" class="alignnone size-large wp-image-594" /></p>
<p>But with client-side MVC and support for local storage techniques, we can take this stack evolution a whole step further. With Sencha Touch, for example, an application constructs its entire user interface from scratch, and can synthesize the entire business logic, validation ruleset, and storage schema that would have traditionally been encapsulated on the server side.</p>
<p>Now, islands of independent data on each and every user&#8217;s device might make for a useful service, but it is far more likely that most applications will continue to operate in conjunction with a server &#8211; which, with the appropriate layer of security to protect access to it, will provide a central storage repository.</p>
<p>Our stack has now been neatly split in two.</p>
<p><img style='border:1px solid #999' src="http://tripleodeon.com/wp-content/uploads/2010/12/Web-of-Synchronization.003-500x319.png" alt="" title="Web of Synchronization.003" width="500" height="319" class="alignnone size-large wp-image-595" /></p>
<p>(Note that, in the same way that we&#8217;ve long learnt to run both client-side and server-side validation of data submitted from HTML forms, it will probably remain wise to mirror business logic on both sides of the network to prevent inconsistency. While the rise of Javascript on the server theoretically makes it possible to do this with one set of common code, in reality, most server stacks will remain non-JS based for some time.)</p>
<p>All well and good. But in one very particular respect, an architecture like this is deeply ambitious. We have added a significant new programming challenge into the mix: and that is one of data synchronization.</p>
<p>When the browser is merely displaying read-only HTML or AHAH, the definitive copy of the business data is one place only: the server. But in this new architecture, we have the same logical data in two places &#8211; and, assuming we&#8217;re allowing users to interact with their copy of it, quite possibly off-line, we have to deal with the matter of keeping the two (or N) data sets consistent.</p>
<p>At a protocol level, this is simple enough. We can easily use JSON to transmit data bidirectionally over an HTTP wire, and Ext JS and Sencha Touch&#8217;s model store classes, for example, take care of all the plumbing for us. But when we should do so, what the payload should be &#8211; and how we reconcile any conflicts between client and server &#8211; can quickly become interesting design questions.</p>
<p>Consider a web-based corporate price list application, build using a client-side MVC pattern, and providing up-to-date information about a company&#8217;s products to its mobile salesforce. On its first instantiation on a mobile device, say, such an application might easily pull the entire list of product records from the server over JSON and store them locally for fast, possibly off-line, access.</p>
<p>So far, so easy. But of course the records might frequently change on the server: the company creates new products, discontinues old ones, and often changes their prices. How should the &#8216;create&#8217;, &#8216;delete&#8217; and &#8216;update&#8217; operations be applied to the mobile device&#8217;s version of the data? Should it regularly refresh the whole data set again? Should it request all changes since the last sync and then incrementally apply those changes to its local copy? If certain data is not updated for a certain length of time, should the client application mark it as stale?</p>
<p>These are already thoughtful decisions for the application developer to have to make.</p>
<p>But now imagine that the company&#8217;s product managers are given more powerful rights within the same application, and they can actually edit the product descriptions on their mobile devices. When connected, these changes can be immediately sent directly back to the server. How can we ensure that other users&#8217; apps can have that change broadcast to them?</p>
<p>What about when the product manager is off-line, perhaps editing the portfolio on a plane? Should the application prohibit updates to the local data? Preferably not, but if changes can be made, how should the application poll to see when it is reconnected, and send those changes back in the most efficient way?</p>
<p>Taking it to extreme, what happens when two product managers edit the same pieces of data? What happens when each have added a new product to which their client applications have assigned the same supposedly unique ID? The system needs to reconcile those potentially conflicting changes &#8211; and very quickly this becomes a non-trivial task.</p>
<p>In the broader computing world, these challenges are common and have been frequently, and successfully, addressed. Many proven solutions exist for synchronization in the realms of distributed file systems, versioned source control, disk, database and site mirroring and so on &#8211; and even to manage our MP3 collections. But what is new is that this will soon becoming a challenge that web developers will need to tackle, and it is a challenge that might be unfamiliar and daunting to many.</p>
<p>In the general case, of course, there is no single approach that will answer all these questions. Effective synchronization across a &#8216;split stack&#8217; architecture will depend very much upon the sort of data that is being manipulated and what the application is setting out to achieve.</p>
<p>Frameworks will certainly provide us with all the tools we need to implement the choices we make. But considering these synchronization-related scenarios and use-cases will be an increasingly important part of bringing compelling applications to users in increasingly diverse contexts. Reconciliation will lie at the heart of how we bring complex applications to life &#8211; not just an after-thought.</p>
<p>The web is no longer one of documents or of simple uni-directional data: it is fast becoming a web of synchronization. And I fear it might not be as easy as we think. As developers, we all need to go into this new world with our eyes wide open and be prepared for new challenges around the corner.</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2010/12/a-web-of-sync/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Sencha Touch + DeviceMotion APIs (= a small plastic toy)</title>
		<link>http://tripleodeon.com/2010/12/sencha-touch-devicemotion-apis-small-plastic-toy/</link>
		<comments>http://tripleodeon.com/2010/12/sencha-touch-devicemotion-apis-small-plastic-toy/#comments</comments>
		<pubDate>Wed, 01 Dec 2010 06:38:03 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=574</guid>
		<description><![CDATA[Here at Sencha Towers, we&#8217;ve been having a bunch of fun with the new accelerometer &#038; gyroscope APIs in the iOS4.2 web browser. Rob Dougan has put together a tilt-controlled list and Ariya Hidayat a box of marbles. Both require an updated iPhone or iPod Touch (although Ariya&#8217;s also works on a MacBook Pro if [...]]]></description>
			<content:encoded><![CDATA[<p>Here at Sencha Towers, we&#8217;ve been having a bunch of fun with the new accelerometer &#038; gyroscope APIs in the iOS4.2 web browser.<br />
<span id="more-574"></span><br />
Rob Dougan has put together a <a href='http://b.rwd.me/'>tilt-controlled list</a> and Ariya Hidayat a <a href='http://ariya.github.com/js/marblebox/'>box of marbles</a>. Both require an updated iPhone or iPod Touch (although Ariya&#8217;s also works on a MacBook Pro if you use the Chrome browser).</p>
<p>The APIs are pretty easy to use, and seem to follow the W3C (<a href='http://dev.w3.org/geo/api/spec-source-orientation.html'>draft</a>) standards.</p>
<p>I thought I would have a go to, and so I wrote a <a href="http://tinyurl.com/ioslide">small Sencha Touch app</a> that mimics one of those small sliding puzzles we all had as kids &#8211; but where the tiles are moved not with touch gestures, but by sliding the pieces under gravity.</p>
<p><img src="http://tripleodeon.com/wp-content/uploads/2010/12/ioslider-500x266.png" alt="" title="ioslider" width="500" height="266" class="alignnone size-large wp-image-575" /></p>
<p>From a Sencha Touch point of view, I&#8217;ve tried to use a best-practice application structure, and both the grid and the tiles are Ext.Panels (which makes them easy to treat in an object-oriented way and, in the case of the tiles, instantiate arbitrarily).</p>
<p>I have set up Ext.EventManager listeners for devicemotion and deviceorientation events, and fortunately, the callback can access the underlying browser event to get the motion-based properties I need.</p>
<p>The tiles themselves are placed on the grid using CSS transforms, rather than top/left positioning, along the lines of:</p>
<pre>Ext.Element.cssTransform(this.getEl(), {translate: [x, y]});</pre>
<p> This makes coding the sliding movement unbelievably easy: I simply have to change the transformation to where I want the tile to move to, and then</p>
<pre>-webkit-transition:-webkit-transform .8s ease-in;</pre>
<p>does the gentle slide. Wow. Transitions and transforms have been a spectacular epiphany for me in the last few months.</p>
<p>One catch with web-based tilt control: tip the device more than 45 degrees, and you might find yourself switching between portrait and landscape mode. I don&#8217;t know of a way to disable this in Mobile Safari.</p>
<p>The issue with this is that the co-ordinate system of the device&#8217;s physical orientation does not rotate, but the web page does. So in my case, I check the window&#8217;s current rotation and subtract the appropriate multiple of 90 degrees so that the elements still slide in the direction expected for the device&#8217;s physical position.</p>
<p>To test it out, get an iPhone or iPod Touch with iOS4.2 installed. Put the device level on a horizontal surface, go to <a href="http://tinyurl.com/ioslide">http://tinyurl.com/ioslide</a> &#8211; then tilt the device about 15 degrees in various directions to make the tiles slide.</p>
<p>Also feel free to look at (and be tempted to improve!) the code. Small, simple, and good fun: let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2010/12/sencha-touch-devicemotion-apis-small-plastic-toy/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>tinySrc is now part of Sencha</title>
		<link>http://tripleodeon.com/2010/12/tinysrc-is-now-part-of-sencha/</link>
		<comments>http://tripleodeon.com/2010/12/tinysrc-is-now-part-of-sencha/#comments</comments>
		<pubDate>Wed, 01 Dec 2010 00:58:37 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Mobile Web]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://tripleodeon.com/?p=570</guid>
		<description><![CDATA[I&#8217;m extremely pleased to announce that one of my projects, tinySrc, has become part of Sencha, alongside such awesome projects as Raphaël JS, jQTouch, Connect, and InfoVis &#8211; as well, of course, as the company&#8217;s core products like Ext JS and the revolutionary mobile framework Sencha Touch. tinySrc has been going from strength to strength over the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m extremely pleased to announce that one of my projects, <a href="http://tinysrc.net/">tinySrc</a>, has become part of <a href="http://sencha.com">Sencha</a>, alongside such awesome projects as <a href="http://raphaeljs.com/">Raphaël JS</a>, <a href="http://jqtouch.com/">jQTouch</a>, <a href="https://github.com/senchalabs/Connect">Connect</a>, and <a href="http://thejit.org/">InfoVis</a> &#8211; as well, of course, as the company&#8217;s core products like <a href="http://www.sencha.com/products/js/">Ext JS</a> and the revolutionary mobile framework <a href="http://www.sencha.com/products/touch/">Sencha Touch</a>.<br />
<span id="more-570"></span><br />
tinySrc has been going from strength to strength over the last 18 months. I think its underlying growth is a reflection of the huge interest in developing for the mobile medium. Mobile web and app developers quickly realize they need to make sure that their graphical experience is correctly formatted for a wide range of screen-sizes and form factors.</p>
<p>There are no intentions to change the API and the way in which the tinySrc runs, so you can continue to use it with confidence.</p>
<p>You&#8217;ll see lots of new cool features coming in the future though: the service has some exciting times ahead of it!</p>
]]></content:encoded>
			<wfw:commentRss>http://tripleodeon.com/2010/12/tinysrc-is-now-part-of-sencha/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
