<?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>WhitherApps</title>
	<atom:link href="http://whitherapps.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://whitherapps.com</link>
	<description>A bandwagon-busting mobile experiment</description>
	<lastBuildDate>Tue, 05 Oct 2010 01:12:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>BBC News, pt IV</title>
		<link>http://whitherapps.com/bbc-news-pt-iv/</link>
		<comments>http://whitherapps.com/bbc-news-pt-iv/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 01:06:15 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[BBC News]]></category>

		<guid isPermaLink="false">http://whitherapps.com/?p=67</guid>
		<description><![CDATA[OK, after yet another long gap, I&#8217;m back. But the hiatus was worth it. I&#8217;m excited to announce that I&#8217;ve a new job &#38; will soon be working with those smart chaps at Sencha&#8230; so hopefully there will be lots more of this sort of thing to come. We promised ourselves that we would have [...]]]></description>
			<content:encoded><![CDATA[<p>OK, after yet another long gap, I&#8217;m back. But the hiatus was worth it. I&#8217;m excited to announce that I&#8217;ve a new job &amp; will soon be working with those smart chaps at <a href="http://sencha,com">Sencha</a>&#8230; so hopefully there will be lots more of this sort of thing to come.</p>
<p>We promised ourselves that we would have fun with some CSS and get this application looking a little smarter. It certainly isn&#8217;t as glossy as the real thing yet. So here&#8217;s our mission statement for this installment: &#8220;indistinguishable or your money back&#8221;.</p>
<p>We have all the structural areas of the page in place, and the basic user experience &#8211; click a thumbnail, get an article. So there should be enough there to be able to style up.</p>
<p>Before we start: one caveat. I&#8217;d quite like to see if we can avoid having to use any external resources for this app &#8211; apart from the BBC material itself of course! In other words, every button, gradient and shadow you see has to be articulated within our single HTML page. Fortunately for us, the WebKit support for CSS3 styling (or at least, its -webkit- variants) gives us a reliable way to do most, if not all, of this. Let&#8217;s see.</p>
<p>Let&#8217;s start at the top of the page, where we have a dark red bar across the top of the app. Until now, it&#8217;s been styled with:</p>
<pre>background:#ff0000;</pre>
<p>&#8230;which is not quite the craftsmanship I have in mind.</p>
<p>I&#8217;ve taken a crop of the top of the application so we can do a proper analysis of it. (Is it me or is the BBC logo not quite centered with the clock?)</p>
<p><a rel="attachment wp-att-72" href="http://whitherapps.com/bbc-news-pt-iv/wa41/"><img class="alignnone size-full wp-image-72" title="wa41" src="http://whitherapps.com/wp-content/uploads/2010/10/wa41.png" alt="" width="138" height="70" /></a></p>
<p>The #bbc_controls box is 44 pixels high, which is the upper pink border all the way down to the dark burgundy shadow. The main red part of it has a gentle gradient. It would be very easy to crop this image and use it as a background, but let&#8217;s see if we can do it with some CSS. First we need to sample the colors used. To start with, I&#8217;ll just use the Apple Digital Color Meter tool to sample some key colors.</p>
<p>The RGB of the pink border at the top is #e36d51. The two lines of shadow at the bottom are #7c110f and #37080a. The red in between goes from #bd1c08 at the top down to #990700 at the bottom.</p>
<p>As an aside&#8230; is the gradient linear across the middle 41 pixels of the bar? The histogram for the gradient looks like this:</p>
<p><a rel="attachment wp-att-75" href="http://whitherapps.com/bbc-news-pt-iv/wa42/"><img class="alignnone size-full wp-image-75" title="wa42" src="http://whitherapps.com/wp-content/uploads/2010/10/wa42.png" alt="" width="172" height="129" /></a></p>
<p>Apparently not. There are 10 pixels at the bottom of the bar that are the same color (#990700) and the gradient is only at the top of the bar. Even that is not quite linear, but let&#8217;s pretend it is for now, yes?</p>
<p>So anyway, let&#8217;s do the CSS for this bar. I&#8217;m going to use WebKit&#8217;s -webkit-gradient CSS property, which is an alternative to having an image URL for the background. I&#8217;ve left the largest slab of color (#990700) as the explicit background-color. At least non-WebKit browsers will have something nice to show.</p>
<p>So, as a first stab:</p>
<pre>background-color:#990700;
background-image:-webkit-gradient(linear, left top, left bottom,
  from(#bd1c08), to(#990700)
);</pre>
<p>This provides a smooth gradient from the top of the bar to the bottom:</p>
<p><a rel="attachment wp-att-76" href="http://whitherapps.com/bbc-news-pt-iv/wa43/"><img class="alignnone size-full wp-image-76" title="wa43" src="http://whitherapps.com/wp-content/uploads/2010/10/wa43.png" alt="" width="28" height="44" /></a></p>
<p>But we need to add some color stops that tell the property that the gradient only goes about two thirds of the way down. Color-stops, unfortunately, are seemingly only specified in percentage, rather than pixel distances. We want the gradient to stop 11 pixels from the bottom of the bar: handily this exactly 75% of the way down.</p>
<pre>background-image:-webkit-gradient(linear, left top, left bottom,
  from(#bd1c08), color-stop(0.75, #990700), to(#990700)
);</pre>
<p>While we are at it, we might even be able to use the gradient stops to do the highlights and shadows at the top and bottom of the bar. Each pixel is 1/44 (2.27%) of the bar. So&#8230;</p>
<pre>background-image:-webkit-gradient(linear, left top, left bottom,
  from(#e36d51), color-stop(0.0227, #e36d51),
  color-stop(0.0227, #bd1c08), color-stop(0.7500, #990700),
  color-stop(0.9545, #990700), color-stop(0.9545, #7c110f),
  color-stop(0.9772, #7c110f), color-stop(0.9772, #37080a),
  to(#37080a)
);</pre>
<p>Doubled-up color-stops allow you to disjoin the gradient. So we have a one pixel line at the top, then the gradient, then the solid slab, and then two distinctly-colored lines at the bottom. Obviously these percentages only work when the height of the bar is precisely 44 pixels, but we&#8217;ve ensured that elsewhere in the CSS.</p>
<p>How does it look?</p>
<p><a rel="attachment wp-att-77" href="http://whitherapps.com/bbc-news-pt-iv/wa44/"><img class="alignnone size-full wp-image-77" title="wa44" src="http://whitherapps.com/wp-content/uploads/2010/10/wa44.png" alt="" width="28" height="44" /></a></p>
<p>As they say in New Zealand: sweet as.</p>
<p>The gray ticker bar beneath the top bar doesn&#8217;t have a gradient, but it does have a white highlight at the top. We can just do that with a border (and shrink the box&#8217;s height by one pixel to account for it:</p>
<pre>#bbc_ticker {
  ...
  height:30px;
  border-top:1px solid #ffffff;
}</pre>
<p>Before we move on to more gradients and coloring in the selector panels, let&#8217;s take a look at some of the typography. We haven&#8217;t specified any fonts yet, and it certainly shows. Now, I&#8217;m not the world&#8217;s greatest font spotter, but there aren&#8217;t that many native on the iPad, so figuring out which to use shouldn&#8217;t be that hard. We&#8217;re aiming for:</p>
<p><a rel="attachment wp-att-78" href="http://whitherapps.com/bbc-news-pt-iv/wa45/"><img class="alignnone size-full wp-image-78" title="wa45" src="http://whitherapps.com/wp-content/uploads/2010/10/wa45.png" alt="" width="256" height="169" /></a></p>
<p>The caps are just about 9 pixels high. (It makes it easier to check you&#8217;ve got the right font when you&#8217;re comparing like sizes). I thought it was Arial at first, but Helvetica seems to be more or less the best match. The fonts seem to be the same on both the section headings (h2) and article headings (h3), except that the former is capitalized. Of course we can do that in CSS too &#8211; and we also tweak the kerning and spacing slightly to make the fonts line up as closely as possible with the original.</p>
<pre>#bbc_article_selectors * {
  font-family:Helvetica, Arial;
  font-weight:normal!important;
  font-size:12px!important;
  letter-spacing:0.02em;
  line-height:16px;
}
#bbc_article_selectors h2 {
  display:none;
  text-transform: uppercase;
  line-height:8px;
  padding-top:7px;
}</pre>
<p>Now is a good time to style up those thumbnail boxes too. They have a fine gray line around them (#464646 on 3 sides, #595959 on the bottom) with a very slight radius, and a background of #222222. There&#8217;s a small inset drop shadow. The images themselves have a faint #3A3A3A border around them.</p>
<p>Here&#8217;s something very annoying: the images that come from the BBC are 105px by 79px: which is exactly the size that they appear on the app &#8211; but with the border included. Should I shrink the image down 2 pixels in each direction so that the border makes up the extra? Or is there a CSS3 way of placing an image border *over* the edge of an image? I don&#8217;t know one, so I&#8217;ve had to slightly shrink the image to fit the box. The CSS now looks something like:</p>
<pre>#bbc_article_selectors nav a {
  display:inline-block;
  width:105px; height:127px;
  margin:4px 5px 6px 5px;
  padding:5px;
  overflow:hidden;
  background:#222222;
  border:1px solid #464646;
  border-bottom-color:#595959;
  -webkit-border-radius:2px;
  -webkit-box-shadow: inset 0px 0px 2px #000;
}
#bbc_article_selectors img {
  border:1px solid #3A3A3A;
  width:103px;
  height:77px;
}</pre>
<p>And the result is below. One is the native app, and one is the web app. Can you tell which is which?</p>
<p><a rel="attachment wp-att-79" href="http://whitherapps.com/bbc-news-pt-iv/wa46/"><img class="alignnone size-full wp-image-79" title="wa46" src="http://whitherapps.com/wp-content/uploads/2010/10/wa46.png" alt="" width="250" height="162" /></a></p>
<p><a rel="attachment wp-att-80" href="http://whitherapps.com/bbc-news-pt-iv/wa47/"><img class="alignnone size-full wp-image-80" title="wa47" src="http://whitherapps.com/wp-content/uploads/2010/10/wa47.png" alt="" width="250" height="162" /></a></p>
<p>Oh, and hey &#8211; I feel like doing the logo:</p>
<pre>&lt;div id="bbc_logo"&gt;&lt;span class="bbc_bbc"&gt;B&lt;/span&gt;&lt;span class="bbc_bbc"&gt;B&lt;/span&gt;&lt;span class="bbc_bbc"&gt;C&lt;/span&gt; News&lt;/div&gt;

#bbc_logo {
  position:absolute;
  left:446px;
  top:14px;
  line-height:18px;
  font-family:"Gill Sans";
  font-size:19px;
  text-transform:uppercase;
}
#bbc_logo .bbc_bbc {
  display:inline-block;
  width:18px;
  height:18px;
  text-align:center;
  margin-right:3px;
  background:#ffffff;
  color: #990700;
}</pre>
<p>Might not get past the strictest of brand police, but pretty close, no?</p>
<p><a rel="attachment wp-att-81" href="http://whitherapps.com/bbc-news-pt-iv/wa48/"><img class="alignnone size-full wp-image-81" title="wa48" src="http://whitherapps.com/wp-content/uploads/2010/10/wa48.png" alt="" width="145" height="41" /></a></p>
<p>And we also need to do the refresh button. I was nearly stumped here, until I discovered the Unicode character &#8216;CLOCKWISE OPEN CIRCLE ARROW&#8217; (x21BB since you ask). This looks nice in the Arial font. Throw in a few shadows and gradients:</p>
<pre>&lt;a id="bbc_refresh" href="#"&lt;&amp;#x21BB;&lt;/a&gt;

#bbc_refresh {
  position:absolute;
  display:block; width:38px; height:24px;
  left:142px; top:10px;
  line-height:18px;
  text-align:center;
  font-family:"Arial";
  font-size:30px;
  text-decoration:none;
  color:#ffffff;
  border:solid 1px #880600;
  background-image:-webkit-gradient(linear, left top, left bottom,
    from(#c20c00), to(#a10800)
  );
  -webkit-border-radius:2px;
  -webkit-box-shadow: inset 0px 1px 1px #ff6666, 0px 1px 1px #bc0e05;
  text-shadow:0px -2px 1px #880600;
}</pre>
<p>And we have:</p>
<p><a rel="attachment wp-att-82" href="http://whitherapps.com/bbc-news-pt-iv/wa49/"><img class="alignnone size-full wp-image-82" title="wa49" src="http://whitherapps.com/wp-content/uploads/2010/10/wa49.png" alt="" width="52" height="39" /></a></p>
<p>Nice. Not too bad for an imageless element.</p>
<p>OK, I think I&#8217;ll leave it there for today &#8211; might just be in time for<a href="http://www.mobilemonday.us/?p=450"> Mobile Monday Silicon Valley</a>, who are debating this very topic tonight. Progress so far:</p>
<div id="attachment_83" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-83" href="http://whitherapps.com/bbc-news-pt-iv/wa410/"><img class="size-medium wp-image-83" title="wa410" src="http://whitherapps.com/wp-content/uploads/2010/10/wa410-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">Getting closer...</p></div>
<p>Next, we need to style up the articles themselves, and also sort out the portrait rotation. Back soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://whitherapps.com/bbc-news-pt-iv/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>BBC News, pt III</title>
		<link>http://whitherapps.com/bbc-news-pt-iii/</link>
		<comments>http://whitherapps.com/bbc-news-pt-iii/#comments</comments>
		<pubDate>Sat, 07 Aug 2010 23:51:13 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[BBC News]]></category>

		<guid isPermaLink="false">http://whitherapps.com/?p=48</guid>
		<description><![CDATA[There&#8217;s been a hiatus in our efforts to rewrite the BBC News app in HTML5 &#8211; no thanks to the odd tropical storm, a consuming day-job project, and kids who&#8217;ve decided that boomerang toucans take priority over their father&#8217;s Javascript hacking. So let&#8217;s get back to it. We left things at the point where we [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a hiatus in our efforts to rewrite the BBC News app in HTML5 &#8211; no thanks to the odd <a href="http://en.wikipedia.org/wiki/Hurricane_Alex_%282010%29">tropical storm</a>, a consuming <a href="http://ivyroot.com/">day-job project</a>, and kids who&#8217;ve decided that <a href="http://en.wikipedia.org/wiki/Angry_Birds">boomerang toucans</a> take priority over their father&#8217;s Javascript hacking. So let&#8217;s get back to it.</p>
<p>We <a href="/bbc-news-pt-ii/">left things</a> at the point where we had a static HTML skeleton that sort of looked like it could be the BBC News app if you squinted at it. Now it&#8217;s time to make it work.</p>
<p>To start with, we need to get our HTML file to be able to make calls to the BBC servers and retrieve JSON- and XML-based payloads. Immediately we run into a problem here, because browsers won&#8217;t make requests to different domains (or will, but probably won&#8217;t receive a successful response). I can&#8217;t upload my humble little HTML file onto the BBC servers, and of course I can&#8217;t get them to respond with JSONP or play the cross-origin preflight request game.</p>
<p>So I need to do a little server-side proxying of my own. It seems that Safari refuses to set the user-agent header in AJAX calls anyway &#8211; and if you recall from our earlier discovery, that&#8217;s important for this app. The proxy will be able to do this user-agent rewriting for us too.</p>
<p>Since I&#8217;m running whitherapps.com on an nginx server, running such a proxy is incredibly easy. I&#8217;ve simply added this to the server&#8217;s config file:</p>
<pre>location /apps/bbc-news/proxy {
  resolver 8.8.8.8;
  proxy_pass $http_x_bbc_url;
  proxy_set_header User-Agent $http_x_bbc_ua;
}</pre>
<p>&#8230;which basically means that any request to http://whitherapps.com/apps/bbc-news/proxy will be proxied on to the URL present in the X-BBC-URL header (as resolved by Google&#8217;s DNS server), and the user-agent will be rewritten to whatever is in the X-BBC-UA header. (Not using nginx for your <em>own</em> web server? Why not?)</p>
<p>In the Javascript for the app, I&#8217;d better provide a small AJAX handler that sets these headers appropriately and calls back to a provided success function (with the response text) or a failure function (with the XHR instance) as required. I also append a timestamp to the end of the URL, since I want to be sure that the browser doesn&#8217;t cache it, confused by my burying of the changing URL inside the headers.</p>
<pre>var BBC_PROXY = "/apps/bbc-news/proxy";
var BBC_USER_AGENT = "BBC News 1.2.1 (iPad; iPhone OS 3.2; en_US)";
function bbcXhr(url, success, failure) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", BBC_PROXY + '?' + new Date().getTime(), true);
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
      if (xhr.status == 200) {
        success(xhr.responseText);
      } else {
        failure(xhr);
      }
    }
  }
  xhr.setRequestHeader("X-BBC-URL", url);
  xhr.setRequestHeader("X-BBC-UA", BBC_USER_AGENT);
  xhr.send("");
}</pre>
<p>(If I was the BBC and wanted to do this properly, I would simply need to alter this function and/or accept requests from other user-agents, and/or respond to cross-origin requests on these URLs&#8230; confusingly the app needs to access a range of different domains.)</p>
<p>So, with the app-to-server communication more or less in place, let&#8217;s start using it.</p>
<p>If you recall from our original investigation into the app traffic, the first request is to a bootstrap URL that returns some helpful pointers in a JSON file. We need to call that when the app is refreshed (or indeed when it first loads up):</p>
<pre>var BBC_BOOTSTRAP = "http://www.live.bbc.co.uk/moira/feeds/ipad/news/en/v1";
function bbcRefresh() {
  bbcXhr(BBC_BOOTSTRAP, function(responseText) {
    var bootstrap = JSON.parse(responseText);
  }, function(xhr) {});
}

addEventListener("load", function() {
  bbcRefresh();
}, false);</pre>
<p>While we are at it, let&#8217;s create a crude refresh button in the control bar at the top of the app. That should help with testing things:</p>
<pre>[&lt;a href='#' id='bbc_refresh'&gt;Refresh&lt;/a&gt;]</pre>
<p>And in the page load event, add a handler for it:</p>
<pre>document.getElementById('bbc_refresh').onclick = function() {
  bbcRefresh();
  return false;
};</pre>
<p>Put those in our app file, and… yes, it works: I get the slab of JSON back, and it&#8217;s parsed into the bootstrap object by the JSON parser available in Safari &#8211; which, although I suppose I do trust the BBC, feels far safer than eval().</p>
<p>Now, there&#8217;s a bunch of interesting things in that structure, such as links to privacy URLs and the like, but for now, we&#8217;ll just iterate through the list of feeds. These will populate the sections of the UI.</p>
<p>I&#8217;ve noticed that the real BBC News app loads the news from the top six or so categories preemptively, but when you click on the other, slightly more obscure categories (like the one for that little-known place, &#8220;Europe&#8221;), it goes and fetches them on-demand. I presume this is the default=true property set on the major feeds and that the other feeds just don&#8217;t work if you&#8217;ve never opened them and then go offline.</p>
<p>Rather than taking the feed information and creating the UI elements directly, I&#8217;ve decided I&#8217;ll do it in two logical steps. First get the feeds and stash the data about them in a local data store, and then secondly construct the UI from the contents of the data store. This is primarily to cater for users who go offline during the life of the app, or who start it up in offline mode and want to see what was there last time.</p>
<p>In fact, now I think about it, the easiest way to do this might be to wrap the local storage functionality in and around the AJAX function. We&#8217;ll key data in the browser&#8217;s local datastore off the URL. If the device is online, the browser gets fresh data, otherwise it gets it from the local storage.</p>
<p>So here&#8217;s a slightly beefier AJAX function that makes this happen behind the scenes:</p>
<pre>function bbcCachedXhr(url, success, failure) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", BBC_PROXY + '?' + new Date().getTime(), true);
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
      if (xhr.status == 200) {
        localStorage.removeItem(url);
        localStorage.setItem(url, xhr.responseText)
        success(xhr.responseText);
      } else {
        responseText = localStorage.getItem(url);
        if (responseText != null) {
          success(responseText);
        } else {
          failure(xhr);
        }
      }
    }
  }
  xhr.setRequestHeader("X-BBC-URL", url);
  xhr.setRequestHeader("X-BBC-UA", BBC_USER_AGENT);
  xhr.send("");
}</pre>
<p>It still calls either a success or failure function, but the former will be called even if the AJAX request is unsuccessful (for whatever reason) <em>but</em> the data was still in the local storage.</p>
<p>This approach works for the BBC app because there are a relatively small number of URLs in play: all the articles for a given section are in one single structure at a stable URL. If there had been a URL for each article, I might have been worried about the cache filling up after a few weeks… but this seems OK for now. This week&#8217;s 10 articles will simply overwrite all of last week&#8217;s, since they are keyed off the same URL.</p>
<p>I have an idea that this function will be very useful both here and in future WhitherApps project.</p>
<p>Right then. Let&#8217;s take the feeds (either just fetched, or rescued from local storage), fetch the articles and create the UI. In part 2, we set up some dummy category panels. Let&#8217;s remove them from the static HTML and simple leave their containers:</p>
<pre>&lt;nav id='bbc_category_selector'&gt;&lt;/nav&gt;
&lt;div id='bbc_article_selectors'&gt;&lt;/div&gt;</pre>
<p>So we need a function that creates all the pieces needed for a given feed category selector. There are two titles (one which appears in the portrait mode, and one in landscape), and the selector panel itself. This function creates all three &#8211; if they are not present &#8211; and returns the main selector panel.</p>
<pre>function bbcEnsureSelector(title) {
  var id = title.replace(/[^a-zA-Z0-9_]/g, '_')
  if (document.getElementById(id+'-t1') == null) {
    var selectorT1 = bbcCreateNode('a', id+'-t1', title);
    document.getElementById('bbc_category_selector').appendChild(selectorT1);
  }
  if (document.getElementById(id+'-t2') == null) {
    var selectorT2 = bbcCreateNode('h2', id+'-t2', title);
    document.getElementById('bbc_article_selectors').appendChild(selectorT2);
  }
  var selector = document.getElementById(id)
  if (selector == null) {
    selector = bbcCreateNode('nav', id);
    document.getElementById('bbc_article_selectors').appendChild(selector);
  }
  return selector;
}

function bbcCreateNode(tag, id, innerText) {
  var node = document.createElement(tag);
  if (id!=null) {
    node.id = id;
  }
  if (innerText!=null) {
    node.appendChild(document.createTextNode(innerText));
  }
  return node;
}</pre>
<p>This may look a little clumsy, but it does include making a safe unique ID (from the title) and using DOM methods to ensure the resulting markup structure is well formed. (I&#8217;m thinking that a few of these functions might get moved into a separate library at some point.)</p>
<p>Then, as just after we parse the bootstrap in the refresh function, let&#8217;s call this for each feed:</p>
<pre>var feeds = bootstrap.feeds[0].feeds;
for (var f in feeds) {
  var feed = feeds[f];
  var selector = bbcEnsureSelector(feed.title);
}</pre>
<p>Seems to work (&#8220;At last! A screenshot!&#8221;):</p>
<div id="attachment_51" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-51" href="http://whitherapps.com/bbc-news-pt-iii/img_0018/"><img class="size-medium wp-image-51" title="IMG_0018" src="http://whitherapps.com/wp-content/uploads/2010/08/IMG_0018-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">Category titles appearing in the left sidebar</p></div>
<p>Now, each of these category selector panels need to have the article thumbnails placed in them. This should happen when the bootstrap is loaded (for those that have default=true in the bootstrap, it seems), and also when a selector is shown that hasn&#8217;t previously been populated. So we&#8217;ll do it in a separate function that can be called in either case.</p>
<pre>function bbcPopulateSelector(selector, url) {
  bbcCachedXhr(url, function(responseText){
    var feed = new DOMParser().parseFromString(responseText, 'text/xml').documentElement;
    if (feed.nodeName=='feed') {
      var feedId = feed.getElementsByTagName('id')[0].textContent;
      var entries = feed.getElementsByTagName('entry');
      for (e=0; e &lt; entries.length; e++) {
        entry = entries[e];
        var entryId = entry.getElementsByTagName('id')[0].textContent;

        var id = feedId + '-' + entryId;
        var thumbnail = bbcCreateNode('a', id+'-thumbnail');

        var thumbnailImage = bbcCreateNode('img', '');
        thumbnailImage.src = bbcRewriteMediaUrl(
          entry.getElementsByTagNameNS('*', 'thumbnail')[0].getAttribute('url'),
          entryId
        );
        thumbnail.appendChild(thumbnailImage);

        var thumbnailTitle = bbcCreateNode('h3', null,
          entry.getElementsByTagName('title')[0].textContent
        );
        thumbnail.appendChild(thumbnailTitle);

        var content = entry.getElementsByTagName('content')[0];
        var contentNodes = content.childNodes;
        var article = bbcCreateNode('div', id+'-article');
        for (var i=0; i &lt; contentNodes.length; i++) {
          article.appendChild(document.importNode(contentNodes[i], true));
        }

        thumbnail.article = article;

        selector.appendChild(thumbnail);
      }
    }
  }, function(xhr){});
}

function bbcRewriteMediaUrl(url, base) {
  if (url.substr(0, 11)!='bbcimage://') {
    return url;
  }
  url = url.substr(11);
  url = decodeURIComponent(url);
  if (url.substr(0, base.length)!=base) {
    return url;
  }
  url = url.substr(base.length);
  url = url.replace('{device}', 'ipad');
  return 'http://' + url;
}</pre>
<p>So what&#8217;s going on here? Firstly we call the feed URL (again, cached via localStorage if offline), and then parse the results. For each article entry in the feed, we get its ID, and create a thumbnail link that will sit in the article-selecting category tray. We use the thumbnail image to actually get a picture for it (using the bbcRewriteMediaUrl function to transform its rather strange syntax, as observed in <a href="http://whitherapps.com/bbc-news/">part I</a>), and add the title of the article beneath it. We have to use getElementsByTagNameNS to get the thumbnail image URL, due to the media RSS namespace on that element.</p>
<p>Then, embedded in the Atom is a slab of HTML under the &lt;content&gt; element for the article itself. We get its children out and lash them into a container held under the thumbnail&#8217;s DOM using the &#8216;article&#8217; attribute. I&#8217;m not entirely sure if this is the most kosher way to do things, but it will do for now. Basically we want it in a place where we can switch it into the main reading panel whenever someone clicks on &#8211; or rather, touches &#8211; the thumbnail.</p>
<p>After the selector panel is known to be in place in the refresh sequence, let&#8217;s call this with URL of every default feed. We have to use &#8216;default&#8217; as an array index when examining the feed object, rather than an object property, because it&#8217;s a reserved word in Javascript and Safari complains otherwise:</p>
<pre>if (feed['default']) {
  bbcPopulateSelector(selector, feed.feed_url);
}</pre>
<p>OK, so let&#8217;s run that up and see what happens. Hopefully, the bootstrap and then the default feeds will be fetched. We should then see a panel appear for each of the categories, and the images and titles of the articles within them. And…</p>
<div id="attachment_53" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-53" href="http://whitherapps.com/bbc-news-pt-iii/img_0019/"><img class="size-medium wp-image-53" title="IMG_0019" src="http://whitherapps.com/wp-content/uploads/2010/08/IMG_0019-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">The thumbnails ...not looking quite right</p></div>
<p>Well, OK. It did what I claimed, more or less, but we obviously have a few cosmetic problems here. Our category trays are of a constrained height, and the thumbnails are not at all styled to fit them. But it shouldn&#8217;t take a lot of CSS to sort this out. Firstly, let&#8217;s sort out the tray overflow, and then the display layout of the thumbnails themselves. (We&#8217;ll deal with making scrolling look nice in due course &#8211; the iPad doesn&#8217;t show scroll bars for overflow:scroll, although you <em>can</em> use two fingers to move the trays left and right).</p>
<p>So let&#8217;s make the following small additions to the CSS:</p>
<pre>#bbc_article_selectors nav {
  ...
   overflow-x:scroll; overflow-y:hidden;
   white-space:nowrap;
}
#bbc_article_selectors nav a {
  display:inline-block;
  width:115px; height:137px;
  margin:5px;
  white-space:normal;
  overflow:hidden;
  background:#000000;
  border:1px solid #ffffff;
}</pre>
<p>What a difference that makes. Arnie looks a bit odd (which is surely setting somebody up for a punchline) for an as-yet-unknown reason… but most of the thumbnails now look respectable. We&#8217;ll sort out the typography soon enough, but even with the default &lt;h3&gt; styling we can still read most of the headlines.</p>
<div id="attachment_54" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-54" href="http://whitherapps.com/bbc-news-pt-iii/img_0020/"><img class="size-medium wp-image-54" title="IMG_0020" src="http://whitherapps.com/wp-content/uploads/2010/08/IMG_0020-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">Thumbnails looking a little better</p></div>
<p>Of course we should make these &lt;a&gt; thumbnails actually do something. After all, we have the text of the article hanging off an expando DOM property, so let&#8217;s put it to good use. We can bind an article display function onto its click event at the end of the bbcPopulateSelector function. It&#8217;s tempting to use an anonymous function here, but I think I&#8217;ll need this in other places eventually (since in the app you can swipe articles to change them too).</p>
<pre>...
  thumbnail.onclick = bbcDisplayArticle;
...

function bbcDisplayArticle(event, thumbnail) {
  if (thumbnail==null) {
    thumbnail = this;
  }
  var articlePanel = document.getElementById('bbc_article');
  articlePanel.innerHTML = '';
  articlePanel.appendChild(thumbnail.article);
  return false;
}</pre>
<p>Crude for now, but this latter function will be a good place to put in some swanky page sliding animation at some point.</p>
<p>So at least we can now pull up articles:</p>
<div id="attachment_55" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-55" href="http://whitherapps.com/bbc-news-pt-iii/img_0021/"><img class="size-medium wp-image-55" title="IMG_0021" src="http://whitherapps.com/wp-content/uploads/2010/08/IMG_0021-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">Houston, we have an article</p></div>
<p>Lovely. Seems to be one final thing to do though: rewrite the images that appear in articles. It makes sense to do this once &#8211; probably at the time we are stealing the article out of the Atom DOM and putting it into the HTML one. Let&#8217;s just do a quick scan for &lt;img&gt; tags and rewrite their src attributes, just before the importNode function puts them into the DOM (this means that Safari won&#8217;t try to go and get them before we can get them into the right syntax).</p>
<pre>var contentImages = content.getElementsByTagName('img');
for (var i=0; i &lt; contentImages.length; i++) {
  contentImages[i].src = bbcRewriteMediaUrl(contentImages[i].src, entryId);
}</pre>
<p>It turns out that some of the images are placeholders for BBC video files too: these are &lt;a&gt; tags with bbcvideo:// schemes and bandwidth metadata. Let&#8217;s look for those too, and enhance our media URL rewriter:</p>
<pre>var contentVideos = content.getElementsByTagName('a');
for (var i=0; i &lt; contentVideos.length; i++) {
  contentVideos[i].href = bbcRewriteMediaUrl(contentVideos[i].href, entryId);
}

if (url.substr(0, 11)!='bbcimage://' &amp;&amp;
    url.substr(0, 11)!='bbcvideo://') {
...
   url = url.replace('{bandwidth}', 'wifi');
...</pre>
<p>There&#8217;s more to the video thing than meets the eye. If you try the app you&#8217;ll be confronted with a cryptic MP4 URL in a manifest of some sort, and so I&#8217;ll need to do a bit more hacking to get the videos showing. Something to do with British TV license payers or some such nonsense. But at least we now have images within the articles:</p>
<div id="attachment_56" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-56" href="http://whitherapps.com/bbc-news-pt-iii/img_0022/"><img class="size-medium wp-image-56" title="IMG_0022" src="http://whitherapps.com/wp-content/uploads/2010/08/IMG_0022-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">Articles with pictures (just don&#39;t click on the video links!)</p></div>
<p>And, if you compare it with a screen shot of the real thing, you&#8217;ll see we&#8217;re actually not doing too badly:</p>
<div id="attachment_57" class="wp-caption alignnone" style="width: 485px"><a rel="attachment wp-att-57" href="http://whitherapps.com/bbc-news-pt-iii/img_0023/"><img class="size-medium wp-image-57" title="IMG_0023" src="http://whitherapps.com/wp-content/uploads/2010/08/IMG_0023-475x356.png" alt="" width="475" height="356" /></a><p class="wp-caption-text">The real thing, earlier today</p></div>
<p>That&#8217;s it for this time. But we have an app you can just about use. Please check it out on your iPads <a href="/apps/bbc-news/pt3.html">here</a> (but don&#8217;t all go too crazy at the same time, since it&#8217;s using my server as the proxy!) and see what you think. Yes, I know the portrait version doesn&#8217;t work yet, and the scrolling is pretty poor&#8230; but hey, come on.</p>
<p>In the next episode, after all this heavy lifting, I think I deserve to play around with some CSS. Lots of lovely -webkit-gradient coming up (I think that&#8217;s what you were all waiting for, anyway).</p>
<p>Back soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://whitherapps.com/bbc-news-pt-iii/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>BBC News, pt II</title>
		<link>http://whitherapps.com/bbc-news-pt-ii/</link>
		<comments>http://whitherapps.com/bbc-news-pt-ii/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 05:21:47 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[BBC News]]></category>

		<guid isPermaLink="false">http://whitherapps.com/?p=33</guid>
		<description><![CDATA[In part two of our attempt to rewrite the BBC News app with web technology, we&#8217;re going to move onto the page structure itself. Some of you may have been left cold by last week&#8217;s trawl through what was happening behind the scenes, so let&#8217;s get up front again, and try and at least capture [...]]]></description>
			<content:encoded><![CDATA[<p>In part two of our attempt to rewrite the <a href="http://itunes.apple.com/ie/app/bbc-news/id364147881?mt=8">BBC News app</a> with web technology, we&#8217;re going to move onto the page structure itself. Some of you may have been left cold by <a href="/bbc-news">last week&#8217;s</a> trawl through what was happening behind the scenes, so let&#8217;s get up front again, and try and at least capture the main UI elements of the app in both portrait and landscape mode.</p>
<p>At this point, I am going to work with a single static HTML file. I&#8217;m not going to be pulling any dynamic content yet, and nor am I going to confuse things by trying to get too clever too soon. Hopefully a simple file will make it easier to understand my thought process.</p>
<p>The first thing to notice when looking at the app is that the landscape/portrait rotation changes the layout quite considerably. So most of what we&#8217;ll try to do first is understand how that can be done elegantly with a bit of CSS and maybe Javascript. Although the page as a whole looks quite different, the same panels are more or less present, so it&#8217;s more a matter of moving things around than changing functionality fundamentally.</p>
<h2>Page topography</h2>
<p>If you have the app open in front of you, take a look at how it&#8217;s laid out.</p>
<div id="attachment_26" class="wp-caption alignnone" style="width: 366px"><a href="http://whitherapps.com/bbc-news/bbc-portrait/" rel="attachment wp-att-26"><img src="http://whitherapps.com/wp-content/uploads/2010/06/bbc-portrait-356x475.png" alt="" title="bbc-portrait" width="356" height="475" class="size-medium wp-image-26" /></a><p class="wp-caption-text">The BBC News iPad app in portrait mode</p></div>
<p>The portrait mode of the app is basically a series of horizontal panels, starting with the red control bar at the top. It has a 1px highlight at the top, 41px of slight gradient red, then 2px of dark shadow at the bottom. Beneath this is a grey bar continent the news ticker. It also has a 1px highlight at the top and then 30px of solid grey. Then there is the category selector (&#8216;Top Stories&#8217;, &#8216;Americas&#8217; and so on), which is 36px of solid black. After this is the news story selector: 152px of dark gray, with a 1px border at the bottom. Finally we&#8217;re into the page itself, 614px high, and scrollable. At the end of the page is a fixed 90px ad (although not always), and a 36px footer, containing a horizontal scroll indicator.</p>
<p>(Let&#8217;s just check all that adds up. 1,004px, which, yes, with the 20px iPad bar at the top of the screen gives us the device&#8217;s full 1024px).</p>
<div id="attachment_25" class="wp-caption alignnone" style="width: 485px"><a href="http://whitherapps.com/bbc-news/bbc-landscape/" rel="attachment wp-att-25"><img src="http://whitherapps.com/wp-content/uploads/2010/06/bbc-landscape-475x356.png" alt="" title="bbc-landscape" width="475" height="356" class="size-medium wp-image-25" /></a><p class="wp-caption-text">The BBC News iPad app in landscape mode</p></div>
<p>In the landscape mode, we have a slightly more interesting layout. The control bar and news ticker are exactly the same as the portrait mode (although, of course, wider), followed by a 1px black rule. After that, on the left of the screen, 507px wide, we have the full height of the screen dedicated to combined category and news story selectors. These are 168px in height each, with a single 1px shadow underneath. Below these &#8216;open&#8217; panels are the headings of the other news sections. These include red bars (18px plus 2px highlight above and 2px shadow below) and larger collapsed panels (40px plus 2px highlight above and 2px shadow below). The very bottom of the left hand pane is a hatched area of 106px containing copyright and help links. Between the left and right panes is a single pixel grey separator, and then we have the main news page, 516px wide by 636px high. The 36px footer rounds off the right hand side of the page.</p>
<p>It&#8217;s interesting to note that the designers have actually made the main reading pane <em>narrower</em> in the landscape mode than in portrait.</p>
<p>At first blush, neither page layout alone seems too hard to reproduce with HTML and CSS. The challenge will probably be moving and removing portions around when the device rotates between the two.</p>
<h2>Some markup</h2>
<p>Let&#8217;s start with the outer part of the page&#8217;s HTML. We want to make sure it&#8217;s nice and standard, and declares viewport settings correctly.</p>
<pre>&lt;!DOCTYPE html&gt;
&lt;html&gt;
 &lt;head&gt;
  &lt;title&gt;BBC News&lt;/title&gt;
  &lt;meta name="apple-mobile-web-app-capable" content="yes"&gt;
  &lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no"&gt;
 &lt;/head&gt;
 &lt;body&gt;
  ...
 &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The apple-mobile-web-app-capable setting in the first &lt;meta&gt; tag removes the thick browser navigation bar from the page when the user has added it as a bookmark on their home screen. This will give us exactly the same real estate as the native client app (i.e. the whole page with the exception of the black 20px bar at the top). The second &lt;meta&gt; tag disables the pinch and zoom scaling on the page, which is not present on the app we are trying to emulate.</p>
<p>Taking the portrait view first, we&#8217;ll create some nice semantic panels for the structure of the page:</p>
<pre>&lt;div id='bbc_controls'&gt;BBC&lt;/div&gt;
&lt;div id='bbc_ticker'&gt;News ticker ...&lt;/div&gt;
&lt;div id='bbc_category_selector'&gt;Top Stories, Americas ...&lt;/div&gt;
&lt;div class='bbc_article_selector bbc_category_selected'&gt;War, Pestilence, Famine ...&lt;/div&gt;
&lt;div class='bbc_article_selector'&gt;Oil, Budgets, Taxes ...&lt;/div&gt;
&lt;div id='bbc_article'&gt;Blah blah ...&lt;/div&gt;
&lt;div id='bbc_banner_ad'&gt;Buy ...&lt;/div&gt;
&lt;div id='bbc_scroll_footer'&gt;o o o o&lt;/div&gt;
</pre>
<p>You&#8217;ll see I didn&#8217;t spend too much time on the copy. We just want to get the right panels in the right place. Also notice that I use HTML id attributes to strongly identify these panels as they are unique within the app. The one exception is the article selector, which I have indicated with a class attribute because there are going to be many of these selectors (one for each news category) &#8211; certainly in the landscape mode where they are stacked on the left hand side, but also in portrait mode, where I think I&#8217;ll have multiple panels too, although only one will show at a time.</p>
<p>I suppose I could have used class attributes for all of the panels, but this seems sensible enough until the semantic police haul me in. Also notice that I prefix every id or class with &#8216;bbc_&#8217;. This sort of thing prevents collisions with any other styling or behaviors when you&#8217;re mixing and matching CSS and Javascript libraries. (Not that we&#8217;re likely to do so here, but I guess it&#8217;s habit).</p>
<p>Wait! This is HTML5. Let&#8217;s do something more interesting than using &lt;div&gt; tags.</p>
<pre>&lt;nav id='bbc_controls'&gt;BBC&lt;/nav&gt;
&lt;ul id='bbc_ticker'&gt;&lt;li&gt;News ticker ...&lt;/li&gt;&lt;/ul&gt;
&lt;nav id='bbc_category_selector'&gt;Top Stories, Americas ...&lt;/nav&gt;
&lt;nav class='bbc_article_selector bbc_category_selected'&gt;War, Pestilence, Famine ...&lt;/nav&gt;
&lt;nav class='bbc_article_selector'&gt;Oil, Budgets, Taxes ...&lt;/nav&gt;
&lt;article id='bbc_article'&gt;Blah blah ...&lt;/article&gt;
&lt;aside id='bbc_banner_ad'&gt;Buy ...&lt;/aside&gt;
&lt;nav id='bbc_scroll_footer'&gt;o o o o&lt;/nav&gt;
</pre>
<p>Many of our panels are predominantly there to provide navigation, so let&#8217;s promote them to be &lt;nav&gt; tags. The main article can be an, er, &lt;article&gt; tag, and the ad (which is fairly auxiliary to the matter at hand) seems a good candidate for being an &lt;aside&gt;. The footer is <em>not</em> a &lt;footer&gt; tag, since that implies meta information about an HTML5 section, and in our case the footer is merely a navigational tool to scroll through pages &#8211; which just happens to be at the foot of the page. Finally I set the ticker to be an unordered list tag &lt;ul&gt;, which will ultimately include multiple headlines (in their own &lt;li&gt; tags) that we will rotate through.</p>
<p>OK. let&#8217;s fire up the iPad browser and take a look.</p>
<div id="attachment_34" class="wp-caption alignnone" style="width: 485px"><a href="http://whitherapps.com/bbc-news-pt-ii/bbc-html/" rel="attachment wp-att-34"><img src="http://whitherapps.com/wp-content/uploads/2010/06/bbc-html-475x94.png" alt="" title="bbc-html" width="475" height="94" class="size-medium wp-image-34" /></a><p class="wp-caption-text">Unstyled HTML version of BBC News web app</p></div>
<p>Not too inspiring yet. Let&#8217;s see what a little CSS can do.</p>
<pre>&lt;style&gt;
 * {
  -webkit-text-size-adjust:none;
  padding:0; margin:0;
 }
 #bbc_controls {
  display:block; width:100%;
  height:44px;
  background:#ff0000;
  color:#ffffff;
 }
 #bbc_ticker {
  display:block; width:100%;
  height:31px;
  background:#cccccc;
  color:#ff0000;
 }
 #bbc_category_selector {
  display:block; width:100%;
  height:36px;
  background:#000000;
  color:#ffffff;
 }
 .bbc_article_selector {
  display:none; width:100%;
  height:153px;
  background:#333333;
  color:#ffffff;
 }
 .bbc_article_selector.bbc_category_selected {
  display:block;
 }
 #bbc_article {
  display:block; width:100%;
  height:614px;
  background:#ffffff;
  color:#000000;
  overflow:auto;
 }
 #bbc_banner_ad {
  display:block; width:100%;
  height:90px;
  background:#ff00ff;
  color:#000000;
 }
 #bbc_scroll_footer {
  display:block; width:100%;
  height:36px;
  background:#000000;
  color:#ffffff;
 }
&lt;/style&gt;
</pre>
<p>Which looks something like:</p>
<div id="attachment_35" class="wp-caption alignnone" style="width: 366px"><a href="http://whitherapps.com/bbc-news-pt-ii/img_0010/" rel="attachment wp-att-35"><img src="http://whitherapps.com/wp-content/uploads/2010/06/IMG_0010-356x475.png" alt="" title="IMG_0010" width="356" height="475" class="size-medium wp-image-35" /></a><p class="wp-caption-text">Styled portrait version of BBC News web app</p></div>
<p>Ah… that looks a little better &#8211; although I&#8217;m not trying too hard to match the colors yet. Notice how I&#8217;m defending against the iOS browser&#8217;s tendency to auto-scale fonts with the -webkit-text-size-adjust style, and resetting the margins and paddings at the start too. (We&#8217;ll get all that stuff pixel perfect later). I&#8217;ve also learnt something new here: HTML5&#8242;s new &lt;nav&gt; element is treated as an inline element by default, so I need to set them as blocks so that they can be styled to the whole width.</p>
<p>Also I hide the article selectors by default and simple display the one that is marked as bbc_category_selected. In portrait mode, you only see one at a time.</p>
<p>But I have hit a snag here. The bbc_article block itself has the right height, and the ad and footer are fixed to the bottom of the page as a result. But when I try to load it up with a large amount of content, overflow:auto does not do what I expect. In a desktop browser that would normally add scroll bars to an element whenever it spills outside of its constrained dimensions. On the iPad, the height is honored, but the scroll bars never show, even when the page is longer than 614px. What&#8217;s more, a single finger doesn&#8217;t scroll the article (as it does in the native app): two fingers are required, and I can&#8217;t guarantee that users will figure that out.</p>
<p>I try playing with position:fixed to hold the top and bottom parts of the page to their physical positions on the screen in the hope that I can use the normal page scrolling to make it seem as though the article alone is scrolling, but that also does not work (Apple&#8217;s viewport philosophy has it that the fixed position means &#8216;fixed to the page&#8217;, not to the screen). But storming to the rescue is Matteo Spinelli&#8217;s <a href="http://cubiq.org/iscroll">iScroll</a> library which replaces what seems to be the browser&#8217;s oddly missing feature in this regard.</p>
<p>We&#8217;ll look in more detail at this when we come to integrate the content into the design. Suffice to say I can breathe easy again on the article scrolling, not to mention the category selectors and other scrollable elements in the page. (Chris Barr has a <a href="http://chris-barr.com/entry/scrolling_a_overflowauto_element_on_a_touch_screen_device/">simpler implementation</a>, but I want to see scroll bars as the pane moves, so iScroll it is.)</p>
<h2>Landscape styling</h2>
<p>Now onto the landscape mode. In the CSS above, I&#8217;ve assumed that portrait is the default mode. But when the rotation changes, some of the elements need to change shape and position. What I will try first is to register a small piece of code on the rotation and page load events, and use it to toggle a class onto the page&#8217;s body tag. Then I can use that class to create priority CSS styling for the landscape mode:</p>
<pre>&lt;script type='text/javascript'&gt;
 window.addEventListener('load', setOrientation, false);
 window.addEventListener('orientationchange', setOrientation, false);
 function setOrientation() {
  var orientation = Math.abs(window.orientation)===90?'bbc_landscape':'bbc_portrait';
  if (document.body.className == '') {
   document.body.className = orientation;
  } else {
   document.body.className = document.body.className.replace(/bbc_landscape|bbc_portrait/, orientation);
  }
 }
&lt;/script&gt;
</pre>
<p>When the page loads, and when the device is rotated, the new orientation is placed into the class, or the existing one replaced. Simple enough. Let&#8217;s test this out by adding a temporary CSS rule:</p>
<pre>.bbc_landscape #bbc_article {
 background:#00ffff;
}
</pre>
<p>And indeed, it goes cyan when I rotate the iPad. But this is a technique I&#8217;ve used on the iPhone for some time… and I&#8217;ve heard a rumor that CSS media queries now work on the iPad. Using these, I can specify that a CSS rule only fires when some condition or other is true. Well then, how about orientation? I remove the script and replace the temporary CSS rule with:</p>
<pre>@media (orientation:landscape) {
 #bbc_article {
  background:#00ffff;
 }
}
</pre>
<p>Rotate and… ah! Genius. It works a treat, just as before. Not only can I save myself a few lines of script and an unnecessary class on the &lt;body&gt;, but this syntax allows me to nest all my landscape rules into one nice block in the CSS. More importantly I am having fun the bleeding edge of contemporary CSS3 support.</p>
<p>So let&#8217;s add a few more real rules inside the @media braces and see if we can get things to move to their landscape positions.</p>
<pre>#bbc_ticker {
 border-bottom:1px solid #000000;
}
#bbc_category_selector {
 display:none;
}
</pre>
<p>The ticker gains a bottom border, and the category selector doesn&#8217;t show in landscape mode. But it is replaced with a small title at the top of each article selector, so I add those into the markup too, interleaving the article selectors. I also group up all these article selector pieces into an outer wrapper that I can use to held them all to the left-hand side of the screen in the landscape mode:</p>
<pre>&lt;div id='bbc_article_selectors'&gt;
 &lt;h2 class='bbc_article_selector_title'&gt;Top Stories&lt;/h2&gt;
 &lt;nav class='bbc_article_selector bbc_category_selected'&gt;War, Pestilence, Famine ...&lt;/nav&gt;
 &lt;h2 class='bbc_article_selector_title'&gt;Americas&lt;/h2&gt;
 &lt;nav class='bbc_article_selector'&gt;Oil, Budgets, Taxes ...&lt;/nav&gt;
&lt;/div&gt;
</pre>
<p>I also remember to make sure the titles don&#8217;t appear in the portrait view, and insert this into the main part of the CSS (i.e. not inside the portrait braces):</p>
<pre>.bbc_article_selector_title {
 display:none;
}
</pre>
<p>The rest of the landscape CSS, including the styling for these new article selector elements is as follows, and we also place these inside the @media braces:</p>
<pre>#bbc_article_selectors {
 display:block; width:507px;
 height:672px;
 background: #111111;
 border-right:1px solid #666666;
 float:left; clear:left;
}
.bbc_article_selector_title {
 display:block; width:507px;
 background:#333333;
 color:#ffffff;
}
.bbc_article_selector {
 display:block; width:507px;
}
#bbc_article {
 width:516px;
 height:636px;
 float:right; clear:right;
}
#bbc_banner_ad {
 display:none;
}
#bbc_scroll_footer {
 width:516px;
 float:right; clear:right;
}
</pre>
<p>…most of which is ensuring that the two-column view works correctly and will be scrollable. The new left-hand container also serves as a useful way to provide the 1px vertical bar between left and right parts of the screen.</p>
<p>Finally I personally don&#8217;t get the ad in landscape mode, so I nuke that too. Let&#8217;s fire it up:</p>
<div id="attachment_36" class="wp-caption alignnone" style="width: 485px"><a href="http://whitherapps.com/bbc-news-pt-ii/img_0009/" rel="attachment wp-att-36"><img src="http://whitherapps.com/wp-content/uploads/2010/06/IMG_0009-475x356.png" alt="" title="IMG_0009" width="475" height="356" class="size-medium wp-image-36" /></a><p class="wp-caption-text">Styled landscape version of the BBC News web app</p></div>
<p>Not bad, not bad. It&#8217;s not beautiful by any means, but it&#8217;s structured correctly, and it serves as a basic wireframe for the app from here on in. More importantly, the orientation works a treat: the CSS media query is applied quicker than the eye can detect, and feels snappy. (I&#8217;ll be using plenty of Javascript for all the scrolling I think, so it&#8217;s nice to know that this is already taken care of without it.)</p>
<h2>Wrap up</h2>
<p>So that&#8217;s it for now. I&#8217;ve put the HTML and CSS in a single static file and it&#8217;s up on this server here, so you can go and <a href="/apps/bbc-news/pt2.html">check it out in an iPad for real</a>. Just don&#8217;t forget to add it to the home screen to make the full-screen mode work properly.</p>
<p>We&#8217;ve shown that the basic structure of the app is very feasible with HTML5 and CSS alone, and now we need to move on to loading up the dynamic data, and then, I suspect, the panel scrolling. At that point, things should really start to come together. It&#8217;s exciting stuff, right?</p>
]]></content:encoded>
			<wfw:commentRss>http://whitherapps.com/bbc-news-pt-ii/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>BBC News, pt I</title>
		<link>http://whitherapps.com/bbc-news/</link>
		<comments>http://whitherapps.com/bbc-news/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 15:50:05 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[BBC News]]></category>

		<guid isPermaLink="false">http://whitherapps.com/?p=8</guid>
		<description><![CDATA[For the inaugural WhitherApps project, we&#8217;re going to look at the (excellent) BBC News iPhone/iPad app and see if it could have been built as a web app, rather than in native code. To kick off with, we&#8217;re going to try and emulate the iPad version, in both orientation modes. What we&#8217;re basically aiming for [...]]]></description>
			<content:encoded><![CDATA[<p>For the inaugural WhitherApps project, we&#8217;re going to look at the (excellent) <a href="http://itunes.apple.com/ie/app/bbc-news/id364147881?mt=8">BBC News</a> iPhone/iPad app and see if it could have been built as a web app, rather than in native code.</p>
<p>To kick off with, we&#8217;re going to try and emulate the iPad version, in both orientation modes. What we&#8217;re basically aiming for is this:</p>
<div id="attachment_25" class="wp-caption alignnone" style="width: 485px"><a href="http://whitherapps.com/bbc-news/bbc-landscape/" rel="attachment wp-att-25"><img src="http://whitherapps.com/wp-content/uploads/2010/06/bbc-landscape-475x356.png" alt="" title="bbc-landscape" width="475" height="356" class="size-medium wp-image-25" /></a><p class="wp-caption-text">The BBC News iPad app in landscape mode</p></div>
<p>And this:</p>
<div id="attachment_26" class="wp-caption alignnone" style="width: 366px"><a href="http://whitherapps.com/bbc-news/bbc-portrait/" rel="attachment wp-att-26"><img src="http://whitherapps.com/wp-content/uploads/2010/06/bbc-portrait-356x475.png" alt="" title="bbc-portrait" width="356" height="475" class="size-medium wp-image-26" /></a><p class="wp-caption-text">The BBC News iPad app in portrait mode</p></div>
<p>Let&#8217;s see how we get on. I&#8217;ve decided to break the process down into 4 steps:</p>
<ul>
<li>Figure out how the app pulls content from the BBC</li>
<li>Make a wireframe web page that behaves like the app</li>
<li>Stitch the content into the wireframe</li>
<li>Decorate the wireframe so it looks just like the real thing</li>
</ul>
<p>This gives me a chance to assess the feasibility of the undertaking before I get too swept up with pushing pixels around.</p>
<h2>Behind the scenes</h2>
<p>Obviously the app does not ship with the news in it, and my assumption is that the app is little more than a client to render a feed of content and images located somewhere on the web. Architecturally, it&#8217;s nothing more than a customized browser-like client&#8230; but we do need to figure out where the data comes from and how we might be able to use it in a <em>real </em>browser-based app.</p>
<p>I&#8217;m using my iPad on a home WiFi network. I take a quick look at the network settings on the device and I see that I can set up a proxy for web access and so on. This seems like the easiest way to get in to see the traffic coming to and from the app: I run up a Squid proxy on my Mac (which is conveniently on the same local WiFi network) and set the iPad&#8217;s proxy to be my Mac&#8217;s local IP address.</p>
<p>As a proxy, Squid does lots of clever things. For our purposes though, we really just want to see the requests the device is making, so I tail the access.log file. This shows me the HTTP requests from the device as it makes them:</p>
<pre>GET http://www.live.bbc.co.uk/moira/feeds/ipad/news/en/v1 - application/json
GET http://www.bbc.co.uk/moira/feed/news_world/front_page - application/atom+xml
GET http://bbc.112.2o7.net/b/ss/bbcwnewsiphone/0/OIP-2.0/s82818894? - text/html
GET http://cdnedge.bbc.co.uk/nol/ifs_news/hi/front_page/ticker.json - text/javascript
GET http://www.bbc.co.uk/moira/feed/news_world/americas - application/atom+xml
GET http://static.bbc.co.uk/moira/img/ipad/thumbnail/48058000/jpg/_48058752_009512185-2.jpg - image/jpeg
...</pre>
<p>This looks very promising. Firstly the app seems to be using HTTP &#8211; no proprietary protocols here &#8211; so this will work well if we come to use some sort of AJAX technique ourselves. Secondly, the URLs are self-explanatory, so it&#8217;s easy to see how things are working. There&#8217;s some sort of initialising JSON at the start, then an ATOM feed of the front page news (and shortly afterward the &#8216;Americas&#8217; page), and then a whole bunch of thumbnails that are used for the navigation icons at the top (or side) of the app.</p>
<p>(Incidentally, if you do do this sort of thing, prepare to be intrigued by the amount of background HTTP that the iPad is sending to Apple!)</p>
<h2>Playing it back</h2>
<p>My first impulse of course is to fire up a web browser (or, in this case, wget on the command line) and see what the payload of some of these responses is. So I try the initial JSON file:</p>
<pre>~ &gt; wget http://www.live.bbc.co.uk/moira/feeds/ipad/news/en/v1
--2010-06-13 13:13:50--  http://www.live.bbc.co.uk/moira/feeds/ipad/news/en/v1
Resolving www.live.bbc.co.uk (www.live.bbc.co.uk)... 212.58.246.160
Connecting to www.live.bbc.co.uk (www.live.bbc.co.uk)|212.58.246.160|:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2010-06-13 13:13:53 ERROR 403: Forbidden.</pre>
<p>And this doesn&#8217;t seem so good. How does the iPad app get the content over HTTP (via my Mac) when my Mac itself can&#8217;t?</p>
<p>Well, like all self-respecting mobile technologists, I have something of a fetish for HTTP user-agents. I wonder how the iPad app identifies itself when it makes requests to the BBC server? I go back to Squid, alter the configuration slightly so that the HTTP headers are logged, and refresh the iPad app. A whole load of new HTTP goes past, but this time I can see that the app&#8217;s requests include:</p>
<pre>User-Agent: BBC News 1.2.1 (iPad; iPhone OS 3.2; en_US)</pre>
<p>Call it a hunch, but I wonder how wget on my Mac will get on if I spoof the user-agent header?</p>
<pre>~ &gt; wget --user-agent="BBC News 1.2.1 (iPad; iPhone OS 3.2; en_US)" http://www.live.bbc.co.uk/moira/feeds/ipad/news/en/v1
--2010-06-13 13:18:20--  http://www.live.bbc.co.uk/moira/feeds/ipad/news/en/v1
Resolving www.live.bbc.co.uk (www.live.bbc.co.uk)... 212.58.246.160
Connecting to www.live.bbc.co.uk (www.live.bbc.co.uk)|212.58.246.160|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 6199 (6.1K) [application/json]</pre>
<p>Bingo! That&#8217;s all it takes to be not &#8216;forbidden&#8217; and get our initial 6Kb&#8217;s worth of JSON. It looks like this:</p>
<pre>{
 "name": "WWW iPad Application Bootstrap",
 "version": "1.0.4",
 "published": "2010-06-07 11:09:39 Etc/GMT",
 "ticker_url": "http://cdnedge.bbc.co.uk/nol/ifs_news/hi/front_page/ticker.json",
 "live_feed_uri_template": "http://www.bbc.co.uk/worldservice/meta/mobile/iphone/%7Bbandwidth%7D",
 "ugc_sms_number": "+447725100100",
 "ugc_email": "talkingpoint@bbc.co.uk",
 "feedback_email": "iphone-feedback@bbc.co.uk",
 "faq_url": "http://www.bbc.co.uk/moira/html/%7bdevice%7d/news/faq/en",
 "feedback_url": "http://www.bbc.co.uk/moira/html/%7bdevice%7d/news/feedback/en",
 "conditions_url": "http://www.bbc.co.uk/moira/html/%7bdevice%7d/news/tandc/en",
 "privacy_url": "http://www.bbc.co.uk/moira/html/%7bdevice%7d/news/privacy/en",
 "copyright": "BBC © 2010",
 "feeds": [
 {
  "type": "group",
  "title": "More",
  "feeds": [
  {
   "title": "Top Stories",
   "feed_url": "http://www.bbc.co.uk/moira/feed/news_world/front_page",
   "default": true,
   "movable": 0
  },
  {
   "title": "Americas",
   "feed_url": "http://www.bbc.co.uk/moira/feed/news_world/americas",
   "default": true
  },
...
  {
   "title": "Audio &amp; Video",
   "feed_url": "http://www.bbc.co.uk/moira/feed/avod/iphone/news/en/v1"
  },
  {
   "type": "group",
   "title": "News in Other Languages",
   "feeds": [
   {
    "title": "Mundo",
    "feed_url": "http://www.bbc.co.uk/worldservice/syndication/mobileiq/iphone/mundo/homepage/full.xml",
    "logo_url": "bbcimage://logomundo/wsdownload.bbc.co.uk/worldservice/images/branding/languages/iphone/mundo_125x19.png"
   },
...
   {
    "title": "Urdu",
    "feed_url": "http://www.bbc.co.uk/worldservice/syndication/mobileiq/iphone/urdu/homepage/full.atom",
    "logo_url": "bbcimage://logourdu/wsdownload.bbc.co.uk/worldservice/images/branding/languages/iphone/urdu_117x28.png"
   }

   ]
  }
  ]
 }
 ]
}</pre>
<p>This looks good. We can see that the first thing the app is doing is being told where all the critical feeds are stored, and how they should be structured in the navigational menu. We can see how to get the ticker data for the top of the page, and we can even get some ideas about how the &#8216;News in other languages&#8217; will be fetched.</p>
<p>Let&#8217;s start by looking at the main feed for what must be the front page:</p>
<pre>http://www.bbc.co.uk/moira/feed/news_world/front_page</pre>
<p>Again, this requires the user-agent to be spoofed, and the response is as follows:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:dc='http://purl.org/dc/elements/1.1/'&gt;
  &lt;title&gt;BBC News | News Front Page | World Edition&lt;/title&gt;
  &lt;updated&gt;2010-06-13T20:29:08+00:00&lt;/updated&gt;
  &lt;id&gt;urn:news-bbc-co-uk:section:bbc_news:front_page:world_edition&lt;/id&gt;
  &lt;author&gt;
    &lt;name&gt;BBC&lt;/name&gt;
  &lt;/author&gt;
  &lt;entry&gt;
    &lt;title&gt;Thousands flee Kyrgyzstan unrest&lt;/title&gt;
    &lt;summary&gt;Escalating ethnic violence in Kyrgyzstan that has killed nearly 100 people prompts tens of thousands to flee to Uzbekistan.&lt;/summary&gt;
    &lt;category label='World/Asia Pacific' term='World/Asia Pacific' /&gt;
    &lt;updated&gt;2010-06-13T17:51:40+00:00&lt;/updated&gt;
    &lt;id&gt;urn:news-bbc-co-uk:story:8737578&lt;/id&gt;
    &lt;link rel='alternate' href='http://news.bbc.co.uk/1/hi/world/asia_pacific/10304165.stm' type='text/html' title='Thousands flee Kyrgyzstan unrest' /&gt;
    &lt;media:thumbnail url='bbcimage://urn%3Anews-bbc-co-uk%3Astory%3A8737578/static.bbc.co.uk/moira/img/%7bdevice%7d/thumbnail/48063000/jpg/_48063440_48063241.jpg' /&gt;
    &lt;content type='xhtml'&gt;
      &lt;div xmlns='http://www.w3.org/1999/xhtml' class='body'&gt;
        &lt;div class='fullwidth_img'&gt;
          &lt;a href='bbcvideo://urn%3Anews-bbc-co-uk%3Astory%3A8737578/www.bbc.co.uk/moira/avod/%7bdevice%7d/av/urn-news.bbc.co.uk-story-8737578/urn-news.bbc.co.uk-media-48063655/news/world/604000/604036/%7bbandwidth%7d'&gt;
            &lt;img alt='Soldiers in central Osh' src='bbcimage://urn%3Anews-bbc-co-uk%3Astory%3A8737578/static.bbc.co.uk/moira/img/%7bdevice%7d/styfull/48063000/jpg/_48063696_jex_721239_de27-1.jpg' class='fullwidth_512x288' /&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;p&gt;Escalating ethnic violence in Kyrgyzstan has prompted tens of thousands of ethnic Uzbeks to flee the country.&lt;/p&gt;
...
        &lt;div class='inline_img'&gt;
          &lt;img alt='Map of Kyrgyzstan' src='bbcimage://urn%3Anews-bbc-co-uk%3Astory%3A8737578/static.bbc.co.uk/moira/img/%7bdevice%7d/styhalf/48063000/gif/_48063789_kyrgyz_osh_jalal_0610.gif' class='inline_226x170' /&gt;
        &lt;/div&gt;
...
      &lt;/div&gt;
    &lt;/content&gt;
  &lt;/entry&gt;
...
&lt;/feed&gt;
</pre>
<p>Excellent. This looks like a very straightforward ATOM feed, containing thumbnails for the navigation and fairly simple HTML formatting. The style of BBC articles is to have small, bite-sized paragraphs with small inline images and occasional videos. We&#8217;ll probably have to sort out all the styling ourselves, but the markup looks clean and workable.</p>
<p>The bbcimage://urn URLs for the images and thumnails look a bit strange, but we&#8217;ve already seen the HTTP traffic when they&#8217;re fetched, so we can figure out how they&#8217;ll need to be rewritten. At first glance it looks like:</p>
<pre>bbcimage://urn%3Anews-bbc-co-uk%3Astory%3A8737578/static.bbc.co.uk/moira/img/%7bdevice%7d/thumbnail/48063000/jpg/_48063440_48063241.jpg
</pre>
<p>Will become:</p>
<pre>http://static.bbc.co.uk/moira/img/ipad/thumbnail/48063000/jpg/_48063440_48063241.jpg
</pre>
<p>&#8230;which is a fairly simply transformation.</p>
<h2>What next?</h2>
<p>OK, so we&#8217;ve figured out how to bootstrap our app, get the structure of the navigation and news categories, and then receive some HTML-like content from the BBC feeds. So far so good: it looks quite simple, and certainly something that a self-respecting web app is going to be able to do.</p>
<p>The user-agent spoofing may not be possible from an AJAX-like context in a web browser, so that might require me to build a small proxy on a server somewhere, and means my web app will ultimately have to be more than a static HTML file. But then I suspected I would need to do that anyway, to avoid cross-site scripting issues, so that&#8217;s no big deal. (If the BBC were hosting the web app themselves, both reasons would be moot).</p>
<p>So, <a href="/bbc-news-pt-ii/">next installment</a>, I&#8217;m going to be taking a look at the structure and user-interface of the app and see how easy it is to synthesize the same overall look and feel of it. Since I&#8217;ve seen the data in the background, I now suspect that much of the app uses Safari browser components anyway&#8230; so I&#8217;m quietly confident!</p>
<p>Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://whitherapps.com/bbc-news/feed/</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>Introducing WhitherApps</title>
		<link>http://whitherapps.com/introducing-whitherapps/</link>
		<comments>http://whitherapps.com/introducing-whitherapps/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 14:25:54 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://whitherapps.com/?p=1</guid>
		<description><![CDATA[The debate It&#8217;s 2010 and debate rages in the mobile industry over the future of applications. On one hand, people seem to love native client apps. A quick download process from an app store, and the shiny icon is sitting on the mobile device&#8217;s desktop, ready to go. What&#8217;s more, as a developer, I might [...]]]></description>
			<content:encoded><![CDATA[<h2>The debate</h2>
<p>It&#8217;s 2010 and debate rages in the mobile industry over the future of applications.</p>
<p>On one hand, people seem to love native client apps. A quick download process from an app store, and the shiny icon is sitting on the mobile device&#8217;s desktop, ready to go.</p>
<p>What&#8217;s more, as a developer, I might even get paid for it. But wait! Damn. If I want to reach lots of users, I have to write different code for every single device platform. iPhone, Android, Symbian. That&#8217;s a lot of code to keep in sync. And I need users to keep updating the applications every time I make a small change.</p>
<p>On the other hand, the mobile web. Build a site which looks and feels like a self-contained application but which can render nicely on a variety of platforms. (It helps that a lot of modern mobile operating systems have broadly similar browsers). I might not be able to make money by selling access to it, but I can update the site whenever I want, and users will see the latest and greatest version.</p>
<p>In reality, there&#8217;s an essential role to be played by both types of application &#8211; as there is for computing in general. But the debate still continues and it&#8217;s fun to be involved.</p>
<h2>Enter WhitherApps</h2>
<p>So what&#8217;s the point of this site, then?</p>
<p>WhitherApps is a bandwagon-busting experiment. I believe there are far too many native client apps which could have been far better written as mobile web apps. What we&#8217;re going to try and do is take a few examples, apply a little reverse-engineering, and rewrite them, warts and all, with web technologies.</p>
<p>We&#8217;ll focus on native client apps that are free to download. These wouldn&#8217;t have suffered commercially had they been written this way in the first place.</p>
<p>Obviously, we&#8217;ll also focus on feasible genres of apps. No 3D games or background apps, for example. To start with, informational media apps (such as newspapers and broadcasters) will be in the spotlight.</p>
<p>But otherwise, we may not need to pull too many punches. Offline access? Through the wonders of HTML5, that should be OK. Native device API access? Well, BONDI and proprietary libraries permitting, we&#8217;ll have a go &#8211; and there&#8217;s always PhoneGap too.</p>
<p>Each post on the site will be a walkthrough (or part of a walkhrough) of the process. As we get our hands dirty, from the protocol-sniffing to the pixel-jiggling, you can follow the steps we took.</p>
<p>Stay tuned and wish us luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://whitherapps.com/introducing-whitherapps/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
	</channel>
</rss>

