<?xml version="1.0"  encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="http://thingsinjars.com/includes/style/rss.css" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="http://thingsinjars.com/rss/development/" rel="self" type="application/rss+xml" />
<title>Things in Jars</title>
<link>http://thingsinjars.com/</link>
<description>Articles from Things in Jars</description>
<language>en</language>
<docs>http://en.wikipedia.org/wiki/RSS_(file_format)</docs>
<lastBuildDate>Sat, 27 Apr 13 00:00:00 -0700</lastBuildDate>
<ttl>45</ttl><item>
<title>GhostStory</title>
<link>http://thingsinjars.com/post/474/ghoststory/</link>
<guid>http://thingsinjars.com/post/474/ghoststory/</guid>
<description><![CDATA[
        <div class="teaser markdown" id="teaser-474">
        <p><a href="http://thingsinjars.com/post/474/ghoststory/">GhostStory</a></p>
<p>During all the research I did for my CSS testing talk, I couldn't help but spot another gap where a testing tool could be useful. </p>

<h2>Cucumber</h2>

<p>Cucumber is a technology used widely in automated testing setups, mostly for acceptance testing - ensuring that the thing everybody agreed on at the beginning was the thing delivered at the end. </p>

<p>This is accomplished by having a set of plain text files containing descriptions of different scenarios or aspects of the application, usually with a description of the actions performed by an imaginary user. You describe the situation (known as a 'Given' step), describe the user's action ('When') and describe the expected outcome ('Then').</p>

<p>The language (properly known as gherkin) used in these files is deliberately simple and jargon-free so that all the key stakeholders in the project - designers, developers, product owners - can understand but the files are also written in a predictable and structured style so that they can, behind the scenes, be turned into testable code. </p>

<p>What occurred to me when looking into this area was that there wasn't an agreed terminology for specifying the layout/colour/look and feel of a project in plain text. Surely this would be the perfect place to drop in some cucumber salad. </p>

<p>What we've got now is a project based on SpookyJS - a way of controlling CasperJS (and, therefore PhantomJS) from NodeJS - which contains the GhostStory testing steps and their corresponding 'behind the scenes' test code. There are only two steps at the moment but they are the most fundamental which can be used to build up future steps. </p>

<p><p>By the way, the name 'GhostStory' only just won out over the original 'CucumberNodeSpookyCasperPhantomJS'. It kinda makes sense because it's built using a lot of ghost-named technologies (Spooky, Casper, Phantom) and cucumber test files are sometimes called "Story" files because they describe a user story.</p></p>

<h2>Implemented Steps</h2>

<p>Here, "Element descriptor" is a non-dev-readable description of the element you want to test - "Main title", "Left-hand navigation", "Hero area call-to-action". In the project, you keep a mapping file, <code>selectors.json</code>, which translates between these descriptions and the CSS selector used to identify the element in tests.</p>

<pre><code>Then the "Element descriptor" should have "property" of "value"
</code></pre>

<p>This is using the computed styles on an element and checking to see if they are what you expect them to be. I talked about something similar to this before <a href="http://thingsinjars.com/post/437/css-verification-testing/">in an earlier post</a>. This is related to the <a href="http://csste.st/techniques/frozen-dom.html">'Frozen DOM' approach</a> that my first attempt at a CSS testing tool, <a href="http://thingsinjars.com/post/438/cssert--like-assert-but-with-css-at-the-front/">cssert</a>, uses but this way does not actually involve a DOM snapshot.</p>

<pre><code>Then the "Element descriptor" should look the same as before
</code></pre>

<p>This uses the <a href="http://csste.st/techniques/image-diff.html">'Image Diff' approach</a>. You specify an element and render the browser output of that element to an image. The next time you run the test, you do the same and check to see if the two images differ. As mentioned many times before, this technique is 'content-fragile' but can be useful for a specific subset of tests or when you have mocked content. It can also be particularly useful if you have a <a href="https://speakerdeck.com/hagenburger/style-guide-driven-development">'living styleguide'</a> as described by <a href="https://twitter.com/Hagenburger/">Nico Hagenburger</a>. I've got some ideas about CSS testing on living styleguides that I'll need to write up in a later post.</p>

<h2>Future Steps</h2>

<p>Off the top of my head, there are a couple of other generic steps that I think would be useful in this project.</p>

<pre><code>Then the "Element descriptor" should have a "property" of "value1", "value2", ..., or "valueN"
</code></pre>

<p>This variation on the computed style measurement allows an arbitrary-length list of values. As long as the element being tested matches at least one of the rules, the step counts as a pass. This could be used to ensure that all text on a site is one of a certain number of font-sizes or that all links are from the predefined colour palette.</p>

<pre><code>Then the "Element descriptor" should look the same across different browsers.
</code></pre>

<p>This would build on the existing image diff step but include multiple browser runners. Just now, the image diffs are performed using <a href="https://github.com/Huddle/PhantomCSS">PhantomCSS</a> which is built on top of PhantomJS which is Webkit-based. This would ideally integrate a Gecko renderer or a Trident renderer process so that the images generated from one could be checked against another. I still feel that image diff testing is extremely fragile and doesn't cover the majority of what CSS testing needs to do but it can be a useful additional check.</p>

<h2>The aim</h2>

<p>I'm hoping this can sit alongside the other testing tools gathering on <a href="http://csste.st/">csste.st</a> where it can help people get a head-start on their CSS testing practices. What I'm particularly keen on with the GhostStory project is that it can pull in other tools and abstract them into testing steps. That way, we can take advantage of the best tools out there and stuff it into easily digested Cucumber sandwiches.</p>

<h2>Try it</h2>

<p>The GhostStory project is, naturally, <a href="https://github.com/thingsinjars/GhostStory">available on GitHub</a>. More usefully, however, I've been working on a fork of SpookyJS that integrates GhostStory into an immediately usable tool.</p>

<p>Please <a href="https://github.com/thingsinjars/SpookyJS">check out this project</a> and let me know what you think. I might rename it to distinguish it from the original SpookyJS if I can figure out exactly how to do that and maintain upstream relationships on GitHub.</p>
      </div>
]]></description>
<pubDate>Sun, 30 Dec 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Some App.net recipes</title>
<link>http://thingsinjars.com/post/469/some-appnet-recipes/</link>
<guid>http://thingsinjars.com/post/469/some-appnet-recipes/</guid>
<description><![CDATA[
        <div class="teaser markdown" id="teaser-469">
        <p><a href="http://thingsinjars.com/post/469/some-appnet-recipes/">Some App.net recipes</a></p>
<p>This is a collection of code snippets for various common tasks you might need to accomplish with the <a href="https://github.com/appdotnet/api-spec">App.net API</a>. Most of these are focused on creating or reading geo-tagged posts. They require a developer account on app.net and at least one of an App ID, App Code, App Access Token or User Access Token. The calls here are implemented using jQuery but that's just to make it easier to copy-paste into the console to test them out (so long as you fill in the blanks). </p>

<p>An important thing to bear in mind is the possibility for confusion between a 'stream' and 'streams'. By default, a 'stream' is a discrete chunk of the 20 latest posts served at a number of endpoints. This is the open, public, <a href="https://alpha-api.app.net/stream/0/posts/stream/global">global stream</a>:</p>

<pre><code>https://alpha-api.app.net/stream/0/posts/stream/global
</code></pre>

<p>On the other hand, 'streams' are long-poll connections that serve up any matching posts as soon as they are created. The connection stays open while there is something there to receive the response. Streams are available under:</p>

<pre><code>https://alpha-api.app.net/stream/0/streams
</code></pre>

<p>Totally not confusing. Not at all.</p>



<h2>Creating a user access token</h2>

<p>Required for any user-specific data retrieval. The only tricky thing you'll need to think about here is the <code>scope</code> you require.</p>

<pre><code>scope=stream email write_post follow messages export
</code></pre>

<p>should cover most requirements.</p>

<h3>Requires</h3>

<ul>
<li><code>client_id</code></li>
</ul>

<p>Visit this URL:</p>

<pre><code>https://alpha.app.net/oauth/authenticate
    ?client_id=[your client ID]
    &amp;response_type=token
    &amp;redirect_uri=http://localhost/
    &amp;scope=stream email write_post follow messages export
</code></pre>



<h2>Using a user access token to create a post (with annotations)</h2>

<h3>Requires</h3>

<ul>
<li><code>User Access Token</code></li>
<li>text to post</li>
</ul>

<p>The text is essential if you don't mark a post as '<code>machine_only</code>'. The annotations here are optional. Annotations don't appear in the global stream unless the requesting client asks for them.</p>

<pre><code>$.ajax({
  contentType: 'application/json',
  data: JSON.stringify({
    "annotations": [{
      "type": "net.app.core.geolocation",
      "value": {
        "latitude": 52.5,
        "longitude": 13.3,
        "altitude": 0,
        "horizontal_accuracy": 100,
        "vertical_accuracy": 100
      }
    }],
    "text": "Don't mind me, just checking something out."
  }),
  dataType: 'json',
  success: function(data) {
    console.log("Text+annotation message posted");
  },
  error: function() {
    console.log("Text+annotation message failed");
  },
  processData: false,
  type: 'POST',
  url: 'https://alpha-api.app.net/stream/0/posts?access_token={USER_ACCESS_TOKEN}'
});
</code></pre>



<h2>Using a user access token to post a machine_only post (with annotations)</h2>

<h3>Requires</h3>

<ul>
<li><code>User Access Token</code></li>
</ul>

<p>In this example, we're creating a post that won't show up in user's timelines and adding the 'well-known annotation' for geolocation.</p>

<pre><code>$.ajax({
  contentType: 'application/json',
  data: JSON.stringify({
    "annotations": [{
      "type": "net.app.core.geolocation",
      "value": {
        "latitude": 52.5,
        "longitude": 13.3,
        "altitude": 0,
        "horizontal_accuracy": 100,
        "vertical_accuracy": 100
      }
    }],
    machine_only: true
  }),
  dataType: 'json',
  success: function(data) {
    console.log("Non-text message posted");
  },
  error: function() {
    console.log("Non-text message failed");
  },
  processData: false,
  type: 'POST',
  url: 'https://alpha-api.app.net/stream/0/posts?access_token={USER_ACCESS_TOKEN}'
});
</code></pre>



<h2>Retrieve the global stream, including geo-annotated posts if there are any</h2>

<h3>Requires</h3>

<ul>
<li><code>User Access Token</code></li>
</ul>

<p>This is a very basic call to retrieve the <a href="https://alpha-api.app.net/stream/0/posts/stream/global">global stream</a> but it also instructs the endpoint to return us all annotations and include machine-only posts.</p>

<pre><code>var data = {
  "include_machine": 1,
  "include_annotations": 1,
  "access_token": "{USER_ACCESS_TOKEN}"
};

$.ajax({
    contentType: 'application/json',
    dataType: 'json',
    success: function(data) {
      console.log(data);
    },
    error: function(error, data) {
      console.log(error, data);
    },
    type: 'GET',
    url: 'https://alpha-api.app.net/stream/0/posts/stream/global',
    data: data
});
</code></pre>



<h2>Creating an App Access Token</h2>

<p>This is necessary for many of the <code>streams</code> operations. It is not used for individual user actions, only for application-wide actions. </p>

<ul>
<li><a href="https://github.com/appdotnet/api-spec/blob/master/auth.md#app-access-token-flow">App.net API wiki on App Access Tokens</a></li>
</ul>

<h3>Requires</h3>

<ul>
<li><code>client_id</code></li>
<li><code>client_secret</code></li>
</ul>

<p><code>client_credentials</code> is one of the four types of <code>grant_type</code> specified in the <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2-31">OAuth 2.0 specification</a>. I had difficulty getting this to work when using a data object:</p>

<pre><code>var data = {
    "client_id": "{CLIENT_ID}",
    "client_secret":"{CLIENT_SECRET}",
    "grant_type": "client_credentials"
};
</code></pre>

<p>The <code>client_credentials</code> kept throwing an error. Instead, sending this as a string worked fine:</p>

<pre><code>$.ajax({
  contentType: 'application/json',
  data: 'client_id={CLIENT_ID}&amp;client_secret={CLIENT_SECRET}&amp;grant_type=client_credentials',
  dataType: 'json',
  success: function(data) {
    console.log(data);
  },
  error: function(error, data) {
    console.log(error, data);
  },
  processData: false,
  type: 'POST',
  url: 'https://alpha.app.net/oauth/access_token'
});
</code></pre>

<p>One other thing to note is that this bit should be done server-side. This will throw a bunch of "…not allowed by Access-Control-Allow-Origin…" errors if you do it via jQuery.</p>

<h3>Returns</h3>

<pre><code>{
    "access_token": "{APP_ACCESS_TOKEN}"
    }
</code></pre>



<h2>Creating a <code>streams</code> format</h2>

<p>Now you have your app access token, you can use it to tell the service what kind of data you want back. The streams offered in the API have two quite powerful aspects. Firstly, filters allow you to run many kinds of queries on the data before it is streamed to you so you don't need to recieve and process it all. Secondly, the decoupling of filters from streams means you can specify the data structure and requirements you want once then just access that custom endpoint to get the data you want back any time.</p>

<h3>Requires</h3>

<ul>
<li><code>App access token</code></li>
</ul>

<p>This first example just creates an unfiltered stream endpoint</p>

<pre><code>$.ajax({
  contentType: 'application/json',
  data: JSON.stringify({"object_types": ["post"], "type": "long_poll", "id": "1"}),
  dataType: 'json',
  success: function(data) {
    console.log(data);
  },
  error: function(error, responseText, response) {
    console.log(error, responseText, response);
  },
  processData: false,
  type: 'POST',
  url: 'https://alpha-api.app.net/stream/0/streams?access_token={APP_ACCESS_TOKEN}'
});
</code></pre>

<h3>Returns</h3>

<pre><code>{
    "data": {
        "endpoint": "https://stream-channel.app.net/channel/1/{LONG_RANDOM_ENDPOINT_URL}",
        "id": "77",
        "object_types": [
            "post"
        ],
        "type": "long_poll"
    },
    "meta": {
        "code": 200
    }
}
</code></pre>



<h2>Using Filters to create a stream of geotagged posts</h2>

<p>We'll specify some requirements for our filter now so that it only returns back a subset of posts. The rules we're specfying here are:</p>

<pre><code>At least one item in the "/data/annotations/*/type" field
must "match"
the value "net.app.core.geolocation"
</code></pre>

<h3>Requires</h3>

<ul>
<li><code>User access token</code></li>
</ul>

<p>The <code>field</code> is specified in '<a href="http://tools.ietf.org/html/draft-pbryan-zyp-json-pointer-02">JSON Pointer</a>' format. Within the response, there is a 'data' object and a 'meta' object. The data contains an 'annotations' object which contains an array of annotations, each of which has a type. This is represented as <code>/data/annotations/*/type</code>.</p>

<pre><code>$.ajax({
  contentType: 'application/json',
  data: JSON.stringify({"match_policy": "include_any", "clauses": [{"object_type": "post", "operator": "matches", "value": "net.app.core.geolocation", "field": "/data/annotations/*/type"}], "name": "Geotagged posts"}),
  dataType: 'json',
  success: function(data) {
    console.log(data);
  },
  error: function(error, responseText, response) {
    console.log(error, responseText, response);
  },
  processData: false,
  type: 'POST',
  url: 'https://alpha-api.app.net/stream/0/filters?access_token={USER_ACCESS_TOKEN}'
});
</code></pre>

<h3>Returns</h3>

<p>The filter rules you just specified, the <code>id</code> of the filter (remember that for later) and the details of the application used to make the request.</p>

<pre><code>{
"clauses": [
    {
        "field": "/data/annotations/*/type",
        "object_type": "post",
        "operator": "matches",
        "value": "net.app.core.geolocation"
    }
],
"id": "527",
"match_policy": "include_any",
"name": "Geotagged posts",
"owner": {
    "avatar_image": {
        "height": 200,
        "url": "https://d2rfichhc2fb9n.cloudfront.net/image/4/Pr63PjEwJ1fr5Q4KeL3392BMgSnIAYlHxv8OkWwzx75V8quNfpaFp4VPpKnDRxdXtYYPtIutrDVdU9NbJn7hKApQL84T5sfB1D9bWTgtizMWInignv0WyPPfM2DpqSThQgvkB68vbPzjZ8VeKM02M2GySZ4",
        "width": 200
    },
    "canonical_url": "https://alpha.app.net/thingsinjars",
    "counts": {
        "followers": 30,
        "following": 65,
        "posts": 96,
        "stars": 0
    },
    "cover_image": {
        "height": 230,
        "url": "https://d2rfichhc2fb9n.cloudfront.net/image/4/UWZ6k9xD8_8LzEVUi_Uz6C-Vn-I8uPGEBtKb9jSVoFNijTwyEm1mJYpWq6JvnA6Jd4gzW76vFnbSWvM3jadhc1QxUl9qS4NTKiv3gJmr1zY_UpFWvX3qhOIyKrBPZckf2MrinqWay3H0h9rfqY0Gp9-liEg",
        "width": 960
    },
    "created_at": "2012-08-12T17:23:44Z",
    "description": {
        "entities": {
            "hashtags": [],
            "links": [],
            "mentions": []
        },
        "html": "&lt;span itemscope="https://app.net/schemas/Post"&gt;Nokia Maps Technologies Evangelist; CreativeJS team member; the tech side of museum140; builder of The Elementals; misuser of semi-colons;rn&lt;/span&gt;",
        "text": "Nokia Maps Technologies Evangelist; CreativeJS team member; the tech side of museum140; builder of The Elementals; misuser of semi-colons;rn"
    },
    "id": "3191",
    "locale": "en_GB",
    "name": "Simon Madine",
    "timezone": "Europe/Berlin",
    "type": "human",
    "username": "thingsinjars"
}
}
</code></pre>



<h2>Listening to the geotagged post stream</h2>

<p>This wil return a link to a long-lasting connection to the app.net stream that will only return posts with the geolocation annotation.</p>

<h3>Requires</h3>

<ul>
<li><code>filter_id</code> from the previous call</li>
</ul>

<p>Note: the <code>filter_id</code> was returned as <code>id</code> in the previous response.</p>

<pre><code>$.ajax({
  contentType: 'application/json',
  data: JSON.stringify({"object_types": ["post"], "type": "long_poll", "filter_id": "527"}),
  dataType: 'json',
  success: function(data) {
    console.log(data);
  },
  error: function(error, responseText, response) {
    console.log(error, responseText, response);
  },
  processData: false,
  type: 'POST',
  url: 'https://alpha-api.app.net/stream/0/streams?access_token={APP_ACCESS_TOKEN}'
});
</code></pre>

<h3>Returns</h3>

<p>The same kind of response as the 'Creating a <code>streams</code> format' example except the data coming down on the stream is filtered.</p>

<pre><code>https://stream-channel.app.net/channel/1/{LONG_RANDOM_ENDPOINT_URL}
</code></pre>

<p>Open that URL up in your browser (seeing as we're testing) and, in a different tab, create a geo-tagged machine-only post (see above). Your post will appear almost instantly after you've submitted it.</p>
      </div>
]]></description>
<pubDate>Mon, 29 Oct 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Location-based time</title>
<link>http://thingsinjars.com/post/468/location-based-time/</link>
<guid>http://thingsinjars.com/post/468/location-based-time/</guid>
<description><![CDATA[
        <div class="teaser markdown" id="teaser-468">
        <p><a href="http://thingsinjars.com/post/468/location-based-time/">Location-based time</a></p>
<p>Inspired by the simplicity of <a href="http://thingsinjars.com/post/466/building-a-proximity-search/">implementing a proximity search using MongoDB</a>, I found myself keen to try out another technology.</p>

<p>It just so happened that I was presented with a fun little problem the other day. Given a latitude and longitude, how do I <strong>quickly</strong> determine what the time is? Continuing the recent trend, I wanted to solve this problem with Node.JS.</p>

<p>Unsurprisingly, there's a lot of information out there about timezones. Whenever I've worked with timezones in the past, I've always gotten a little bit lost so this time, I decided to actually read a bit and find out what was supposed to happen. In essence, if you're doing this sort of task. you do not want to have to figure out the actual time yourself. Nope. It's quite similar to one of my top web dev rules:</p>


  <p>Never host your own video.</p>


<p><strong>(Really, never deal with video yourself. Pay someone else to host it, transcode it and serve it up. It'll will always work out cheaper.)</strong></p>

<p>What you want to do when working with timezones is tie into someone else's database. There are just too many rules around international boundaries, summer time, leap years, leap seconds, countries that have jumped over the international date line (more than once!), islands whose timezone is 30 minutes off the adjacent ones...</p>

<p>To solve this problem, it needs to be split into two: the first part is to determine which timezone the coordinate is in, the second is the harder problem of figuring out what time it is in that timezone. Fortunately, there are other people who are already doing this. Buried near the back of the bottom drawer in very operating system is some version of the <code>tz database</code>. You can spend hours <a href="http://en.wikipedia.org/wiki/Tz_database">reading up about it</a>, its controversies and history on Wikipedia if you like. More relevantly, however, is what it can do for us in this case. Given an IANA timezone name – "America/New_York", "Asia/Tokyo" – you can retrieve the current time from the system's <code>tz database</code>. I don't know how it works. I don't need to know. It works.</p>

<h2>Node</h2>

<p>Even better for reaching a solution to this problem, <a href="https://npmjs.org/package/zoneinfo">there's a node module</a> that will abstract the problem of loading and querying the database. If you use the <code>zoneinfo</code> module, you can create a new timezone-aware Date object, pass the timezone name to it and <strong>it</strong> will do the hard work. awsm. The module wasn't perfect, however. It loaded the system database synchronously using <code>fs.readFileSync</code> which is I/O blocking and therefore a <em>Bad Thing</em>. Boo.</p>

<p>10 minutes later and <a href="http://marcon.me/">Max</a> had wrangled it into using the asynchronous, non-blocking <code>fs.ReadFile</code>. Hooray!</p>

<p>Now all I needed to do was figure out how to do the first half of the problem: map a coordinate to a timezone name.</p>

<h2>Nearest-Neighbour vs Point-in-Polygon</h2>

<p>There are probably more ways to solve this problem but these were the two routes that jumped to mind. The tricky thing is that the latitude and longitude provided could be arbitrarily accurate. A simple lookup table just wouldn't work. Of course, the core of the problem was that we needed to figure out the answer fast.</p>

<h3>Nearest Neighbour</h3>

<ol>
<li>Create a data file containing a spread of points across the globe, determine (using any slow solution) the timezone at that point.</li>
<li>Load the data into an easily searchable in-memory data-structure (such as a <a href="http://en.wikipedia.org/wiki/K-d_tree">k-d tree</a>)</li>
<li>Given a coordinate, find the nearest existing data point and return its value.</li>
</ol>

<h3>Point in Polygon</h3>

<ol>
<li>Create a data file specifying the geometry of all timezones.</li>
<li>Given a coordinate, loop over each polygon and determine whether this coordinate is positioned inside or outside the polygon.</li>
<li>Return the first containing polygon</li>
</ol>

<p>This second algorithm could be improved by using a coarse binary search to quickly reduce the number of possible polygons that contain this point before step 2.</p>

<p>Despite some kind of qualification in mathematic-y computer-y stuff, algorithm analysis isn't my strong point. To be fair, I spent the first three years of my degree trying to get a record deal and the fourth trying to be a stand-up comedian so we may have covered complexity analysis at some point and I just didn't notice. What I do know, however, is that k-d trees are fast for searching. Super fast. They can be a bit slower to create initially but the point to bear in mind is that you only load it once while you search for data lots. On the other hand, while it's a quick task to load the geometry of a small number of polygons into memory, determining which polygon a given point is in can be slow, particularly if the polygons are complex.</p>

<p>Given this vague intuition, I settled on the first option. </p>

<p>If I wanted to create a spread of coordinates and their known timezones from scratch, it might have been an annoyingly slow process but, the Internet being what it is, someone already did the hard work. <a href="https://gist.github.com/1769458">This gist</a> contains the latitude and longitude for every city in the world and what IANA timezone it is in. Score! A quick regex later and it looks like this:</p>

<pre><code>module.exports = [
  {"latitude": 42.50729, "longitude": 1.53414, "timezone": "Europe/Andorra"},
  {"latitude": 42.50779, "longitude": 1.52109, "timezone": "Europe/Andorra"},
  {"latitude": 25.56473, "longitude": 55.55517, "timezone": "Asia/Dubai"},
  {"latitude": 25.78953, "longitude": 55.9432, "timezone": "Asia/Dubai"},
  {"latitude": 25.33132, "longitude": 56.34199, "timezone": "Asia/Dubai"},
  etc…
</code></pre>

<p>(<a href="https://github.com/thingsinjars/coordinate-tz/blob/master/city_timezones.js">See the original on GitHub</a>)</p>

<p>All that's left is to load that into a k-d tree and we've got a fully-searchable, fast nearest neighbour lookup.</p>

<h2>Source</h2>

<p>The source for this node module is, of course, <a href="https://github.com/thingsinjars/coordinate-tz">available on GitHub</a> and the module itself is available for <a href="https://npmjs.org/package/coordinate-tz">install via npm</a> using:</p>

<pre><code>npm install coordinate-tz
</code></pre>

<p>When combined with the <a href="https://npmjs.org/package/zoneinfo"><code>zoneinfo</code> module </a> (or, even better, <a href="https://github.com/mmarcon/node-zoneinfo">this async fork of the module</a>), you can get a fast, accurate current time lookup for any latitude and longitude.</p>

<p>Not a bad little challenge for a Monday evening.</p>
      </div>
]]></description>
<pubDate>Mon, 15 Oct 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Building a Proximity Search</title>
<link>http://thingsinjars.com/post/466/building-a-proximity-search/</link>
<guid>http://thingsinjars.com/post/466/building-a-proximity-search/</guid>
<description><![CDATA[
        <div class="teaser markdown" id="teaser-466">
        <p><a href="http://thingsinjars.com/post/466/building-a-proximity-search/">Building a Proximity Search</a></p>
<p>This is the detailed post to go with <a href="http://thingsinjars.com/post/465/proximity-search/">yesterday's quick discussion about proximity search</a>. All the code is <a href="https://github.com/thingsinjars/Proximity">available on GitHub</a>.</p>

<p>This assumes a bit of <a href="http://nodejs.org/">NodeJS</a> knowledge, a working copy of <a href="http://mxcl.github.com/homebrew/">homebrew</a> or something similar.</p>

<h2>Install</h2>

<ul>
<li>MongoDB - <code>brew install mongodb</code></li>
<li><a href="http://nodejs.org/">NodeJS</a></li>
<li>NPM (included in NodeJS installer these days)</li>
</ul>

<p>These are included in the <a href="https://github.com/thingsinjars/Proximity/blob/master/package.json"><code>package.json</code></a> but it can't hurt to mention them here:</p>

<ul>
<li><code>npm install twitter</code> (node twitter streaming API library)</li>
<li><code>npm install mongodb</code> (native mongodb driver for node)</li>
<li><code>npm install express</code> (for convenience with API later)</li>
</ul>

<p>Start <code>mongod</code> in the background. We don't quite need it yet but it needs done at some point, may as well do it now.</p>

<h2>Create a Twitter App</h2>

<p><a href="https://dev.twitter.com/apps/new">Fill out the form</a> Then press the button to get the single-user access token and key. I love that Twitter does this now, rather than having to create a full authentication flow for single-user applications.</p>

<h2>ingest.js</h2>

<p><em>(open the <a href="https://github.com/thingsinjars/Proximity/blob/master/ingest.js">ingest.js</a> file and read along with this bit)</em></p>

<p>Using the basic native MongoDB driver, everything must be done in the <code>database.open</code> callback. This might lead to a bit of Nested Callback Fury but if it bothers you or becomes a bit too furious for your particular implementation, there are a couple of alternative Node-MongoDB modules that abstract this out a bit.</p>

<pre><code>// Open the proximity database
db.open(function() {
    // Open the post collection
    db.collection('posts', function(err, collection) {
        // Start listening to the global stream
        twit.stream('statuses/sample', function(stream) {
            // For each post
            stream.on('data', function(data) {
                if ( !! data.geo) {
                    collection.insert(data);
                }
            });
        });
    });
});
</code></pre>

<h2>Index the data</h2>

<p>The hard work has all been done for us: <a href="http://www.mongodb.org/display/DOCS/Geospatial+Indexing/">Geospatial Indexing in MongoDB</a>. That's a good thing.</p>

<p>Ensure the system has a Geospatial index on the tweets.</p>

<pre><code>db.posts.ensureIndex({"geo.coordinates" : "2d"})
</code></pre>

<p>Standard Geospatial search query:</p>

<pre><code>db.posts.find({"geo.coordinates": {$near: [50, 13]}}).pretty()
(find the closest points to (50,13) and return them sorted by distance)
</code></pre>

<p>By this point, we've got a database full of geo-searchable posts and a way to do a proximity search on them. To be fair, it's more down to mongodb than anything we've done.</p>

<p>Next, we extend the search on those posts to allow filtering by query</p>



<pre><code>db.posts.find({"geo.coordinates": {$near: [50, 13]}, text: /.*searchterm.*/}).pretty()
</code></pre>

<h2>API</h2>

<p>Super simple API, we only have two main query types:</p>

<ul>
<li><code>/proximity?latitude=55&amp;longitude=13</code></li>
<li><code>/proximity?latitude=55&amp;longitude=13&amp;q=searchterm</code></li>
</ul>

<p>Each of these can take an optional <code>'callback'</code> parameter to enable <code>jsonp</code>. We're using express so the callback parameter and content type for returning JSON are both handled automatically.</p>

<p><code>api.js</code></p>

<p><em>(open the <a href="https://github.com/thingsinjars/Proximity/blob/master/api.js">api.js</a> file and read along with this bit)</em></p>

<p>This next chunk of code contains everything so don't panic.</p>

<pre><code>db.open(function() {
  db.collection('posts', function(err, collection) {
    app.get('/proximity', function(req, res) {
      var latitude, longitude, q;
      latitude = parseFloat(req.query["latitude"]);
      longitude = parseFloat(req.query["longitude"]);
      q = req.query["q"];

      if (/^(-?d+(.d+)?)$/.test(latitude) &amp;&amp; /^(-?d+(.d+)?)$/.test(longitude)) {
        if (typeof q === 'undefined') {
          collection.find({
            "geo.coordinates": {
              $near: [latitude, longitude]
            }
          }, function(err, cursor) {
            cursor.toArray(function(err, items) {
              writeResponse(items, res);
            });
          });
        } else {
          var regexQuery = new RegExp(".*" + q + ".*");
          collection.find({
            "geo.coordinates": {
              $near: [latitude, longitude]
            },
            'text': regexQuery
          }, function(err, cursor) {
            cursor.toArray(function(err, items) {
              writeResponse(items, res);
            });
          });
        }
      } else {
        res.send('malformed lat/lng');
      }

    });
  });
});
</code></pre>

<p>If you've already implemented the <code>ingest.js</code> bit, the majority of this <code>api.js</code> will be fairly obvious. The biggest change is that instead of loading the data stream then acting upon each individual post that comes in, we're acting on URL requests.</p>

<pre><code>app.get('/proximity', function(req, res) {
</code></pre>

<p>For every request on this path, we try and parse the query string to pull out a latitude, longitude and optional query parameter.</p>

<pre><code>if (/^(-?d+(.d+)?)$/.test(latitude) &amp;&amp; /^(-?d+(.d+)?)$/.test(longitude)) {
</code></pre>

<p>If we <strong>do</strong> have valid coordinates, pass through to Mongo to do that actual search:</p>

<pre><code>collection.find({
  "geo.coordinates": {
    $near: [latitude, longitude]
  }
}, function(err, cursor) {
  cursor.toArray(function(err, items) {
    writeResponse(items, res);
  });
});
</code></pre>

<p>To add a text search into this, we just need to add one more parameter to the <code>collection.find</code> call:</p>

<pre><code>var regexQuery = new RegExp(".*" + q + ".*");
collection.find({
  "geo.coordinates": {
    $near: [latitude, longitude]
  },
  'text': regexQuery
}
</code></pre>

<p>This makes it so simple, making it it kind of feels like cheating. Somebody else did all the hard work first.</p>

<h2>App.net Proximity</h2>

<p>This works quite well on the <a href="https://alpha-api.app.net/stream/0/posts/stream/global">App.net Global Timeline</a> but it'll really become useful once the <a href="https://github.com/appdotnet/api-spec/blob/master/resources/streams.md">streaming API is switched on</a>.</p>

<p>Of course, the <a href="https://github.com/thingsinjars/Proximity">code is all there</a>. If you want to have a go yourself, feel free.</p>
      </div>
]]></description>
<pubDate>Mon, 08 Oct 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Proximity Search</title>
<link>http://thingsinjars.com/post/465/proximity-search/</link>
<guid>http://thingsinjars.com/post/465/proximity-search/</guid>
<description><![CDATA[
        <div class="teaser markdown" id="teaser-465">
        <p><a href="http://thingsinjars.com/post/465/proximity-search/">Proximity Search</a></p>
<p>Now that geolocated posts are beginning to show up around app.net, I found myself wondering about proximity search. Twitter <a href="https://dev.twitter.com/docs/api/1/get/geo/search">provides one themselves</a> for geotagged tweets. What a proximity search does, essentially, is provide results from a data set ordered by increasing distance from a given location. This can be further enhanced by combining it with a text search either before or after the distance sorting. This would give you a way to search for a certain query within a certain area.</p>

<p><a href="http://search.twitter.com/search.json?geocode=52.5,13.3,1000mi&amp;q=toast&amp;rpp=100">Here, for example, is a proximity search centred on Berlin including any tweet in 1000 miles containing the word 'toast'</a>.</p>

<p>When I first started thinking about the tech required for a proximity search, I remembered <a href="https://twitter.com/lukas_nowacki">Lukas Nowacki</a> back in our old <a href="http://www.whitespacers.com/">Whitespace</a> days implementing the <a href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a> in MySQL (Alexander Rubin has a good overview of <a href="http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL">how to do this</a>). As much as I love my trigonometry and logarithms, I must admit, I was looking around for a simpler solution. Actually, I was looking around for a <a href="http://thingsinjars.com/post/430/copy-paste-coding/">copy-paste solution</a>, to be honest. I may even have spent some time going down that route if <a href="http://marcon.me/">Max</a> hadn't pointed me in the direction of <a href="http://www.mongodb.org/">MongoDB</a>.</p>

<p>I'd been putting off digging into NoSQL databases for a while because, well, I had no real reason to. Recently, I've either been focused on front-end dev or hacking away at Java and never really had any good reason to investigate any of these new-fangled technologies get off my lawn you kids. </p>

<h2>MongoDB</h2>

<p>After 10 minutes of messing around with Mongo, I pretty much just found myself saying “No... way. There's no way that's actually working” I'm sure those of you experience with document-oriented databases are rolling your eyes right now but for those few of us left with an entirely relational concept of databases, let me just explain it like this: you know those things you want to do with a database that are just a hassle of multiple joins and confusing references? Document databases do some of those things really really well. </p>

<p>The biggest selling point for me, however was the <a href="http://www.mongodb.org/display/DOCS/Geospatial+Indexing/">native geospatial indexing</a>. That pretty much made the majority of my proximity search complete. All I needed to do was wrap it in a nice interface and call it a day...</p>

<p>I'll follow up tomorrow with a more detailed 'How-to' guide.</p>
      </div>
]]></description>
<pubDate>Sun, 07 Oct 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>CoverMap - Nokia Maps on Facebook</title>
<link>http://thingsinjars.com/post/463/covermap---nokia-maps-on-facebook/</link>
<guid>http://thingsinjars.com/post/463/covermap---nokia-maps-on-facebook/</guid>
<description><![CDATA[
        <div class="teaser markdown" id="teaser-463">
        <p><a href="http://thingsinjars.com/post/463/covermap---nokia-maps-on-facebook/">CoverMap - Nokia Maps on Facebook</a></p>
<p>I'm almost managing to keep to my intended schedule of one map-based web experiment per week. Unfortunately, I've mostly been working on internal <a href="http://maps.nokia.com/">Nokia Maps</a> projects over the weekends recently so I've not had much to post here.</p>

<p>I can share my latest toy, though: <a href="http://covermap.me">CoverMap.me</a></p>

<p>Using just the public APIs over a couple of hours last Sunday afternoon, I made this to allow you to set a Nokia Map as your Facebook Timeline cover. The whole process is really straightforward so I thought I'd go over the main parts.</p>

<p>The exact aim of CoverMap.me is to allow the user to position a map exactly, choose from any of the available map styles and set the image as their cover image.</p>

<h2>Make a Facebook App</h2>

<p>Go to <a href="http://developers.facebook.com/apps/">developers.facebook.com/apps/</a> and click 'Create New App', fill in the basic details – name of the app, URL it will be hosted on, etc – and you're done.</p>

<h2>Facebook login</h2>

<p>I've used the Facebook JS SDK extensively over the summer for various projects but I wanted to try out the PHP one for this. Super, super simple. Really. Include the library (<a href="https://github.com/facebook/facebook-php-sdk">available here</a>), set your <code>appId</code> and <code>secret</code> and request the <code>$login_url</code>.</p>

<pre><code>$facebook-&gt;getLoginUrl(array('redirect_uri' =&gt; "http://example.com/index.php"));
</code></pre>

<p>That will give you a link which will take care of logging the user in and giving you basic access permissions and details about them.</p>

<h2>Nokia Maps JS API</h2>

<p>When I'm hacking together something quick and simple with the <a href="http://api.maps.nokia.com/">Nokia Maps API</a>, I usually use the properly awsm jQuery plugin <a href="https://github.com/mmarcon/jOVI">jOVI</a> written by the equally awsm <a href="http://marcon.me/">Max</a>. This makes 90% of the things you would want to do with a map extremely easy and if you're doing stuff advanced enough to want the extra 10%, you're probably not the type who'd want to use a jQuery plugin, anyway. Either way, you need to register on the <a href="http://api.developer.nokia.com/">Nokia developer site</a> to get your Nokia <code>app_id</code> and <code>secret</code>.</p>

<p>To create a map using jOVI, simply include the plugin in your page then run <code>.jOVI</code> on the object you want to contain the map along with starting parameters:</p>

<pre><code>$(window).on('load', function() {
  $('#mapContainer').jOVI({
    center: [38.895111, -77.036667], // Washington D.C.
    zoom: 12,           // zoom level
    behavior: true,     // map interaction
    zoomBar: true,      // zoom bar
    scaleBar: false,    // scale bar at the bottom
    overview: false,    // minimap (bottom-right)
    typeSelector: false,// normal, satellite, terrain
    positioning: true   // geolocation
  }, "APP_ID", "APP_SECRET");
});
</code></pre>

<p>This gives us a complete embedded map.</p>

<p>As I mentioned above, part of the idea for CoverMap.me was to allow the  to choose from any of the available map styles. This was an interesting oddity because the public <a href="http://api.maps.nokia.com/en/maps/intro.html">JS API</a> gives you the choice of 'Normal', 'Satellite', 'Satellite Plain' (a.k.a. no text), 'Smart' (a.k.a. grey), 'Smart Public Transport', 'Terrain' and 'Traffic' while the <a href="http://api.maps.nokia.com/en/restmaps/overview.html">RESTful Maps API</a> (the API that provides static, non-interactive map images) supports all of these <em>plus</em> options to choose each of them with big or small text <em>plus</em> a 'Night Time' mode. Because of this, I decided to go for a two-step approach where users were shown the JS-powered map to let them choose their location then they went through to the RESTful static map to allow them to choose from the larger array of static tiles.</p>

<h2>RESTful Maps</h2>

<p>The <a href="http://api.maps.nokia.com/en/restmaps/overview.html">RESTful Maps API</a> is relatively new but does provide a nice, quick map solution when you don't need any interactivity. Just set an <code>img src</code> with the query parameters you need and get back an image.</p>

<pre><code>(this should be all on one line)
http://m.nok.it/
    ?app_id=APP_ID
    &amp;token=APP_TOKEN
    &amp;nord       // Don't redirect to maps.nokia.com
    &amp;w=640      // Width
    &amp;h=480      // Height
    &amp;nodot      // Don't put a green dot in the centre
    &amp;c=38.895111, -77.036667 // Where to centre
    &amp;z=12       // Zoom level
    &amp;t=0        // Tile Style
</code></pre>

<p>That URL produces this image:</p>

<p><img src="http://m.nok.it/?app_id=_peU-uCkp-j8ovkzFGNU&token=gBoUkAMoxoqIWfxWA5DuMQ&nord&w=640&h=480&nodot&c=38.895111, -77.036667&z=12&t=0" alt="Map of Washington D.C."></p>

<h2>Upload to Facebook</h2>

<p>Given the above, we've now got an image showing a map positioned exactly where the user wants it in the tile style the user likes. We just need to make the Facebook API call to set it as Timeline Cover Image and we're done.</p>

<p>You'd think.</p>

<p>Facebook doesn't provide an API endpoint to update a user's profile image or timeline cover. It's probably a privacy thing or a security thing or something. Either way, it doesn't exist. Never fear! There's a solution!</p>

<p>With the default permissions given by a Facebook login/OAUTH token exchange/etc... (that thing we did earlier), we are allowed to upload a photo to an album. </p>

<p>The easiest way to do this is to download the map tile using cURL then repost it to Facebook. The clever way to do it would be to pipe the incoming input stream directly back out to Facebook without writing to the local file system but it would be slightly more hassle to set that up and wouldn't really make much of a difference to how it works.</p>

<pre><code>// Download from RESTful Maps
$tileUrl = "http://m.nok.it/?app_id=APP_ID&amp;token=APP_TOKEN&amp;nord&amp;w=640&amp;h=480&amp;nodot&amp;c=38.895111,%20-77.036667&amp;z=12&amp;t=0";
$ch = curl_init( $tileUrl );
$fp = fopen( $filename, 'wb' );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_exec( $ch ); 
curl_close( $ch );
fclose( $fp );

//Upload to Facebook
$full_image_path = realpath($filename);
$args = array('message' =&gt; 'Uploaded by CoverMap.me');
$args['image'] = '@' . $full_image_path;
$data = $facebook-&gt;api("/{$album_id}/photos", 'post', $args);
</code></pre>

<p>The closest thing we can do then is to construct a Facebook link which suggests the user should set the uploaded image as their Timeline Cover:</p>

<pre><code>// $data['id'] is the image's Facebook ID 
$fb_image_link = "http://www.facebook.com/" . $username . "?preview_cover=" . $data['id'];
</code></pre>

<h2>Done</h2>

<p>There we go. Minimal development required to create a web app with very little demand on the user that gives them a Nokia Map on their Facebook profile. Not too bad for a Sunday afternoon.</p>

<p><a href="http://covermap.me">Go try it out</a> and let me know what you think.</p>

<p><p>The code is now <a href="https://github.com/thingsinjars/CoverMapMe">available on GitHub</a></p></p>
      </div>
]]></description>
<pubDate>Sat, 29 Sep 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Using CSS :target to control state</title>
<link>http://thingsinjars.com/post/462/using-css-target-to-control-state/</link>
<guid>http://thingsinjars.com/post/462/using-css-target-to-control-state/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-462">
        <p><a href="http://thingsinjars.com/post/462/using-css-target-to-control-state/">Using CSS :target to control state</a></p>
<p>There can be a fair amount of discussion provoked by the phrase "CSS only" or "Built entirely in HTML and CSS" when it comes to tech demos. The discussion generally revolves around the fact that what the phrase actually means 99% of the time is "Using CSS for the graphical bits but tracking the mouse using JS" or "Using CSS transforms for most of it but using JS to calculate the values" or any number of variations on that theme. </p>

<p>Now, I'm not saying that's a bad thing at all, I quite happily called <a href="http://thelab.thingsinjars.com/CSSKart/">my interpretation of Super Mario Kart</a> CSS-only even though without JS, Yoshi wouldn't make it to the first bend. What these demos are doing, essentially, is using CSS as the rendering layer where previously, JS would have been used. By doing so, you even get some nice hardware acceleration thrown in. Not too bad.</p>

<h2>Why fall back?</h2>
<p>The reason we fall back to JS for a lot of things is because CSS is a declarative language (see my <a href="http://thingsinjars.com/post/437/css-verification-testing/">post on CSS testing</a> to learn more). However you say things should be is how they are. In CSS, you can't set a variable to one value, do something with it then set it to a different value and do something else. For a start, you don't have variables. Even if you did, the style sheet is read top-to-bottom before anything is done with it. The variable would always have the final value assigned to it, even the first time you used it. I'm simplifying a bit but not much. If you want to do anything clever, you generally need to resort to JS, an interpreted language.</p>

<h2>Really CSS only</h2>
<p>If you want to make something properly interactive but entirely CSS, you have to find a way to modify the state of the DOM so that different sets of styles can be applied to the same sets of elements. We actually do this all the time when we change the colour of a link on :hover. The user interacts with the page, the state of the page is changed slightly, a different style applies. There's a lot you can do now that you have a way to modify the page based on user interaction. Hooray for pseudo-classes! </p>

<p>An extremely important addition to the set of pseudo-classes available in CSS3 is the :target class. This becomes set on an element when the element is the target of a clicked link. Think of in-page jump links. When you click on one and the URL changes to 'blah.html#the-thing-you-clicked', the element with <code>id="the-thing-you-clicked"</code> gets the :target pseudo-class. Now you can affect it and its children with new styles. Now it becomes interesting, you can click on something on one bit of the page and it cause something to happen on another bit of the page. </p>

<h2>Multiple-nested states</h2>
<p>By nesting several elements around the thing you're intending to modify, you can now create a set of states entirely controlled by CSS. For example, with this HTML:</p>

<pre lang="html"><code>&lt;div id=&quot;red&quot;&gt;
  &lt;div id=&quot;blue&quot;&gt;
    &lt;div id=&quot;green&quot;&gt;
      &lt;div id=&quot;yellow&quot;&gt;
          &lt;p&gt;Hello.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#red&quot;&gt;Red&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#blue&quot;&gt;Blue&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#green&quot;&gt;Green&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#yellow&quot;&gt;Yellow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#default&quot;&gt;Default&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</code></pre>
And this CSS:
<pre lang="css"><code>p {
    color:black;
}
#red:target p {
    color:red;
}
#blue:target p {
    color:blue;
}
#green:target p {
    color:green;
}
#yellow:target p {
    color:yellow;
}</code></pre>

<p>You can change the colour of the text by clicking on the link. Without any JS.</p>

<p><a href="http://jsfiddle.net/DMNSn/">See this on JSFiddle</a>.</p>

<h2>Shiny demos</h2>
<p>This still isn't perfect. There are still going to be many things that JS is best for, calculations being one, keyboard input being another. To try and find the best way to show this off, I tried to update CSS Mario Kart to be entirely CSS and I almost got there but wasn't 100% successful.</p>
<ul>
<li><a href="http://thelab.thingsinjars.com/CSSKart/cssonly.html">CSS-only Mario Kart</a></li>
</ul>

<p>I then started to build a zoetrope in CSS, found <a href="http://andrew-hoyer.com/experiments/zoetrope/">someone else</a> had already done it and decided to modify it.</p>

<ul>
<li><a href="http://thelab.thingsinjars.com/zoetrope/index.html#spin">CSS-only Zoetrope</a></li>
</ul>

<p>Maybe soon, the phrase "CSS only" will really mean "CSS only. And a bit of HTML."</p>      </div>
]]></description>
<pubDate>Sun, 15 Jul 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Web Audio API Part 1</title>
<link>http://thingsinjars.com/post/461/web-audio-api-part-1/</link>
<guid>http://thingsinjars.com/post/461/web-audio-api-part-1/</guid>
<description><![CDATA[
        <div class="teaser " id="teaser-461">
        <p><a href="http://thingsinjars.com/post/461/web-audio-api-part-1/">Web Audio API Part 1</a></p>
I'm enjoying the chance to write for another site that I get with <a href="http://creativejs.com">creativejs.com</a> but it does leave me less time to create new posts for here. 

Having said that, there's nothing wrong with the occasional cross-post. Here's the first part of the introduction to Web Audio that I promised a couple of weeks ago:

<a href="http://creativejs.com/resources/web-audio-api-getting-started/">Web Audio API - Getting Started</a> on <a href="http://creativejs.com">CreativeJS</a>
      </div>
]]></description>
<pubDate>Tue, 19 Jun 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>ImpressJS Tools</title>
<link>http://thingsinjars.com/post/448/impressjs-tools/</link>
<guid>http://thingsinjars.com/post/448/impressjs-tools/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-448">
        <p><a href="http://thingsinjars.com/post/448/impressjs-tools/">ImpressJS Tools</a></p>
<p>While putting together last week's <a href="http://thingsinjars.com/post/446/museum140-shorty/">promo video for Museum140</a> (a vote'd be awsm, btw), I knocked up a few tools to make my life easier. As I always say, if you find something you like, make a plugin for it. Seriously, I <strong>always</strong> say that. That might even be how I proposed to my wife, I'll have to check.</p>

<p>Anyway.</p>

<h2>Play</h2>
<p>This is a simple timing helper. It just provides a little array you can push slide durations into and at the end, you call 'play'. I can't see many uses for this other than in creating videos.</p>
<pre><code>ImpressJS.play(3000);  //Set the first slide duration for 3 seconds
ImpressJS.play(1000);  //Set the second slide duration for 1 second
ImpressJS.play(); //Play from the start
</code></pre>

<h2>Edit</h2>
<p>This is much more useful.</p>

<p>If this script is included in the page (after the impress.js script), you can drag your slides around, rotate and scale them into exactly the position you want. Once you're happy, you can get the current HTML output onto the console for pasting back into your original slideshow file. I could have snuck in a <a href="http://thingsinjars.com/post/440/create-a-draggable-file-on-the-fly-with-js/">drag-n-drop file handler</a> but that would make it Chrome only.</p>


<h2>Disclaimer</h2>
<p>These tools rely on ImpressJS having a public API which it currently doesn't have. It's obviously high on the author's priority list (given the <a href="https://github.com/bartaz/impress.js/issues/39">amount of discussion</a> it's raised) but, as too many pull requests spoil the broth, I've made a <a href="https://github.com/thingsinjars/impress.js">little fork of my own</a>, added the public functions the tools require and I'll update them once the main repository's settled down a bit.</p>

<h2>Download</h2>
<p>These are available in the tools folder of this <a href="https://github.com/thingsinjars/impress.js">fork of impress.js</a>. Each one contains an example. Hopefully, these will be updated to use the public API as soon as it's available.</p>
      </div>
]]></description>
<pubDate>Mon, 16 Jan 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Create a draggable file on-the-fly with JS</title>
<link>http://thingsinjars.com/post/440/create-a-draggable-file-on-the-fly-with-js/</link>
<guid>http://thingsinjars.com/post/440/create-a-draggable-file-on-the-fly-with-js/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-440">
        <p><a href="http://thingsinjars.com/post/440/create-a-draggable-file-on-the-fly-with-js/">Create a draggable file on-the-fly with JS</a></p>
<p>Here's a useful little code snippet if you're building a web application. It's a simple way of making the boundary between web-browser and platform a bit smaller. It allows you to create a file (text, html, whatever) in in your page which the user can drag onto their desktop (if their browser supports the dragstart event and dataTransfer methods).</p>

<pre><code>document.getElementById('downloadElement').addEventListener("dragstart", function (e) {
  e.dataTransfer.setData("DownloadURL", "text/html:filename.html:data:image/png;base64," + btoa(fileContent));
});
</code></pre>

<p>A description of the code:</p>
<ul>
 <li>attach an event listener to the draggable element you specify (<code>downloadElement</code>)</li>
<li>when you start to drag it (<code>dragstart</code>),</li>
<li>it creates a dataTransfer object (with the type <code>DownloadURL</code>)</li>
<li>and sets the content of that to be whatever you pass it (<code>fileContent</code>)</li>
<li>It uses <code><a href="https://developer.mozilla.org/en/DOM/window.btoa">btoa()</a></code> to encode the string data as a base64-encoded string.</li>
<li>When you combine this with the MIME-type (<code>text/html</code>),</li>
<li>you can create a file with the specified name (<code>filename.html</code>) when the user releases the drag in their local file system.</li>
<li>The fake MIME-type (<code>image/png</code>) is there as part of the object data to convince the browser this is a binary file (which it is, even though it's not an image).</li>
</ul>

<p>Note: The element this is attached to (<code>downloadElement</code> above) should either be draggable by default (image, link or text selection) or have the draggable attribute set otherwise this'll do nothing.</p>

<p>Credit goes to <a href="http://paul.kinlan.me/">Paul Kinlan</a> for using this in <a href="http://appmator.appspot.com/">Appmator</a> which is where I first saw this done this way. He actually uses it alongside some extremely clever JS zip-file creation stuff, too, it's definitely worth digging through the source there.</p>

<p>You can find out more about the drag events on the <a href="https://developer.mozilla.org/En/DragDrop/Drag_Operations">MDN</a>.</p>      </div>
]]></description>
<pubDate>Thu, 08 Dec 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>cssert – Like ‘assert’ but with CSS at the front</title>
<link>http://thingsinjars.com/post/438/cssert--like-assert-but-with-css-at-the-front/</link>
<guid>http://thingsinjars.com/post/438/cssert--like-assert-but-with-css-at-the-front/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-438">
        <p><a href="http://thingsinjars.com/post/438/cssert--like-assert-but-with-css-at-the-front/">cssert – Like ‘assert’ but with CSS at the front</a></p>
<p>This continues on from my post about <a href="http://thingsinjars.com/post/437/cssert---css-verification-testing/">CSS verification testing</a></p>

<p>cssert – pronounced however you feel like it – is my attempt at bringing some kind of style verification into an automated build process. If you've read <a href="http://thingsinjars.com/post/437/cssert---css-verification-testing/">the previous article</a>, you'll know that this falls into the second group of CSS test frameworks, style measurement and comparison. The system works exactly as I described above – your test files have a basic HTML structure created by traversing the DOM from the element being tested upwards. You could also include your entire HTML in the test file if you liked, it would just be unnecessary in most cases.</p>

<p>I've created a couple of (for me, at least) helpful utilities which allow these test cases to be generated from a page via a bookmarklet and then run in the browser or on the command-line. Running the tests in the browser is useful for quick human verification while the command-line interface can be integrated into an automated build system if you like that kind of thing. The test file structure is quite simple (all samples here taken from the <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap project</a>:</p>
<p>First, we have the test file opening structure:</p>
<pre><code>&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;title&gt;cssert test page&lt;/title&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;../lib/cssert.css&quot;&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;cssert Test cases&lt;/h1&gt;&lt;p&gt;click to expand test&lt;/p&gt;&lt;script type=&quot;text/html&quot;&gt;/*==</code></pre>
<p>Then we have the name of the test:</p>
<pre><code>Intro Paragraph</code></pre>
<p>Then we have the skeleton DOM:</p>
<pre><code>&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;base href=&quot;http://twitter.github.com/bootstrap/examples/hero.html&quot;&gt;&lt;link href=&quot;../1.3.0/bootstrap.css&quot; rel=&quot;stylesheet&quot;&gt;&lt;style type=&quot;text/css&quot;&gt;
      body {
        padding-top: 60px;
      }
    &lt;/style&gt;&lt;style&gt;#cssert-style-modal {display:none;position: fixed;top: 10%;left: 50%;margin-left: -350px;width: 700px;background: #39c;color: white;padding: 10px;color: #fff;text-shadow: 0 1px 0 rgba(0,0,0,.3);background-image: -webkit-linear-gradient(-45deg, rgba(255,255,255,0), rgba(255,255,255,.1) 60%, rgba(255,255,255,0) 60%);border-radius: 5px;border: 1px solid #17a;box-shadow: inset 0 0 0 1px rgba(255,255,255,.3);}#cssert-style-modal ul,#cssert-style-modal li {margin:0;padding:0;font-size:11px;list-style:none;}#cssert-style-modal&gt;ul&gt;li {float:left;width:140px;font-size:13px;}#cssert-style-modal ul {margin-bottom:10px;}#cssert-pre {position:fixed;top:10px;right:10px;background:white;border:1px solid gray;width:200px;height:200px;overflow:auto;}#cssert-drag {position:fixed;top:210px;right:10px;background:white;border:1px solid gray;width:200px;height:20px;overflow:auto;}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;container&quot;&gt;&lt;div class=&quot;hero-unit&quot;&gt;&lt;p&gt;Vestibulum id ligula porta felis euismod semper. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</code></pre>
<p>The CSS selector identifying the element to verify:</p>
<pre><code>html body div div p</code></pre>
<p>And the styles we wish to verify:</p>
<pre><code>{"font-family":"'Helvetica Neue', Helvetica, Arial, sans-serif","font-weight":"200","font-style":"normal","color":"rgb(64, 64, 64)","text-transform":"none","text-decoration":"none","letter-spacing":"normal","word-spacing":"0px","line-height":"27px","text-align":"-webkit-auto","vertical-align":"baseline","direction":"ltr"}</code></pre>
<p>A test file can contain as many test units as you like. At the very end is the close of the test file structure</p>
<pre><code>*/&lt;/script&gt;&lt;script src=&quot;../lib/cssert.js&quot;&gt;&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</code></pre>
<p>You'll probably notice the crucial bit in the test structure is the <code>base</code> element. The CSS available from the location specified here is the thing we are actually testing. In typical test lingo, the structure we have in our test file is the mock and our tests work by asserting the values &lsquo;output&rsquo; from applying the CSS to this structure are as expected.</p>

<h2>Running the tests</h2>
<h3>Running the tests in-browser</h3>
<p>Open the test page in a browser. That's it. If it's green and says 'passed', the test passed. If it's red and says 'failed', the test failed. You can see the output by clicking on the title of the test.</p>
<p>This works by loading the test file, creating an iframe and injecting the test case into the iframe as source. It then looks into the iframe and measures the styles. If they match those specified in the test file, it passes, otherwise, it fails. Clicking on the test title simply removes the <code>position:absolute</code> which is hiding the iframe.</p>
<h3>Running the tests on command-line</h3>
<p>The exact same test page can also be used with the command-line interface. cssert uses <a href="http://phantomjs.org">PhantomJS</a> to run the tests in a headless webkit instance. You'll need to install PhantomJS into your path after downloading it. Place your test case in the tests folder and run:</p>
<pre><code>$ ./cssert testcase.html</code></pre>
<p>To run all tests in the tests folder at once, simply run with no arguments:</p>
<pre><code>$ ./cssert</code></pre>
<p>This works by, again, loading the HTML from the test files. In this case, the structure is injected into a new headless browser window. The styles are measured and the output is redirected to stdout. Each browser window test is also rendered as a PNG so you can see what failed if any did.</p>

<h2>Limitations</h2>
<p>I'm not saying this is the ultimate solution to CSS testing. Declarative languages don't sit well with testing. This is as close as I can get for the moment. I'm also not going to be able to head off or counter all possible complaints or criticisms but I will cover a couple.</p>
<p>Firstly, most of the limitations you'll run into are caused by using the automatically generated tests. They're good for creating a starting point but at the moment, they need to be tweaked for many cases.</p>
<h3>Sibling selectors</h3>
<p>Because the test generates the DOM via following parents up the structure, sibling elements are ignored. These styles are still testable, though. Simply add the sibling element into your HTML test block.</p>
<h3>Styles modified by JS</h3>
<p>The styles are measured on the element as it is when the case is generated. The test compares this against the styles provided by the CSS. If the element contains JS-only styles not added by CSS, they will not be correctly matched. Modify your test case to allow for this.</p>
<h3>Why not use Selenium?</h3>
<p>This, essentially does the same as Selenium would do if you took the time to set up your test cases. This makes it much easier to set up test cases, though.</p>
<h3>@font-face!</h3>
<p>If your @font-face declaration contains a suggested 'local' source (as recommended in Paul Irish's <a href="http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/">bulletproof syntax</a>), a <a href="https://bugs.webkit.org/show_bug.cgi?id=36351">bug in QTWebkit</a> will prevent the test case from running correctly.</p>

<h2>Installation</h2>
<p>Just clone the git project from <code>git@github.com:thingsinjars/cssert.git</code> and you're good to go.</p>
<p>The tests directory comes with some sample tests generated using Twitter's Bootstrap project. Put your tests in that same place.</p>      </div>
]]></description>
<pubDate>Mon, 28 Nov 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Copy-paste coding</title>
<link>http://thingsinjars.com/post/430/copy-paste-coding/</link>
<guid>http://thingsinjars.com/post/430/copy-paste-coding/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-430">
        <p><a href="http://thingsinjars.com/post/430/copy-paste-coding/">Copy-paste coding</a></p>
<p>This weekend, I had a spare couple of hours on Saturday night (as often happens when you have a kid) so I decided to pass the time with a bit of copy-paste coding.</p>

<p>I grabbed a bit of <a href="http://banditracer.eu/carexample/">example code for a top-down racing game</a> built using <a href="http://www.box2d.org/">Box2d</a> and <a href="http://gamejs.org/">GameJs</a>. I then grabbed a <a href="http://maps.google.com/">Google Maps</a> demo and a <a href="http://maps.nokia.com/">Nokia Maps demo</a> and smooshed them together. I've seen a few racing games before so I know there's nothing innovative here, it's just a bit of silliness.</p>

<h2>The results</h2>
<ul>
 <li><a href="http://thelab.thingsinjars.com/car2d/index-ovi.html">Driving on Nokia Maps</a></li>
 <li><a href="http://thelab.thingsinjars.com/car2d/index.html">Driving on Google Maps</a></li>
</ul>

<h2>Copy-Paste: Not a bad thing</h2>
<p>There are many developers who will tell you that blindly copy-pasting is a terrible way to code. They make the valid points that you don't understand something if you don't read it properly and that you'll end up stuck down an algorithmic cul-de-sac with no way to three-point-turn your way out (although they may phrase it differently). These are valid points but...</p>

<p>If I'd sat down on Saturday night and thought "I want to build something in Box2D" then gone to the site, downloaded the library, read the docs and loaded the examples, by the time I had understood what I was doing, Sunday morning would have come round and I'd still have GameJS to read up on. There's absolutely no harm in blindly catapulting yourself a long way down the development track then looking round to see where you are. Sure, you'll end up somewhere unfamiliar and you may end up with absolutely no clue what the code around you does but at least you have something to look at while you figure it out. At least a few times, you'll find something almost works and a quick search of the docs later, you've figured it out and know what it's doing.</p>

<p>Basically, copy-pasting together a simple little demo and making it work is a lot more interesting than taking baby-steps through example code and beginner tutorials. Don't be too careful about trying to build something complicated.</p>

<h2>An Idea</h2>
<p>If you're in the mood for copy-paste coding, try taking the two demos above (Google and Nokia), grab the node.js server from the <a href="http://thingsinjars.com/post/412/multi-user-pages/">multi-user page experiment</a> and figure out how to have multiple racers on the same map (by transmitting angle and geo-coords).</p>      </div>
]]></description>
<pubDate>Mon, 31 Oct 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Sine</title>
<link>http://thingsinjars.com/post/429/sine/</link>
<guid>http://thingsinjars.com/post/429/sine/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-429">
        <p><a href="http://thingsinjars.com/post/429/sine/">Sine</a></p>
<p>Another game concept prototype &ndash; <a href="http://thelab.thingsinjars.com/sine/">Sine</a></p>

<p>Honestly, I have no idea what I was going for with this one. It started off last weekend with a vague idea about matching patterns of numbers and old-school graphics and I don't know what and ended up with this.</p>

<p>The idea is to make the bottom row match the top row, basically. There are several front-ends to this game so you can choose the style of play you prefer - numbers and letters, waves, colours or a generated sound wave (if you have a shiny new-fangled browser). It uses the nifty little <a href="http://codebase.es/riffwave/">Riffwave library</a> to generate PCM data and push it into an audio element.</p>

<h2>Further development</h2>
<p>If I were to develop this further, I'd try and build it in a modular fashion so that front-ends could be generated really easily and open it to other people to see how many different ways this game could be played. It'd be an interesting social experiment to be able to play what is fundamentally the same game in a dozen different ways. You could find out if visual thinkers processed the information faster than numerical or audio-focused people. Leaderboards could allow different styles of player to compete on the same playing field but with a different ball (hmm, weak sports analogy). The rhythms of the game lend themselves well to generated drum tracks so there's probably something in that area for exploring as well.</p>

<p>At the moment, the code is written as the programming equivalent of stream-of-consciousness &ndash; global variables everywhere, some camel-case, some underscored, vague comments sprinkled around. There's some commented-out code for the wave mode that moves the waves closer together so that there's a time-limit set but I felt it didn't suit the game.</p>


<h2>Warning</h2>
<p>The audio mode is <strong>very</strong> annoying. Seriously. If I were still a full-time game designer, I would not release this due to public health concerns. As I'm now an enthusiastic amateur, here you go :D</p>      </div>
]]></description>
<pubDate>Fri, 21 Oct 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Text Editors</title>
<link>http://thingsinjars.com/post/426/text-editors/</link>
<guid>http://thingsinjars.com/post/426/text-editors/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-426">
        <p><a href="http://thingsinjars.com/post/426/text-editors/">Text Editors</a></p>
<p>Many years ago during the text-editor holy wars, I sided neither with the Vi Ninjas nor the Emacs Samurai but instead went a third way &ndash; <a href="http://en.wikipedia.org/wiki/Pico_(text_editor)">Pico</a> (short for Pine Composer). It was the text editing part of the e-mail program I used (<a href="http://www.washington.edu/pine/">Pine</a>). For many years, this served me well. Even today, Pico's successor - <a href="http://www.nano-editor.org/">Nano</a> &ndash; is installed pretty much everywhere. It isn't , however, quite powerful enough for fast-paced web development. Serious, full-time development needs shortcuts and macros, syntax highlighting and snippets. When you spend 10 or more hours every day <a href="http://xkcd.com/722/">pressing buttons to change flashing lights</a>, you need to optimise the way the lights flash.</p>

<p>After Pico, I found <a href="http://www.crimsoneditor.com/">Crimson Editor</a> which served me well for almost 10 years. I eventually started working on a Mac and became a <a href="http://macromates.com/">TextMate</a> user for most of the last 5 years.</p>

<p>In my new job, I find myself jumping from computer to computer to desktop to server quite a lot. The only constant editor available is Vi. Or Vim (Vi Improved). I've been trying to pick it up as a way to ensure I can always jump into a friendly text editor no matter where I am. Besides, these days Vim is the old-new-cool thing that all the cool-old-kids use, particularly MacVim so I thought it was worth giving it a go to see what the fuss was about.</p>

<p>Incidentally, the first thing that always jumped into my head whenever anybody mentioned Vi was the <a href="http://vimgolf.com/">Vim Golf</a> challenge two of my lecturers played while I was at Uni. It's a well-known and surprisingly popular game where two Seventh-dan Vi proficients try to accomplish an edit on a file using the fewest keystrokes. Each morning, one lecturer would lay down a challenge and the other had 24 hours to come up with a solution before presenting it and the next challenge the following day. The (possibly apocryphal) conclusion to the long-running game came when it was discovered that the lecturer who won most often was actually recompiling the network install of Vim every night to include his own custom keyboard shortcuts.</p>

<p>One of the biggest deciding factors in trying it out was actually fellow Edinburgh Web Dev/International Traveller Drew Neil (<a href="https://twitter.com/nelstrom">@nelstrom</a>), creator and voice of the <a href="http://vimcasts.org/">vimcasts.org</a> series of screencasts who is actually writing a book on Vim this very second as I write this. Most people are evangelical about their choice of text editor to the point of rabid fundamentalist, frothing-at-the-mouth, intoning-keyboard-shortcuts craziness (hence my allusions to text-editor holy wars). When I mentioned to Drew that I used Pico instead, his response was long the lines of "Fair enough". This lack of confrontation actually inspired me to try it out. Well played, sir.</p>

<p>In an unrelated aside, I once did an <a href="http://all-sorts.org/blog/illustrations#surrealists">illustration</a> for the '<a href="http://all-sorts.org/blog/illustrations">Collective Nouns Illustrated</a>' project Drew ran.</p>

<p>Anyway, I'll give it a go and see what happens. If you're interested, I recommend reading Yehuda Katz' post '<a href="http://yehudakatz.com/2010/07/29/everyone-who-tried-to-convince-me-to-use-vim-was-wrong/">Everyone Who Tried to Convince Me to use Vim was Wrong</a>'. Don't worry, I'm definitely not going to try and convince anyone to use one code editor over another. You should probably stop using FrontPage, though.</p>      </div>
]]></description>
<pubDate>Thu, 06 Oct 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Whitehat Syndication</title>
<link>http://thingsinjars.com/post/424/whitehat-syndication/</link>
<guid>http://thingsinjars.com/post/424/whitehat-syndication/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-424">
        <p><a href="http://thingsinjars.com/post/424/whitehat-syndication/">Whitehat Syndication</a></p>
<p>When I refer to Google or Googlebot here, I could really be talking about any web search or web crawler. When I refer to Yahoo, I actually mean Yahoo. Don't get confused.</p>

<p>I recently ran into an interesting SEO problem on a project which has led to a question I just don't know the answer to:</p>

<p>How do you display syndicated content without triggering Google's duplicate content flag?</p>

<p>Hmm... intriguing.</p>

<h2>Background</h2>
<p>To explain the problem more fully (without giving out any project specifics), imagine you have a website. You probably already do so that shouldn't be hard. Now, imagine you fill that website full of original content. Again, that shouldn't be hard. For the sake of example, let's assume you run a news blog where you comment on the important stories of the day.</p>

<p>Next, you figure that your readers also want to read important related facts about the news story. Associated Press (AP) syndicates its content and through the API, you can pull in independently-checked related facts about whatever your original content deals with. So far, so good.</p>

<p>Unfortunately, a thousand other news blogs also pull in the same AP content alongside their original (and some not-so-original) content. Now, when the Googlebot crawls your site, it finds the same content there as it does in a thousand other places. Suddenly, you're marked with a 'duplicate content' black flag and all the lovely google juice you got from writing original articles has been taken away. Boo.</p>

<p>Your first thought might be to reach for the <code>rel="canonical"</code> attribute but that really only applies to entire pages. We need something that only affects a portion of the page.</p>

<h2>Solution</h2>
<p>What you need to do is find a way to include the content in your page when a visitor views it (providing extra value for readers) but prevent Google from reading it (hurting your search ranking). Fortunately, there are some methods for doing this. One involves having the content in an external JS file which is listed in your robots.txt to prevent Google from reading it. Another similar method involves having the content in an external HTML and including it as an iframe, again, preventing crawling via robots.txt. When the reader visits the page, the content is there, when Google visits, it isn't.</p>

<h2>The Problem with the Solution</h2>
<p>Both of the techniques mentioned here involve an extra HTTP request. You are including an external file so the visitor's browser has to go to your server, grab the file and include it. This isn't a huge problem for most sites but when you're dealing with high-traffic, highly-optimised websites, every file transferred counts. You go to all the trouble of turning all background <a href="http://spriteme.org/">images into sprites</a>, why waste extra unnecessary connections on content?</p>
	
<p>There is an extra problem with the JS solution in that the content isn't available to visitors that don't have JS enabled but as I've <a href="http://thingsinjars.com/post/382/html5-for-large-public-bodies/" title="HTML5 for Large Public Bodies">mentioned before</a>, that's only a problem if any of your visitors actually have JS disabled. Only you know that for sure.</p>

<h2>Yahoo's Solution</h2>
<p>Yahoo have a nice solution to this problem. If you include the attribute <code>class="robots-nocontent"</code> on any element, the Yahoo spider (called 'slurp') will ignore the content. Perfect. This does, however, only work for Yahoo. Not perfect.</p>

<h2>My solution</h2>

<p>My attempt at solving this problem which is a combination of SEO and high front-end performance was inspired by the technique <a href="http://googlecode.blogspot.com/2009/09/gmail-for-mobile-html5-series-reducing.html" title="Gmail for Mobile HTML5 Series: Reducing Startup Latency - The official Google Code blog">GMail uses to deliver JS to mobile devices</a>. In their article, Google delivers JS that they don't want run immediately in the initial payload. They figure that the cost of serving a single slightly larger HTTP request is less than the delay in retrieving data on demand.</p>

<p>I use HTML embedded in a JS comment in the original page which is then processed on DOMReady to strip out the comments and inject it into wherever it is supposed to be (identified by the <code>data-destination</code> attribute). I'm doing this on a page which already loads jQuery so this can all be accomplished with a simple bit of code.</p>

<pre><code>&lt;script type=&quot;text/html&quot; class=&quot;norobot&quot; data-destination=&quot;.content-destination&quot;&gt;
 /*!
  &lt;p&gt;This content is hidden on load but displayed afterwards using javascript.&lt;/p&gt;
 */
&lt;/script&gt;
&lt;div class=&quot;content-destination&quot;&gt;&lt;/div&gt;
&lt;script src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
 $(&#x27;.norobot').each(function() {
  _this = $(this);
  $(_this.data(&#x27;destination&#x27;)).html(_this.html().replace(&#x27;/*!&#x27;,&#x27;&#x27;).replace(&#x27;*/&#x27;,&#x27;&#x27;));
 });
&lt;/script&gt;</code></pre>

<h2>Notes on the code</h2>
<p>You may have noticed the <code>type="text/html"</code> attribute on the script block. That's to get around the fact that jQuery parses and executes any script blocks it finds when moving elements around (in an appendTo() or an html(), for example. Adding this attribute tells jQuery to process this as template code. </p>

<p>Also, the opening JS comment here begins <code>/*!</code>. The exclamation mark in this is a directive to any minifiers you might use on the code to tell them not to remove this comment block.</p>

<p>This is also available in a <a href="http://thelab.thingsinjars.com/Post-Load/index.html">standalone page</a>.</p>

<p>This is all a very long setup for my initial question. Does Google read this and, if so, does this affect duplicate content rankings?</p>

<h2>Plus and Minus</h2>
<ul><li><strong>Minus</strong>: The duplicate content is definitely in the page.</li>
<li><strong>Plus</strong>: It's hidden in JavaScript</li>
<li><strong>Minus</strong>: we're using JavaScript to serve different content to users and to google.</li>
<li><strong>Plus</strong>: we're showing less to google than users. Spam techniques show more to increase keyword matches. </li>
<li><strong>Plus</strong>: faster response due to a single http request (Google likes fast pages)</li>
</ul>

<p>Obviously, we could add an extra step of obfuscating the 'hidden' content by reversing it or encoding it. This would definitely hide it from google and it would be trivial to undo the process before showing it to the user but is this step necessary? Part of my reasoning for concluding that Google ignores JS comments is that thousands of sites include the same standard licences bundled with their JS library of choice and don't get penalised. This may, of course, be specific to licences, though.</p>

<p>I can find no definitive answer anywhere on this subject. If you have any good references, please let me know. Alternatively, if you happen to know <a href="http://www.mattcutts.com">Matt Cutts</a>, ask him for me. If I get any conclusive answer, I'll update here.</p>

      </div>
]]></description>
<pubDate>Mon, 03 Oct 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>A collection of bookmarklets</title>
<link>http://thingsinjars.com/post/415/a-collection-of-bookmarklets/</link>
<guid>http://thingsinjars.com/post/415/a-collection-of-bookmarklets/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-415">
        <p><a href="http://thingsinjars.com/post/415/a-collection-of-bookmarklets/">A collection of bookmarklets</a></p>
<p>Bookmarklets are the handiest little things. In case you don't know (which I'm sure you do), they're small chunks of JS that you store in your browser's Bookmarks or Favourites section which you can launch while looking at any web page. I write bookmarklets for all kinds of different tasks &ndash; navigating quickly around the build monitor at work, filling in tricky forms that my browser autocomplete doesn't handle, etc. </p>

<p>Here are a few of bookmarklets I find extremely useful for web development. To add them to your browser, simply drag the link on the title into your bookmark bar, hold shift down and drag or right-click and 'Add to Favourites', depending on what browser you're in.</p>

<h2><a title="Add Script" href="javascript:(function(){document.body.appendChild(document.createElement('script')).src=prompt('Script to add');})();">Add JS to the page by URL</a></h2>
<p>This will allow you to add any script you like to the current page. This can be particularly useful if you want to add a certain library or plugin to a page to investigate it further.</p>
<pre><code>javascript:(function(){document.body.appendChild(document.createElement('script')).src=prompt('Script to add');})();</code></pre>

<h2><a title="Add jQuery" href="javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://code.jquery.com/jquery-latest.min.js'})();">Add the latest CDN jQuery to the page</a></h2>
<p>A variation on the above bookmarklet, this simply adds the latest version of jQuery. If you want to be able to play with a page and are familiar with jQuery, this will ensure that it is loaded and attached.</p>
<pre><code>javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://code.jquery.com/jquery-latest.min.js'})();</code></pre>

<h2><a title="Add CSS" href="javascript:(function(d){if(d.createStyleSheet)%20{d.createStyleSheet(%20u%20);}%20else%20{var%20css=d.createElement(%27style%27),u=prompt(%27CSS%20to%20add%27);css.setAttribute(%22type%22,%22text/css%22);css.appendChild(document.createTextNode(%22@import%20url(%22+u+%22)%22));d.getElementsByTagName(%22head%22)[0].appendChild(css);}}(document))">Add CSS to the page by URL</a></h2>
<p>Add any stylesheet to the current page with a particular URL. This is handy if you want to demo variations to clients, I find. particularly if you predefine the CSS URL.</p>
<pre><code>javascript:(function(d){if(d.createStyleSheet)%20{d.createStyleSheet(%20u%20);}%20else%20{var%20css=d.createElement(%27style%27),u=prompt(%27CSS%20to%20add%27);css.setAttribute(%22type%22,%22text/css%22);css.appendChild(document.createTextNode(%22@import%20url(%22+u+%22)%22));d.getElementsByTagName(%22head%22)[0].appendChild(css);}}(document))</code></pre>



<h2><a title="Submit to a specific reddit" href="javascript:window.location=%22http://www.reddit.com/r/webdev/submit?url=%22+encodeURIComponent(window.location)+'&title='+encodeURIComponent(document.title);void(0);">Submit this page to the webdev subreddit</a></h2>
<p>This isn't so much a web dev helper, more a general helper. I use this (or a variation thereof) to submit posts to specific <a href="http://www.reddit.com/">reddits</a> with fields prefilled. This bookmarklet defaults to the <a href="http://www.reddit.com/r/webdev/">webdev</a> subreddit.</p>
<pre><code>javascript:window.location=%22http://www.reddit.com/r/webdev/submit?url=%22+encodeURIComponent(window.location)+&#x27;&amp;title=&#x27;+encodeURIComponent(document.title);void(0);</code></pre>

<h2><a href="javascript:(function(){var div = document.createElement('div'); div.innerHTML ='xstyle' +prompt('Style to add')+ '/style';document.body.appendChild(div.lastChild);})();">Add a CSS rule to the page</a></h2>
<p>I can't remember whether I wrote this one or if I found it somewhere. The 'x&lt;style&gt;' is something from the middle of jQuery, though. Anyhow.</p>
<p>This allows you to add a style block directly into the page. This is useful for small CSS injections where the browser's web inspector is unavailable or incapable. Even though it's a single prompt that pops up, there's no reason why you can't past an entire stylesheet in there. I sometimes find myself doing that when I'm previewing designs on a production server.</p>
<pre><code>javascript:(function(){var div = document.createElement(&#x27;div&#x27;); div.innerHTML =&#x27;x&lt;style&gt;&#x27; +prompt(&#x27;Style to add&#x27;)+ &#x27;&lt;/style&gt;&#x27;;document.body.appendChild(div.lastChild);})();</code></pre>      </div>
]]></description>
<pubDate>Mon, 28 May 2012 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Workflow. The flow. Of work.</title>
<link>http://thingsinjars.com/post/408/workflow-the-flow-of-work/</link>
<guid>http://thingsinjars.com/post/408/workflow-the-flow-of-work/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-408">
        <p><a href="http://thingsinjars.com/post/408/workflow-the-flow-of-work/">Workflow. The flow. Of work.</a></p>
<h2>How to actually work</h2>
<p>Don&rsquo;t tell anyone (particularly not your clients and especially not my clients) but making websites is really very easy. Don't make it harder by deliberately hindering yourself. You should always try to travel the shortest distance between &ldquo;amends needs done&rdquo; and &ldquo;amend is done&rdquo;. Again, I hear a &ldquo;Pah!&rdquo; in the distance, &ldquo;Well, that&rsquo;s obvious.&rdquo;, but is it? Are you sure you&rsquo;re ‘Being all you can be&rsquo;?</p>
<h2>The shortest distance</h2>
<p>Okay, picture the scene: you've run out of socks. You need to put on a load of washing. The washing is in a pile in the corner of the room. You hunch over, pick up all the socks, pants, t-shirts and walk, waddle and totter to the washing machine. As you walk, you drop a sock and bend down to pick it up, dropping another. You recover that one and another falls. Eventually, you make it to the washing machine after a few minutes, put everything in, throw in some powder and set it going. As you head back to your bedroom, you spot three more socks that you missed. Darn.</p>
<p>Okay, picture the scene: you've run out of socks. You need to put on a load of washing. Fortunately, every time you took your socks off, you put them straight in the washing machine. You wander to the kitchen, put in the powder and switch it on. Done.</p>
<p>Any time you try to do anything, the more steps involved between intention and completion, the more likely it is to go wrong. Whether the intention is 'wear clean socks' or 'update this website', if you can do it in a handful of steps, you'll make fewer mistakes than if you have to do it in a hunched-over armful.</p>
<h2>Workflow. The flow. Of Work.</h2>
<p>The next time you're making an amend somewhere, watch yourself. Watch which applications you jump between. Don't just make your changes, pay attention to how you do them. Are you jumping between text editor and FTP client? Text editor and web browser? FTP and Subversion? Just take a few minutes to think about which steps you might be able to miss out. For instance, if you use Textmate and Transmit, you can set up DockSend so that pressing ctrl-shift-f then 2 will upload the file you currently have open to the same place on the server. You can now change the editor↔FTP↔browser cycle to editor↔browser.</p>
<h2>However...</h2>
<p>Seamless does not imply flawless. Don't be tempted to simplify to the stage where you don't need any interaction between making a change and the change being live. If you rely on the fact that your changes 'just happen', you might be tempted not to check. That's the point at which they don't 'just happen'.</p>
<p>This article is modified from a chapter in a book <a href="http://www.phenotypic.co.uk">Andrew</a> and I were writing a couple of years ago about web development practical advice. Seeing as we both got too busy to finish it, I'm publishing bits here and there. If you'd like to see these in book form, let me know.</p>      </div>
]]></description>
<pubDate>Fri, 28 Oct 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Testing</title>
<link>http://thingsinjars.com/post/406/testing/</link>
<guid>http://thingsinjars.com/post/406/testing/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-406">
        <p><a href="http://thingsinjars.com/post/406/testing/">Testing</a></p>
<h2>The web is a visual medium. Well, mostly.</h2>
<p>There's no better way to test a visual medium than by looking at it. Look at your site in as many browsers as you can. If you've already got as many browsers installed on your development computer as you can fit, get another computer and install some more. Either that or run a Virtual Machine.</p>


<h2>Definition: Virtual Machine (VM)</h2>
<p>Applications like VirtualBox, VMWare or Parallels allow you to run an entire computer within your computer. It is a self-contained system that doesn't interact with your own machine meaning you can have IE6 installed on one VM, IE7 on another and IE8 on a third. All running in a window on your iMac. Shiny.</p>


<p>If you can't do that easily, you could use one of the growing number of browser testing services. These are server rooms packed with computers running Virtual Machines and automated systems to which you supply a URL, wait a few moments and get shown an image (or several hundred images) showing your URL in different browsers on different platforms. Some of the more sophisticated services allow you to scroll down a long page or specify different actions, text entry or mouse events you want to see triggered. These services can be exceptionally useful when it comes to developing HTML e-mails as there are some rare and esoteric e-mail clients out in the wild. <a href="http://litmus.com/">Litmus</a> does an excellent job at virtualised testing for HTML e-mails. On that note, the Campaign Monitor <a href="http://www.campaignmonitor.com/templates/">library of free HTML e-mail templates</a> is a great place to start, learn and possibly finish when working on an HTML e-mail.</p>

<p>There is also a place for automated testing for some things. Recently, there has been a bit of a movement away from validating code as the purpose of web development is not to make it 'check a box' on a merely technical level, it is to get the message across via the design however possible. However, validation is still the best and easiest way to check your syntax. Syntax errors are still the main cause for mistakes appearing in your web sites and are the easiest thing to fix. Don't assume IE is wrong. Again, if you're keen on HTML e-mails, here's a <a href="http://litmus.com/blog/validating-html-for-email">great post on the Litmus blog</a>.</p>

<p>This article is modified from a chapter in a book <a href="http://www.phenotypic.co.uk">Andrew</a> and I were writing a couple of years ago about web development practical advice. Seeing as we both got too busy to finish it, I'm publishing bits here and there. If you'd like to see these in book form, let me know.</p>      </div>
]]></description>
<pubDate>Fri, 09 Sep 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Torch</title>
<link>http://thingsinjars.com/post/401/torch/</link>
<guid>http://thingsinjars.com/post/401/torch/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-401">
        <p><a href="http://thingsinjars.com/post/401/torch/">Torch</a></p>
<h2>Concept</h2>
<p>Another proof-of-concept game design prototype. This is kind of a puzzle game. Ish. It's mostly a simple maze game but one in which you can't see the walls. You can see the goal all the time but you are limited to only being able to see the immediate area and any items lit up by your torch. You control by touching or clicking near the torch. The character will walk towards as long as you hold down. You can move around and it'll follow.</p>

<p><a href="http://apps.angryrobotzombie.com/torch/">Torch v0.1</a></p>

<p>The first 10 levels are very easy and take practically no time at all. After that, they get progressively harder for a while before reaching a limit (somewhere around level 50, I think). The levels are procedurally generated from a pre-determined seed so it would be possible to share high scores on progression or time taken without having to code hundreds of individual levels. </p>

<p>Items that could be found around the maze (but aren't included in this prototype) include:</p>

<ul>
<li>Spare torches which can be dropped in an area and left to cast a light</li>
<li>Entrance/exit swap so that you can retrace your steps to complete the level </li>
<li>Lightning which displays the entire maze for a few seconds (but removes any dropped torches)</li>
<li>Maze flips which flip the maze horizontally or vertically to disorient you.</li>
</ul>

<p>I worked on this for a few months (off and on) and found it to be particularly entertaining with background sound effects of dripping water, shuffling feet with every step, distant thunder rumbling. It can be very atmospheric and archaeological at times.</p>


Half-way through a level, two torches dropped
<img src="http://thingsinjars.com/uploaded/images/maze.png" alt="Torch, the game">


<h2>Slightly technical bit</h2>
<p>The game loop and draw controls are lifted almost line-for-line from this <a href="http://dev.opera.com/articles/view/creating-pseudo-3d-games-with-html-5-can-1/">Opera Dev article on building a simple ray-casting engine</a>. I discarded the main focus of the article - building a 3D first-person view - and used the top-down mini map bit on its own. The rays of light emanating from the torch are actually the rays cast by the engine to determine visible surfaces. It's the same trick as used in <a href="http://en.wikipedia.org/wiki/Wolfenstein_3D">Wolfenstein 3D</a> but with fewer uniforms. It's all rendered on a canvas using basic drawing functionality.</p>

<p>The audio is an interesting, complicated and confusing thing. If I were starting again, I'd look at integrating an existing sound manager. In fact, I'd probably use an entire game engine (something like <a href="http://impactjs.com/">impact.js</a>, most likely) but it was handy to remember how I used to do stuff back in the days when I actually made games for a living. Most of all, I'd recommend not looking too closely at the code and instead focusing on the concept.</p>

<h2>Go, make.</h2>
<p>As with <a href="http://thingsinjars.com/post/390/knots/">Knot</a> from my previous blog post, I'm not going to do anything with this concept as I'm about to start a big, new job in a big, new country and I wanted to empty out my &lsquo;To do&rsquo; folder. The code's so scrappy, I'm not going to put it up on GitHub along with my other stuff, I seriously do recommend taking the concept on its own. If you are really keen on seeing the original code, it's all unminified on the site so you can just grab it from there.</p>

<p>The usual rules apply, if you make something from it that makes you a huge heap of neverending cash, a credit would be nice and, if you felt generous, you could always buy me a larger TV.</p>

<p><a href="http://apps.angryrobotzombie.com/torch/">Torch v0.1</a></p>      </div>
]]></description>
<pubDate>Mon, 11 Jul 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Knots</title>
<link>http://thingsinjars.com/post/390/knots/</link>
<guid>http://thingsinjars.com/post/390/knots/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-390">
        <p><a href="http://thingsinjars.com/post/390/knots/">Knots</a></p>
<h2>Game design</h2>
<p>I had an idea around Christmas for a new game design. it was basically to be a single or multi-player game where you would tie knots in a piece of &lsquo;string&rsquo;. The single-player game would focus on discovering new patterns while the multi-player one would be a time-based challenge where each would tie a knot, pass it over to their opponent and the first to untie it would win.</p>

<p>I built a basic prototype and had some fun inventing a few interesting knots (my favourite being &lsquo;Yoda&rsquo;) but didn't get round to doing anything with it. As I'm tidying up all my projects before immigrating to Germany, I figured I should just go ahead and put this out into the world.</p>

<p><a href="http://apps.angryrobotzombie.com/knot/">Knot v0.1</a></p>

<h2>Slightly technical bit</h2>
<p>The system is built using an invisible 3x3 grid and 4 quadratic curves. The curves' start, control and end points are the centre of a tile. When you move a tile, it basically swaps position with the tile nearest where you drop it. This can also be done with multiple tiles simultaneously if you're on a multi-touch device. You can see the tiles if you enable debug mode. You can also switch between the two colour schemes it has at the moment.</p>


Yoda in Knot form
<img src="http://thingsinjars.com/uploaded/images/yoda.png" alt="Yoda Knot">


<p>The only addition I've made to it since Christmas was to add on a system to allow players to save knots back into the system. I've only built in 22 patterns so if you make a nice, interesting or funny one, give it a recognisable name (nothing too rude, please) and save it, it will then be available to everybody who plays with it. You can also set whether the pattern is to count as &lsquo;matched&rsquo; when rotated 90&deg;, 180&deg;, flipped vertically or flipped horizontally. Calculating the isomorphisms (when two knots look the same to the viewer but aren't necessarily the same to the computer) was probably the trickiest bit of the system.</p>

<h2>Go, make.</h2>
<p>If you're interested in taking the idea further, <a href="https://github.com/thingsinjars/Knot">grab the code from GitHub</a> and make something from it. The usual rules apply, if you make something from it that makes you a huge tonne of neverending cash, a credit would be nice and, if you felt generous, you could always buy me a larger TV.</p>

<p><a href="http://apps.angryrobotzombie.com/knot/">Knot v0.1</a></p>
      </div>
]]></description>
<pubDate>Mon, 27 Jun 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>HTML5 for Large Public Bodies</title>
<link>http://thingsinjars.com/post/382/html5-for-large-public-bodies/</link>
<guid>http://thingsinjars.com/post/382/html5-for-large-public-bodies/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-382">
        <p><a href="http://thingsinjars.com/post/382/html5-for-large-public-bodies/">HTML5 for Large Public Bodies</a></p>
<h2>Your country needs you...</h2>

<p>...to stand at the cutting edge of technology.</p>

<p>Sounds awfully impressive, don't you think?</p>

<p>There are quite a few regulations to bear in mind and comply with when developing a website for a Government organisation or any large public body. This has lead to a lot of sites being developed in a very defensive manner, ensuring safe compliance at the expense of a great and consistent user experience.</p>

<p>This video features a presentation about how large publicly-liable institutions should and can embrace the latest in web technologies without sacrificing standards. By embracing them, in fact.</p>

<p>The content of this was developed while planning and building the <a href="http://www.nms.ac.uk/">National Museums Scotland website</a> which launched last November. The messages presented are applicable to museums, galleries, swimming pools, councils, anywhere, really.</p>

<p>If you're a techie person in the cultural or government sector, you might find this useful in convincing others to take advantage of the latest cool (and useful) technologies.</p>

<h2>Video</h2>
<p><a href="http://vimeo.com/24436131">HTML5 for Large Public Bodies</a> from <a href="http://vimeo.com/madine">Simon Madine</a> on <a href="http://vimeo.com">Vimeo</a>.</p>

<h2>Links from the presentation</h2>
<ul>
<li><a href="http://remysharp.com/2010/10/08/what-is-a-polyfill/">PolyFills</a></li>
<li><a href="http://www.netmagazine.com/features/making-html5-and-css3-work-polyfills-and-shims">.NET magazine article</a></li>
<li><a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills">(Almost) complete list of polyfills</a></li>
<li><a href="http://diveintohtml5.org/">Dive into HTML5</a></li>
<li><a href="http://html5boilerplate.com/">HTML5 Boilerplate</a></li>
<li><a href="http://www.smashingmagazine.com/2009/08/04/designing-a-html-5-layout-from-scratch/">Smashing Magazine</a></li>
<li><a href="http://html5doctor.com/">HTML5 Doctor</a></li>
<li><a href="http://alpha.gov.uk/">AlphaGov</a></li>
</ul>

<h2>Slideshow</h2>
<p>The source for the slides is <a href="http://thingsinjars.com/widgets/html5-presentation/">available online</a> although it's mostly webkit-friendly. I realise the irony of a presentation about cross-platform HTML5 not being a great example itself of that but it does degrade adequately. If I get the time in the future, I'll tidy it up. An actual good (and relevant) example of cross-platform web technologies is the <a href="http://www.nms.ac.uk/">National Museums Scotland website</a> itself which performs fantastically across all manner of platforms.</p>      </div>
]]></description>
<pubDate>Tue, 31 May 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Psychopathic megalomaniac vs Obsequious sycophant?</title>
<link>http://thingsinjars.com/post/380/psychopathic-megalomaniac-vs-obsequious-sycophant/</link>
<guid>http://thingsinjars.com/post/380/psychopathic-megalomaniac-vs-obsequious-sycophant/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-380">
        <p><a href="http://thingsinjars.com/post/380/psychopathic-megalomaniac-vs-obsequious-sycophant/">Psychopathic megalomaniac vs Obsequious sycophant?</a></p>
<h2> - or - </h2>
<h2>Tabs vs Spaces?</h2>
<p>Which are you? Is there any middle ground?</p>

<p>In any modern, code-friendly text editor, you can set tab size. This means that one tab can appear to be as wide as a single space character or - more commonly - 2 or 4 spaces. It's even possible in some to set any arbitrary size so there's nothing stopping you setting tabs to be 30 spaces and</p>
<pre><code>format() {
                              your code() {
                                                            like;
                              }
                              this;
}</code></pre>

<p>However you do it, the point is that using tabs allows the reader personal preference.</p>

<p>Indenting your code using spaces, however, is completely different. A space is always a space. There's actually a simple conversion chart:</p>

<ul>
<li>1 = One</li>
<li>2 = Two</li>
<li>3 = Three</li>
<li>and so on.</li>
</ul>
<p>The fundamental difference here is that the person reading the code has no choice about how it's laid out. Tabs means you get to read the code how <em>you</em> want to, spaces means you read the code how <em>I</em> want you to. It's a subtle difference but an important one. </p>

<p>Space indenting is therefore perfectly suited to psychopathic megalomaniacs who insist their way is right while tab indenting is for obsequious sycophants who are putting the needs of others above themselves. Sure, there may be lots of grades in-between but why let moderation get in the way of a barely coherent point?</p>

<p>
Curiously, neither of these extremes feels a great need to comment their code. One sees no need as their code is for themselves and they already understand it, the other assumes that if they can understand it, its purpose is so obvious as to be trivial. Both are wrong here.</p>

<p>There's unfortunately no real middle ground here. Teams must agree amongst themselves what side of the fence they fall down on. It is entirely possible to set many text editors to automatically convert tabs to spaces or spaces to tabs on file save but if you're doing that, you'd better hope your favourite diff algorithm ignores white space otherwise version control goes out the window.</p>
<p>This article is modified from a chapter in a book <a href="http://www.phenotypic.co.uk">Andrew</a> and I were writing a couple of years ago about web development practical advice. Seeing as we both got too busy to finish it, I'm publishing bits here and there. If you'd like to see these in book form, let me know.</p>      </div>
]]></description>
<pubDate>Mon, 25 Jul 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Archiving Tweets</title>
<link>http://thingsinjars.com/post/378/archiving-tweets/</link>
<guid>http://thingsinjars.com/post/378/archiving-tweets/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-378">
        <p><a href="http://thingsinjars.com/post/378/archiving-tweets/">Archiving Tweets</a></p>
<h2>Archiving Tweets - Technical</h2>
<p>Twitter has an amazing amount of data and there's no end to the number of ideas a coffee-fuelled mind can come up with to take advantage of that data. One of the greatest advantages of Twitter – its immediacy, its currency, its of-the-moment-ness – is, however, also one of the drawbacks. It is very easy to find out what people are thinking about now, yesterday or a few days ago but trying to find something from more than a week ago is surprisingly tricky. The standard, unauthenticated search only returns the last 7 days of results, beyond that, there's nothing. You can get around this by building custom applications which authenticate themselves correctly with Twitter and provide a level of traceability but that's quite tricky.</p>
<p>The easiest way to archive search results for your own personal use is actually surprisingly simple. Every search results page includes an RSS feed link<a href="http://thingsinjars.com/post/378/archiving-tweets/#foot_378_1" id="foot_378_a" class="footnote">1</a>. This will be updated everytime there are new results. Simply subscribe to this feed with a feed reader (<a href="http://reader.google.com">Google Reader</a> is simple and free) and your results will be archived permanently. This is great if you're searching for personal interest stuff but doesn't work so well if you want to share the results with the public.</p>
<p><a href="http://thingsinjars.com/post/378/archiving-tweets/#foot_378_a" id="foot_378_1" class="footnote">1</a> Note: The feed link only appears for searches performed on <a href="http://search.twitter.com">search.twitter.com</a>, <em>not</em> for searches performed via the standard web interface at <a href="https://twitter.com/#!/search/">https://twitter.com/#!/search/</a></p>
<p>This was the problem I was presented with when I was asked to build a tweet-archiving mechanism for <a href="http://www.museum140.com/">Museum140's</a> <a href="http://memories.museum140.com">Museum Memories (#MusMem)</a> project. Jenni wanted some kind of system that would grab search results, keep them permanently and display them nicely. I didn't want to create a fully OAuth-enabled, authenticated search system simply because that seemed like more work than should really be necessary for such a simple job. Instead, I went down the RSS route, grabbing the results every 10 minutes and storing them in a database using <a href="http://code.google.com/p/rssingest/">RSSIngest</a> by Daniel Iversen. The system stores the unique ID of each Tweet along with the time it was tweeted and the search term used to find it. The first time a tweet is displayed, a request is made to the Twitter interface to ask for all the details, not only of the tweet, but also of the user who tweeted it. These are then stored in the database as well. This way, we don't make too many calls to Twitter and we don't get blocked.</p>
<p>If you want your own Tweet Archive, I've <a href="https://github.com/thingsinjars/TweetArchiver">put the code on GitHub</a> for anyone to use. It requires PHP, MySQL and, ideally, a techie-type to set it up.</p>
<h2>Archiving Tweets - Non-technical</h2>
<p>With the technical side out of the way, we're left with the human issues to deal with. If you're automatically saving all results with a particular phrase, all a malicious person needs to do is include that phrase in a spam-filled tweet or one with inappropriate language and suddenly, it's on your site, too. If you aren't going to individually approve each tweet before it is saved, you must keep a vigilant eye on it.</p>
<p>The other thing which has turned out to be a problem is the Signal-to-Noise ratio. When we initially decided on the hashtag #MusMem, nobody else was using it. To use Social Media parlance, there was no hashtag collision.  The idea was to encourage people to use it when they wanted their memories stored in the MemoryBank. Unfortunately, it is now being used by anyone tweeting anything related to Museums and Memories. This is particularly troublesome at the moment as this month is International Museum month, one of the themes of which is ‘Memory’ (which is why we built the MemoryBank in the first place). This means that the permanent memories we want stored (the Signal) are getting lost in the morass of generic Museum Memories (the Noise). There is no way to solve this problem algorithmically. If we are to thin it down, we actually need to manually edit the several thousand entries stored.</p>
<p>If anyone can think of a solution to this issue, please let everybody know – the world needs you.</p>      </div>
]]></description>
<pubDate>Mon, 23 May 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Investigating IE's innerHTML</title>
<link>http://thingsinjars.com/post/371/investigating-ies-innerhtml/</link>
<guid>http://thingsinjars.com/post/371/investigating-ies-innerhtml/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-371">
        <p><a href="http://thingsinjars.com/post/371/investigating-ies-innerhtml/">Investigating IE's innerHTML</a></p>
<p>Be warned, this is a long and quite techy post that rambles a bit. It's about JS, <a href="http://jquery.com/" title="jQuery: The Write Less, Do More, JavaScript Library">jQuery</a>, IE and XML namespaces. Be careful.</p>
<p>I'm currently working on a tool which uses JS to parse an XML document and output it as JSON. Straightforward enough, you'd think. The issue I'm fighting against crops up when the XML tags have an arbitrary namespace. True enough, some of the files I'll be processing have this namespace defined at the top of the document but the tool has to be robust enough to cope when they don't.</p>
<p>To cut a long story short, IE6, IE7 and IE8 have an interesting attitude to innerHTML when the tags you are trying to insert have a namespace. IE9 seems to do the job as you'd expect. I've created some <a href="http://jsfiddle.net">jsFiddle</a> pages which try and identify the issues. They both use <a href="http://docs.jquery.com/Qunit" title="QUnit - jQuery JavaScript Library">QUnit</a> and the test code is included below.</p>
<h2>createElement nodeName vs get(0).nodeName</h2>
<p><a href="http://jsfiddle.net/thingsinjars/j4xJG/">View this on jsFiddle.net</a></p>
<p>I started off using jQuery to help identify this as the tool uses jQuery for the XML heavy-lifting. The two tests in this demo create elements in two different ways. First, we create the element using document.createElement and grab the nodeName then we use jQuery's constructor and use get(0) to grab the bare DOM element's nodeName. Also, in this first set of tests, we're creating non-standard elements.</p>
<pre><code class="prettyprint lang-js">
test("Compare elements without namespace", function() {
 var element1, element2;

 element1 = document.createElement('spud').nodeName;
 element2 = $('&lt;spud/&gt;').get(0).nodeName;

 equals(element1, element2, "We expect these to match");
});
</code></pre>

<p>The code above runs fine everywhere – IE, FireFox, Opera, Chrome, etc. etc. Good.</p>

<pre><code class="prettyprint lang-js">
test("Compare elements with namespace", function() {
 var element1, element2;

 element1 = document.createElement('a:spud').nodeName;
 element2 = $('&lt;a:spud/&gt;').get(0).nodeName;

 equals(element1, element2, "We expect these to match");
});
</code></pre>

<p>This runs fine in non-IE browsers, they all report the nodeName as <code>'a:spud'</code>. IE now reports the nodeName as <code>'spud'</code>. Ah. I dug through the jQuery source, tracking down the bare roots of the constructor and eventually figured out that just looking at the element itself isn't going to provide any clues. The bit that does the actual string-to-elements work (somewhere around <a href="https://github.com/jquery/jquery/blob/master/src/manipulation.js#L587">line 5619 in jQuery 1.5.2</a>) creates a container div then injects the (slightly modified) code as innerHTML. The issue must be in IE's interpretation of innerHTML, I thought to myself. And then to you by writing it here.</p>

<h2>.innerHTML aside</h2>
<h3>or ‘jQuery is clever’</h3>
<p>Before we continue with this long and, ultimately, unnecessary investigation into namespaces, I have to take a small diversion to cover some smart stuff jQuery does. One thing in particular, in fact. Around that line I mentioned earlier (5619-ish), an extra bit of text is inserted into the innerHTML to cope with IE's oddity. If you are trying to create a non-standard element using innerHTML, IE will not complain but also just do pretty much nothing at all:</p>
<pre><code class="prettyprint lang-js">        var div = document.createElement('div');
        div.innerHTML = '&lt;spud&gt;&lt;/spud&gt;';
        alert(div.innerHTML);
</code></pre>
<p>The above code will alert <code>'&lt;spud&gt;&lt;/spud&gt;'</code> in most browsers but <code>''</code> in IE. What jQuery does is firstly wrap your element in an extra <code>&lt;div&gt;&lt;/div&gt;</code> (producing <code>'&lt;DIV&gt;&lt;/DIV&gt;'</code>) then prepends the word 'div' to that. The innerHTML reported by IE is now <code>'div&lt;DIV&gt;&lt;SPUD>&lt;/SPUD&gt;&lt;/DIV&gt;'</code>! There it is! Next, the extra gubbins is removed by calling .lastChild and you're left with <code>innerHTML = '&lt;SPUD&gt;&lt;/SPUD&gt;'</code>. That's pretty darned clever.</p>

<h2>.innerHTML vs document.appendChild</h2>
<p><a href="http://jsfiddle.net/thingsinjars/4ZsKU/">View this on jsFiddle.net</a></p>
<p>Back on track. Armed with this little trick, we can reliably test innerHTML in IE using non-standard elements.</p>

<pre><code class="prettyprint lang-js">
module("Known elements (span)");
 test("Compare elements without namespace", function() {
  var div1, div2;

  div1 = document.createElement('div');
  div1.innerHTML = '&lt;span&gt;&lt;/span&gt;';

  div2 = document.createElement('div');
  div2.appendChild(document.createElement('span'));

  equals(div1.innerHTML.toLowerCase(), div2.innerHTML.toLowerCase(),
     "We expect these to match");
 });

 test("Compare elements with namespace", function() {
  var div1, div2;

  div1 = document.createElement('div');
  div1.innerHTML = '&lt;u:span&gt;&lt;/u:span&gt;';

  div2 = document.createElement('div');
  div2.appendChild(document.createElement('u:span'));

  equals(div1.innerHTML.toLowerCase(), div2.innerHTML.toLowerCase(),
     "We expect these to match");
 });
</code></pre>

<p>The first test in this pair runs fine everywhere exactly as we'd hope and expect. The second fails miserably in IE. Let us quickly run the same test with unknown elements just to make sure we're identifying the right problem:</p>

<pre><code class="prettyprint lang-js">module("Unknown elements (spud)");
 test("Compare elements without namespace", function() {
  var div1, div2;

  div1 = document.createElement('div');
  div1.innerHTML = 'div&lt;div&gt;' + '&lt;spud&gt;&lt;/spud&gt;' + '&lt;/div&gt;';
  div1 = div1.lastChild;

  div2 = document.createElement('div');
  div2.appendChild(document.createElement('spud'));

  equals(div1.innerHTML.toLowerCase(), div2.innerHTML.toLowerCase(),
     "We expect these to match");
 });
 test("Compare elements with namespace", function() {
  var div1, div2;

  div1 = document.createElement('div');
  div1.innerHTML = 'div&lt;div&gt;' + '&lt;u:spud&gt;&lt;/u:spud&gt;' + '&lt;/div&gt;';
  div1 = div1.lastChild;

  div2 = document.createElement('div');
  div2.appendChild(document.createElement('u:spud'));

  equals(div1.innerHTML.toLowerCase(), div2.innerHTML.toLowerCase(),
     "We expect these to match");
 });
</code></pre>

<p>As before, the first test in this pair works fine, the second fails. Cool. Or not. Either way, you can now see that it doesn't really matter whether the elements are standard or custom and that little diversion we took earlier really was unnecessary. Still, you know more now about some of the cleverness in jQuery than you did before.</p>

<p>It turns out the reason IE reports the nodeNames as the non-namespaced ones is because it has been busy behind the scenes and added an extra XML namespace prefix into our current context. The innerHTML of the div we filled up using innerHTML has been modified to:</p>

<pre><code class="prettyprint lang-js">  &lt;?xml:namespace prefix = u /&gt;
  &lt;u:span&gt;&lt;/u:span&gt;
</code></pre>

<p>Where'd that namespace declaration come from?! Goshdarnit, IE. From its point of view, within that little context, <code>u:span</code> is equivalent to <code>span</code></p>

<h2>The most stripped-down example</h2>
<p><a href="http://jsfiddle.net/thingsinjars/pfQbG/" title="Checking validity of innerHTML">View this on jsFiddle</a></p>
<p>Seriously, it does not get more fundamental than this.</p>
<pre><code class="prettyprint lang-js">element = document.createElement('div');
testHTML = '&lt;div&gt;&lt;/div&gt;';
element.innerHTML = testHTML;
element.innerHTML.toLowerCase() == testHTML.toLowerCase() 
</code></pre>
<p>The last line there is true for all browsers.</p>
<pre><code class="prettyprint lang-js">element = document.createElement('div');
testHTML = '&lt;a:div&gt;&lt;/a:div&gt;';
element.innerHTML = testHTML;
element.innerHTML.toLowerCase() == testHTML.toLowerCase() 
</code></pre>
<p>The last line there is true for all browsers <em>except IE 6, 7 and 8!</em></p>

<h2>In conclusion?</h2>
<p>Ultimately, there are no winners here. Identifying the problem is quite different from fixing it. I've added a note to the relevant <a href="http://bugs.jquery.com/ticket/4208">jQuery bug</a> in the tracker but it's not so much a bug in jQuery as a humorous IE quirk. There's some talk of refactoring the <a href="http://api.jquery.com/find/" title=".find() &#8211; jQuery API">.find() method</a> to handle more complicated tagnames so this might get picked up then. The fix will probably be something along the lines of checking the outcome of the innerHTML doesn't have an unexpected namespace declaration when the selector has a colon in it:</p>
<pre><code class="prettyprint lang-js">div.replace( /]*>/g, '' )</code></pre>
<p>I'd submit the patch myself but I'm having difficulty getting unmodified jQuery to build on any of my machines without failing most of the QUnit tests. I've probably typed something wrong.</p>      </div>
]]></description>
<pubDate>Fri, 01 Apr 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Autogenerated Everything</title>
<link>http://thingsinjars.com/post/369/autogenerated-everything/</link>
<guid>http://thingsinjars.com/post/369/autogenerated-everything/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-369">
        <p><a href="http://thingsinjars.com/post/369/autogenerated-everything/">Autogenerated Everything</a></p>
<p>After seeing this <a href="http://www.dubberly.com/concept-maps/3x4grid.html">collection</a> of the 892 different ways you can partition a 3 x 4 grid<a href="http://thingsinjars.com/post/369/autogenerated-everything/#generate_foot_1" id="generate_foot_a" class="footnote">1</a>, I was struck by a thought. If these were generated as HTML templates, they could be combined with a couple of other useful websites and become a nice, API-driven site builder<a href="http://thingsinjars.com/post/369/autogenerated-everything/#generate_foot_2" id="generate_foot_b" class="footnote">2</a>.</p>

<h2>The process</h2>
<ul>
	<li>On the site-building webpage, you'd enter a few keywords describing the site you want and drag a slider along between 1 and 12 to specify how many content areas you want. The value from the slider would be used to pick a template randomly from the number available for that combination of panels.</li>
	<li>This template would be dropped into the middle of an <a href="http://www.html5boilerplate.com/">HTML 5 boilerplate</a> (possibly generated via <a href="http://initializr.com">Initializr</a>)</li>
	<li>The keywords would be passed to <a href="http://colorapi.com/">ColorAPI</a> to generate an asthetically pleasing colour-scheme</li>
	<li>The keywords would then be passed to <a href="http://flickholdr.com/">FlickHoldr</a> along with the dimensions of some of the areas from the template to get relevant imagery</li>
	<li>Grab some lorem ipsum of the right length from <a href="http://loremipscream.com/api">LoremIpscream</a> to fill out the content areas of the site</li>
	<li>Done. Your asthetically pleasing, nicely designed site is ready to download within a few seconds.</li>
</ul>

<p>Once this service has been created, I'm fairly sure me and the rest of the industry will be out of a job.</p>


	<p><a id="generate_foot_1" href="http://thingsinjars.com/post/369/autogenerated-everything/#generate_foot_a" class="footnote">1</a> Technically, there are 3,164 ways you can partition the grid but most of them are vertical or horizontal mirrors of the 892 mentioned.</p>
	<p><a id="generate_foot_2" href="http://thingsinjars.com/post/369/autogenerated-everything/#generate_foot_b" class="footnote">2</a> There are a few references to <a href="http://3x4grid.com">3x4grid.com</a> which is apparently going to be an API-accessible collection of these layouts but there doesn't seem to be anything there yet.</p>
      </div>
]]></description>
<pubDate>Fri, 01 Apr 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>8 bit alpha</title>
<link>http://thingsinjars.com/post/368/8-bit-alpha/</link>
<guid>http://thingsinjars.com/post/368/8-bit-alpha/</guid>
<description><![CDATA[
        <div class="teaser " id="teaser-368">
        <p><a href="http://thingsinjars.com/post/368/8-bit-alpha/">8 bit alpha</a></p>
Another week, another launch. I really need to find a cure for whatever illness I have that results in compulsion to built stuff. Maybe there's a Builders Anonymous group where you can go for support in coming to terms with the fact that you don't always <em>have to</em> solve the problem yourself. Learn to accept that sometimes things are just the way they are.

Pshaw!

A few days ago, I read <a href="http://calendar.perfplanet.com/2010/png-that-works/">this article</a> by <a href="http://pornel.net/">Kornel Lesiński</a>. It describes the curious and interesting ways of PNGs, particularly highlighting the fact that the 8-bit PNG with an embedded alpha channel needs a lot more love than it gets. It gives you the small file sizes you get from 8-bit PNGs (resulting from the maximum 255 colour palette) but also the benefits of a full partial transparency alpha channel unlike GIFs or standard 8-bit PNGs in which pixels are on or off, nothing in between. The reason this file type is ignored is because the most common web graphic creation application in the world (Adobe Photoshop) doesn't support them. At least not yet. You need Adobe Fireworks or some other application to convert your 24-bit alpha channel images.

After a quick search turned up nothing but instructions on how to enable command-line convertion on a Linux server, I figured this would be a handy web service. Drag, Drop, Download, Done. This also gave me an excuse to play with some <a href="https://developer.mozilla.org/en/using_files_from_web_applications">File API</a> stuff. In the end, I decided to use a <a href="https://github.com/pangratz/dnd-file-upload">jQuery plugin</a> because there was a greater chance that it had been tested and bugfixed than my own script.

<h2><a href="http://www.8bitalpha.com">8-bit alpha</a></h2>

With a name like that, I had to go for a retro theme. I even created a nice <a href="http://www.8bitalpha.com/images/spinner.gif" title="eight bit indicator image">8-bit spinner</a>.

If you have a use for the service, <a href="http://twitter.com/thingsinjars">let me know</a>, if you want to learn how it works, <a href="https://github.com/thingsinjars/8bitalpha">browse the source</a>. If you want to popularise the phrase “Drag, Drop, Download, Done” for this kind of simple web application, do that too.      </div>
]]></description>
<pubDate>Fri, 25 Mar 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Shelvist</title>
<link>http://thingsinjars.com/post/367/shelvist/</link>
<guid>http://thingsinjars.com/post/367/shelvist/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-367">
        <p><a href="http://thingsinjars.com/post/367/shelvist/">Shelvist</a></p>
<p>I've been a bit quiet for the last couple of weeks. Now I can reveal why!</p>
<p>All my spare time has been taken up building <a href="http://shelvi.st/">Shelvist</a> (well, that <em>and</em> looking after a 4-month old). It's a way of keeping track of which books you have read, which ones you are currently reading and which ones you want to read. That's it. </p>
<p>Just over a year ago, I started listening to a lot of audiobooks and, 12 months after I subscribed to <a href="http://www.audible.co.uk">Audible</a>, I decided I wanted to see just how many books I'd read<a class="footnote" href="http://thingsinjars.com/post/367/shelvist/#foot_367_1">*</a>. All the existing book tracking sites (e.g. <a href="http://shelfari.com">Shelfari</a>, <a href="http://www.goodreads.com/">Goodreads</a>) focus on recommending, rating, reviewing which just seemed like hard work.</p>
<p><a id="foot_367_1" class="footnote">*</a>Listening to an audio book counts as reading. It just sounds weird if you tell people you listened to a book.</p>
<p>Building this was also a chance to learn some new tech. I've been wanting to play with <a href="http://www.cakephp.org">CakePHP</a> for a while so this seemed like the best opportunity. It's been a while since I used any kind of framework and I've never used a PHP MVC framework (although I did build one last year as an intellectual exercise).</p>
<p>I got over 90% of the site built in spare time over about 5 days and most of that was spent just reading the CakePHP docs. The reason for the lengthy delay between initial build and launch is down to that last 10%. As often happens with frameworks, <em>nearly everything</em> you'd ever need to do is bundled into some nice, easy to access functionality. That is, after all, kinda the point of a framework. It's the stuff that makes your product or website unique that proves trickier. I won't go into any details just now although I might come back to it in a later post. </p>
<p>More later, first of all, go shelve some books: <a href="http://shelvi.st/">Shelvist</a>.</p>      </div>
]]></description>
<pubDate>Fri, 18 Mar 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Scoped Style</title>
<link>http://thingsinjars.com/post/360/scoped-style/</link>
<guid>http://thingsinjars.com/post/360/scoped-style/</guid>
<description><![CDATA[
        <div class="teaser " id="teaser-360">
        <p><a href="http://thingsinjars.com/post/360/scoped-style/">Scoped Style</a></p>
I couldn't let it lie. The nifty JavaScript from <a href="http://thingsinjars.com/post/359/css-scoped/">the previous post</a> was all well and good but I had to have a go at jQuery plugin-ifying it. It has been Enpluginated.

Your options now are simple:
<ol>
<li>Have a look at <a href="http://thelab.thingsinjars.com/scoped/index.html">a demo</a></li>
<li><a href="https://github.com/thingsinjars/jQuery-Scoped-CSS-plugin">Check out the source on GitHub</a></li>
<li><a href="https://github.com/thingsinjars/jQuery-Scoped-CSS-plugin/archives/master">Download it</a> and start scoping some styles.</li>
</ol>

If you still have no idea what I'm talking about, you can <a href="http://www.w3.org/TR/html5/semantics.html#the-style-element">read about the attribute</a>. There are still a couple of bugs when the scoped blocks are deeply nested within other scoped areas so I'm hoping someone with a keen sense of how to straighten out Webkit oddness can help. When browsers don't implement functionality, it's a bit tricky to guess what they'd mean.

Aside from that, it's cross-browser (IE7+) compatible and ready to use. I'm interested to know if anyone finds it useful or finds any odd combinations of styles that don't scope nicely.      </div>
]]></description>
<pubDate>Sun, 30 Jan 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>CSS Scoped</title>
<link>http://thingsinjars.com/post/359/css-scoped/</link>
<guid>http://thingsinjars.com/post/359/css-scoped/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-359">
        <p><a href="http://thingsinjars.com/post/359/css-scoped/">CSS Scoped</a></p>
<p>Update: <a href="http://thingsinjars.com/post/360/scoped-style/">Bam! Plugin'd</a></p>
<p>One of the things in HTML5 that caught my eye a while back was the new 'scoped' attribute for style tags. The idea of it is that you can include a style element mid-document, mark it as scoped and its declarations will only apply to the style elements parent element and its child elements. The styles won't affect anything outside this. The biggest problem with bringing in this attribute is that it's not backwards compatible. If you include a style block mid-page, its declarations will be applied to ever element whose selector matches, inside or outside scope. It is anti-progressively enhancable. This means that designers and developers can't start using it until there's enough support. What we need is another of those JS tricks to make it usable.</p>

<p>Possibly the idea of having a style block dropped into the middle of a semantic document strikes you as a distasteful but thinking practically, this could make CMS workflows a bit easier and keep global stylesheets clean of lots of one-off specific styles. For example, <a href="http://thingsinjars.com/post/334/testing-css3-stuff/">this post</a> describing striped CSS backgrounds could have benefited from having the demo directly within the body of the post but, without going into the backend to add an extra id, this could have messed up the layouts for all other posts.</p>

<p>My first attempt at solving this problem with JS involved generating a unique class, adding it to the parent element and then parsing the style blocks using <a href="http://www.glazman.org/JSCSSP/">JSCSSP</a> so that I could rewrite them with the new class to add specificity. This approach only worked for the most basic declarations, unfortunately. The parser worked perfectly but there's a lot of detail in CSS specificity that mean this would be a much larger problem than I thought.</p>

<p>My second attempt involved:</p>
<ol>
<li>Allowing the style blocks to affect everything on the page (at which point, the elements in-scope look right, those out-of-scope look wrong)</li>
<li>Using JS to read the current computed styles of each element in-scope and copy them to a temporary array</li>
<li>Emptying out the scoped style element (in-scope look wrong, out-of-scope looks right)</li>
<li>Copying the styles back from the temporary array onto each element</li>
</ol>

<p>The first couple of versions only work in webkit, the latest (below) works in mozilla, too.</p>

<p>This <a href="http://thelab.thingsinjars.com/scoped/index-single.html">worked great</a> unless you had <a href="http://thelab.thingsinjars.com/scoped/index-multiple.html">more than one</a> scoped block – step 1 allowed scoped styles to affect each other.</p>

<p>The current attempt involves temporarily emptying all other scoped styles before taking the computed styles from a block. I'm now just thinking that this method might not work if you have multiple scoped blocks within the same context. Oh well, there's something to fix in the future.</p>

<p><a href="http://thelab.thingsinjars.com/scoped/index-js.html">This is where I'm at just now</a>.</p>

<p>Yes, it's a mess, yes the JS is scrappy and yes, it doesn't currently work in IE but I'll get round to that next. It took long enough to get it working in Firefox as there's no simple way to convert a ComputedCSSStyleDeclaration to a string in Mozilla unlike Webkit's implementation of cssText or IE's currentStyle. I might even make it into one of those new-fangled jQuery plugins everyone's using these days.</p>
      </div>
]]></description>
<pubDate>Fri, 28 Jan 2011 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Testing CSS3 stuff</title>
<link>http://thingsinjars.com/post/334/testing-css3-stuff/</link>
<guid>http://thingsinjars.com/post/334/testing-css3-stuff/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-334">
        <p><a href="http://thingsinjars.com/post/334/testing-css3-stuff/">Testing CSS3 stuff</a></p>
<p>You may have seen Google's 'Watch this space' advertising appearing all over the place. They have quite eye-catching diagonally striped backgrounds in various colours. A couple of days ago, I was wondering how easy it would be to recreate this in CSS without images. Unfortunately, the state of CSS 3 is such that some things work wonderfully, some just plain don't (scoped attribute, I'm looking at you). The following code relies on vendor extensions and so, unless you're willing to tend it and correct it after the spec is finalised, don't use this on a production server.</p>
<p>The most obvious thing to notice from the following code, though, is the competing syntax for the repeating linear gradient style. Mozilla have separated it into a distinct style (<code>-moz-repeating-linear-gradient</code>) while Webkit have built it as an option to their general gradient style (<code>-webkit-gradient</code>).</p>
<pre><code class="prettyprint">body {
	background-image: -moz-repeating-linear-gradient(
		-45deg,
		transparent,
		transparent       25%,
		rgba(0,0,0,0.15)  25%,
		rgba(0,0,0,0.15)  50%,
		transparent       50%,
		transparent       75%,
		rgba(0,0,0,0.15)  75%,
		rgba(0,0,0,0.15)
	);
	background-image: -webkit-gradient(
		linear,
		0% 0%,
		100% 100%,
		from(transparent),
		color-stop(0.25, transparent),
		color-stop(0.25, rgba(0,0,0,0.15)),
		color-stop(0.50, rgba(0,0,0,0.15)),
		color-stop(0.50, transparent),
		color-stop(0.75, transparent),
		color-stop(0.75, rgba(0,0,0,0.15)),
		to(rgba(0,0,0,0.15))
	);
}</code></pre>
<p>To get a better idea of what this does, view source on <a href="http://thelab.thingsinjars.com/watch-these-stripes.html">this demo page</a>. This includes a button to change the class on the body (using JS) which simply changes the background colour – the stripes are semi-transparent on top of that. Remember, due to the vendor prefixes, this only works in -moz or -webkit browsers.</p>
<p>It's supposed to look like this:</p>
<ul class="gallery"><li><a href="http://thingsinjars.com/uploaded/images/striped.png" rel="lightbox"><img src="http://thingsinjars.com/uploaded/images/thumbs/striped.png" /></a></li></ul>      </div>
]]></description>
<pubDate>Wed, 08 Dec 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Writing a Plex Plugin Part III</title>
<link>http://thingsinjars.com/post/299/writing-a-plex-plugin-part-iii/</link>
<guid>http://thingsinjars.com/post/299/writing-a-plex-plugin-part-iii/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-299">
        <p><a href="http://thingsinjars.com/post/299/writing-a-plex-plugin-part-iii/">Writing a Plex Plugin Part III</a></p>
<p>This is the final part of <a href="http://blah.thingsinjars.com/post/297/writing-a-plex-plugin-part-i/" title="geek - thingsinjars">my walkthrough</a> of the <a href="http://www.plexapp.com">Plex Media Server</a> <a href="http://transmissionbt.com">Transmission</a> plugin.</p>
<p>Right.</p>
<p>We've done the <a href="http://blah.thingsinjars.com/post/297/writing-a-plex-plugin-part-i/" title="geek - thingsinjars">required built-in functionality</a> (preference management, for instance) and <a href="http://blah.thingsinjars.com/post/298/writing-a-plex-plugin-part-ii/">the bits that talk to Transmission</a> itself. Basically, we're done. Anything else added here is just extra. That is, of course, the best reason to add stuff here. As I have <a href="http://thingsinjars.com/post/248/its-not-difficult-dont-make-it-difficult/">previously ranted</a> at length, there's no point doing anything if you aren't trying to do it as well as it possibly can be done. In this particular instance, that manifests itself in the ability to browse, search for and download torrents all within the Plex client interface.</p>

<h2>EZTV</h2>
<p>I love <a href="http://ezrss.it">EZTV</a>. It makes things easy. Previous versions of this plugin included an EZTV search but after rooting around in the source of the µTorrent plugin, I found some nifty code which turned me onto the clever XML parsing Plex can do.</p>
<p>Note: although some of this stuff looks clever, all the cleverness was done by the Plex dev team and the author of the µTorrent plugin. I'm a good copy-and-paster.</p>

<p>This function grabs the H2s from the page <a href="http://ezrss.it/shows/">http://ezrss.it/shows/</a>. If you go there, you'll see that the page lists every TV show in EZTV. The original µTorrent function listed everything but there are a lot of shows there now so it was actually taking a long time just to get that list. As they've split the page up by section, we can just grab the bits we want. This is going to be a full page in Plex (not a popup) so we're using a MediaContainer.</p>
<pre><code class="prettyprint">def TVShowListFolders(sender):
  dir = MediaContainer()</code></pre>

<p>Using the built-in XML module, we can simply pass in a URL and get back an object containing the hierarchical structure of the entire page. Seriously, how simple is this? As it's HTML, add in the option <code class="prettyprint">isHTML=True</code>.</p>
<pre><code class="prettyprint">  showsPage = XML.ElementFromURL(
                'http://ezrss.it/shows/', 
                isHTML=True, 
                errors='ignore'
              )</code></pre>

<p>Now that we have the whole page structure, take the chunks of the page we want. All the sections we want (and one we don't) are divs with the class 'block' so use that in xpath to pull them out.</p>
<pre><code class="prettyprint">  blocks = showsPage.xpath('//div[@class="block"]')</code></pre>

<p>The first block is the one we don't want (if you look at the page, it's the one that lists all the letters) so we remove it.</p>
<pre><code class="prettyprint">  blocks.pop(0)</code></pre>

<p>For each of the remaining blocks, find the text in the first H2. That is the letter title of the section ('A', 'B', 'C', etc). Add that to Plex as a menu item then return the entire list.</p>
<pre><code class="prettyprint">  for block in blocks:
    letter = block.xpath("h2")[0].text
    dir.Append(
      Function(
        DirectoryItem(
          TVShowListSubfolders,
          letter,
          subtitle=None,
          summary=None,
          thumb=R(ICON),
          art=R(ART)
        ),
        letter=letter
      )
    )
  return dir</code></pre>
<p>I hope I'm not the only one impressed with that (although I have a feeling I might be). Using just a couple of lines from the XML module and a sprinkle of xpath and we've got another menu, dynamically generated from a third-party website. If EZTV ever change their layout, it should be a simple matter of changing the xpath to match and we're done. Again.</p>

<p>We can now do the same again but this time, we only pull out a single section based on the letter passed in.</p>
<pre><code class="prettyprint">def TVShowListSubfolders(sender, letter):
  dir = MediaContainer()
  showsPage = XML.ElementFromURL(
                'http://ezrss.it/shows/',
                isHTML=True,
                errors='ignore'
              )
  blocks = showsPage.xpath(
            '//div[@class="block" and h2 = "%s"]' % letter
           )</code></pre>

<p>Remembering to ignore any 'back to top' links, write out a list of the shows in this section. These will call the TVEpisodeList method next.</p>
<pre><code class="prettyprint"> for block in blocks:
  for href in block.xpath('.//a'):
   if href.text != "# Top":
    requestUrl = "http://ezrss.it" + href.get("href") + "&mode=rss"
    dir.Append(
     Function(
      DirectoryItem(
       TVEpisodeList,
       href.text,
       subtitle=None,
       summary=None,
       thumb=R(ICON),
       art=R(ART)
      ),
      name=href.text,
      url=requestUrl
     )
    )
 return dir</code></pre>

<p>This lists all available torrents for the chosen show. By this point, you should be familiar with how this works. We're using the XML module to grab the page at the URL (this time it's an RSS feed so we don't need to parse it as HTML); we use XPath to iterate through the items in the feed; we generate a menu item from the data which will call a function when selected; we append that to a MediaContainer then return the whole thing to Plex. Done. The AddTorrent function was defined <a href="http://blah.thingsinjars.com/post/298/writing-a-plex-plugin-part-ii/">higher up</a>.</p>
<pre><code class="prettyprint">def TVEpisodeList(sender, name, url):
 dir = MediaContainer()
 feed = XML.ElementFromURL(url, isHTML=False, errors='ignore').xpath("//item")
 for element in feed:
  title = element.xpath("title")[0].text
  link = element.xpath("link")[0].text
  dir.Append(
   Function(
    DirectoryItem(
     AddTorrent,
     title,
     subtitle=None,
     summary=None,
     thumb=R(ICON),
     art=R(ART)
    ),
    torrentUrl=link
   )
  )
 return dir</code></pre>

<h2>Adult considerations...</h2>
<p>There is currently a section in the plugin which will allow you to search IsoHunt. This might get dropped in future versions of the plugin as results from IsoHunt are almost exclusively...ahem...adult, regardless of search terms. Sure, that might be exactly what you were looking for but if you were actually looking for Desperate Housewives, you might be surprised when your file comes down and it's actual 'desperate housewives'...</p>

<h2>Search EZTV</h2>
<p>The final part is a straightforward search of EZTV. The interesting thing to note is that this uses a different type of menu item. Where normally, you'd use a DirectoryItem in a Function, this uses an InputDirectoryItem in a Function. This type of menu item will pop open an on-screen keyboard before calling the target function giving you the opportunity to grab some user input.</p>

<p>It's appended to the menu in the usual way:</p>
<pre><code class="prettyprint"> dir.Append(
  Function(
   InputDirectoryItem(
    SearchEZTV,
    L('MenuSearchTV'),
    "Search the TV shows directory",
    summary="This will use EZTV to search.",
    thumb=R(SEARCH),
    art=R(ART)
   )
  )
 )</code></pre>
<p>By the way, I think there's a minor bug in the InputDirectoryItem in that it doesn't like it when subtitle is passed as a named argument. I should probably file that as a bug with <a href="http://elan.plexapp.com">Elan</a>.</p>

<p>When the user has entered their input and submitted, the named Function <code class="prettyprint">SearchEZTV</code> is called with the standard argument <code class="prettyprint">sender</code> and the extra argument <code class="prettyprint">query</code> containing the user's input.</p>
<p>This function was a lot longer in the previous version of the Framework. It was so much simpler this time round.</p>
<pre><code class="prettyprint">def SearchEZTV(sender, query=None):
  dir = MediaContainer()
  url = "http://ezrss.it/search/index.php?simple&mode=rss&show_name="
  if query != None:
   url += "%s" % query
  feed = XML.ElementFromURL(
          url, 
          isHTML=False, 
          errors='ignore'
         ).xpath("//item")
  if feed == None:
    return MessageContainer("Error", "Search failed")
  if len(feed) == 0:
    return MessageContainer("Error", "No results")
  for element in feed:
    title = element.xpath("title")[0].text
    category = element.xpath("category")[0].text
    link = element.find("enclosure").get("url")
    size = prettysize(int(element.find("enclosure").get("length")))
    dir.Append(
      Function(
       DirectoryItem(
        AddTorrent,
        title,
        subtitle=None,
        summary="Category: %s\nSize: %s" % (category,size),
        thumb=R(ICON),
        art=R(ART)
       ),
      torrentUrl=link
     )
    )
  return dir</code></pre>
  
<h2>Done</h2>
<p>That's it. The only other little thing to mention is how handy it is to use the built-in Log function. The first argument is a standard Python string, the second is 'Should this only turn up in the console when in debug mode?' to which the answer will almost always be 'True'. There is a third argument but unless you're messing with character encodings, you don't need to worry about it.</p>
<pre><code class="prettyprint">Log("Message to log is: %s %d" % (errorString, errorCode), True)</code></pre>

<h2>Go, make...</h2>
<p>If you made it to the end here, you're probably either keen to start making your own Plex plugins or <a href="http://www.flickr.com/photos/photojennic/">my wife</a> who I am going to get to proofread this. Assuming you're the former, here are some handy links:</p>

<ul>
	<li style="margin:0;"><h3><a href="http://dev.plexapp.com/docs/">Online plugin development manual</a></h3>
	<p>There are plenty of bits missing but it's still the best reference available for the framework.</p></li>
	<li style="margin:0;"><h3><a href="http://forums.plexapp.com/">Plex forums</a></h3>
	<p>Particularly the <a href="http://forums.plexapp.com/index.php?/forum/42-media-server-plugins/">Media Server Plugins forum</a></p></li>
	<li style="margin:0;"><h3><a href="https://plexapp.lighthouseapp.com/projects/31804-plex-plug-ins/overview">Plex Plugins Lighthouse</a></h3>
	<p>This is where bugs are filed, suggestions made and final plugin submission happens. It's handy for picking little tips if someone else has had the same problem as you.</p></li>
</ul>
<p>If you want to use the plugin, it's available in 'Plex Online' in Plex/Nine or 'Plex App Store' in Plex/Eight. If you'd like to read through the complete source, you can download the zipped .Bundle.
<p><a href="http://thingsinjars.com/uploaded/other/Transmission.bundle.zip">Transmission Plugin for Plex Media Server v1.0 [Zip - 1.1MB]</a></p>
      </div>
]]></description>
<pubDate>Thu, 30 Sep 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Writing a Plex Plugin Part II</title>
<link>http://thingsinjars.com/post/298/writing-a-plex-plugin-part-ii/</link>
<guid>http://thingsinjars.com/post/298/writing-a-plex-plugin-part-ii/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-298">
        <p><a href="http://thingsinjars.com/post/298/writing-a-plex-plugin-part-ii/">Writing a Plex Plugin Part II</a></p>
<p>This is part two of <a href="http://blah.thingsinjars.com/post/297/writing-a-plex-plugin-part-i/" title="geek - thingsinjars">my walkthrough</a> of the <a href="http://www.plexapp.com">Plex Media Server</a> <a href="http://transmissionbt.com">Transmission</a> plugin.</p>
 
<p>The previous part dealt with the basic required functions and preparing the main menu. This bit goes through the torrent control and the next will cover the built-in site-scraping functionality. To be honest, I'm not sure how much of this middle section will be of use to anyone but other torrent client plugin makers. The cool stuff really happens in the next one. Think of this as the difficult second album that you have to listen to before the return-to-form third.</p>
 
<h2>Listing the torrents</h2>
<p>This is the main interface to Transmission. Using the <code class="prettyprint">RTC</code> method from before, this prepares a request to send via HTTP and reacts depending on the result (or error) we get back. First of all, we say we want information ('torrent-get') and we specify what info we want (the 'fields')</p>
<pre><code class="prettyprint">def TorrentList(sender):
  error, result  = RTC("torrent-get",
    { "fields": [
      "hashString","name","status",
      "eta","errorString",
      "totalSize","leftUntilDone","sizeWhenDone",
      "peersGettingFromUs",  "peersSendingToUs",  "peersConnected",
      "rateDownload",      "rateUpload",
      "downloadedEver",    "uploadedEver"
    ] }
  )</code></pre>
<p>If we get an error back, we check what it was.</p>
<pre><code class="prettyprint">  if error != None:
    if error != "Connection refused":
      return MessageContainer(
          "Transmission unavailable",
          "There was an unknown error."
      )
    else:
      return MessageContainer(
          "Transmission unavailable",
          "Please make sure Transmission is installed and running."
      )</code></pre>
 
<p>Now we have our information, we create a MediaContainer to display it. We'll be building these entries up as if they were standard library MediaItems although the final action will not be to play them.</p>
<pre><code class="prettyprint">  elif result["torrents"] != None:
    dir = MediaContainer()</code></pre>
 
<p>For each set of torrent information we get back, we need to prepare the info and make it pretty.</p>
<pre><code class="prettyprint">    for torrent in result["torrents"]:
      progress    = 100;
      summary = ""
 
      if torrent["errorString"]:
        summary += "Error: %s\n" % (torrent["errorString"])</code></pre>
 
<p>If we have some time until we're done and we're not seeding, display the progress as "12.3 MB of 45.6 GB (0%)". We add this to the MediaItem's summary field. This is where we use the <code class="prettyprint">prettysize</code> and <code class="prettyprint">prettyduration</code> functions we imported at the top. They take a computer-friendly value (1048576 bytes) and return a human-friendly one (1MB).</p>
<pre><code class="prettyprint">  if torrent["leftUntilDone"] > 0 and
    torrent["status"] != TRANSMISSION_SEEDING:
    progress = ((torrent["sizeWhenDone"] - torrent["leftUntilDone"]) /
          (torrent["sizeWhenDone"] / 100))
 
    summary += "%s of %s (%d%%)\n" % (
        prettysize(torrent["sizeWhenDone"] - torrent["leftUntilDone"]),
        prettysize(torrent["sizeWhenDone"]), progress
      )</code></pre>
 
 
<p>Similarly, if there's an estimated time until the file is finished downloading, add that to the summary as "3 days remaining"</p>
<pre><code class="prettyprint">    if torrent["eta"] > 0 and torrent["status"] != TRANSMISSION_PAUSED:
      summary += prettyduration(torrent["eta"]) + " remaining\n"
    else:
      summary += "Remaining time unknown\n"</code></pre>
 
<p>Display download status ("Downloading from 3 of 6 peers") and download and upload rates ("Downloading at 3KB/s, Uploading at 1KB/s").</p>
<pre><code class="prettyprint">  if torrent["status"] == TRANSMISSION_DOWNLOADING:
    summary += "Downloading from %d of %d peers\n" % (
      torrent["peersSendingToUs"],
      torrent["peersConnected"])
    summary += "Downloading at %s/s\nUploading at %s/s\n" % (
      prettysize(torrent["rateDownload"]),
      prettysize(torrent["rateUpload"]))</code></pre>
    
<p>For all other downloading statuses, we don't need extended information so we just return a human-friendly version of the status we get back (we do this via another method below).</p>  
<pre><code class="prettyprint">  else:
    summary += TorrentStatus(torrent)</code></pre>
 
<p>If we're seeding (the torrent has finished downloading and we're just uploading now), write out information about the uploading.</p>
<pre><code class="prettyprint">  else:
    if torrent["status"] == TRANSMISSION_SEEDING:
      summary += "Complete\n"
      progress=100
      if torrent["downloadedEver"] == 0:
        torrent["downloadedEver"] = 1</code></pre>
 
<p>"45.6GB, uploaded 22.8GB (Ratio 0.50)" and some detail about the people we're uploading to.</p>
<pre><code class="prettyprint">  summary += "%s, uploaded %s (Ratio %.2f)\n" % (
    prettysize(torrent["totalSize"]),
    prettysize(torrent["uploadedEver"]),
    float(torrent["uploadedEver"]) / float(torrent["downloadedEver"]))
  if torrent["status"] == TRANSMISSION_SEEDING:
    summary += "Seeding to %d of %d peers\n" % (
      torrent["peersGettingFromUs"],
      torrent["peersConnected"])
    summary += "Uploading at %s/s\n" % (
      prettysize(torrent["rateUpload"]))</code></pre>
 
<h3>Icon generation</h3>
<p>The next addition was a bit of a tricky point for this version of the plugin. Previous versions generated the thumbnail icon dynamically using the Python Imaging Library (PIL). It would create a progress bar showing the exact percentage and write the name of the file on the icon. In order to be able to achieve this, PIL had to be imported which generated a whole bunch of deprecation warnings. There are rumours that a future version of the plugin framework will include some functionality to generate images on-the-fly (possibly a variation of PIL itself) but until then, I decided the best way forward would be to generate the images by hand and include them in the plugin. This meant that I could either generate 101 images (0% - 100%) or display the percentage rounded off. In order to save space, I went with rounding to the nearest 10%.</p>
<pre><code class="prettyprint">  nearest = int(round(progress/10)*10)</code></pre>
 
<p>The last thing to do in this loop (remember, we're still looping through the torrent information we received all the way back up at the top of the page) is to actually add this item. It is added as a PopupDirectoryItem so that selecting it will display a context menu of action choices specified in the TorrentInfo method below. With that, we also add the summary we've spent so long crafting, the percentage icon as the thumb and a couple of extra bits of information to help later functions know what to do.</p>
<pre><code class="prettyprint">  dir.Append(
    Function(
      PopupDirectoryItem(
        TorrentInfo,
        torrent["name"],
        summary=summary,
        thumb=R("%s.png" % nearest)
      ),
      name = torrent["name"],
      status = torrent["status"],
      hash = torrent["hashString"]
    )
  )</code></pre>
 
<p>To finish this menu, we add the same functions that are available to individual torrents but acting on all – 'Pause all' and 'Resume all' – then return the menu to Plex for display.</p>
<pre><code class="prettyprint">  dir.Append(
    Function(
      DirectoryItem(
        PauseTorrent,
        L('MenuPauseAll'),
        subtitle=None,
        summary=None,
        thumb=R(PAUSE),
        art=R(ART)
      ),
      hash='all'
    )
  )
  dir.Append(
    Function(
      DirectoryItem(
        ResumeTorrent,
        L('MenuResumeAll'),
        subtitle=None,
        summary=None,
        thumb=R(RESUME),
        art=R(ART)
      ),
      hash='all'
    )
  )
  return dir</code></pre>
 
<p>Here's the TorrentStatus lookup. Again, this uses the built-in localisation function 'L' to display the text and, again, I still haven't actually translated any of it so there's still only english. I must get round to that eventually.</p>
<pre><code class="prettyprint">def TorrentStatus(torrent):
  if torrent == None or torrent["status"] == None:
    return L('TorrentStatusUnknown')
  elif torrent["status"] == TRANSMISSION_WAITING:
    return L('TorrentStatusWaiting')
  elif torrent["status"] == TRANSMISSION_CHECKING:
    return L('TorrentStatusVerifying')
  elif torrent["status"] == TRANSMISSION_PAUSED:
    return L('TorrentStatusPaused')
  elif torrent["status"] == TRANSMISSION_DOWNLOADING:
    return L('TorrentStatusDownloading')
  elif torrent["status"] == TRANSMISSION_SEEDING:
    return L('TorrentStatusSeeding')
  else:
    return L('TorrentStatusUnknown')</code></pre>
 
<h2>Torrent action menu</h2>
<p>This is the popup menu displayed when you select one of the listed torrents. The only thing to notice from these is that the option to pause is only shown for active torrents and the option to resume is only shown for paused torrents. The hash mentioned here is the id of the torrent which will be needed later.</p>
<pre><code class="prettyprint">def TorrentInfo(sender, name, status, hash):
  dir = MediaContainer()
  dir.Append(
    Function(
      DirectoryItem(
        ViewFiles,
        L('MenuViewFiles'),
        subtitle=None,
        summary=None,
        thumb=R(ICON),
        art=R(ART)
      ),
      hash=hash
    )
  )
  if status == TRANSMISSION_PAUSED:
    dir.Append(
      Function(
        DirectoryItem(
          ResumeTorrent,
          L('MenuResume'),
          subtitle=None,
          summary=None,
          thumb=R(ICON),
          art=R(ART)
        ),
        hash=hash
      )
    )
  else:
    dir.Append(
      Function(
        DirectoryItem(
          PauseTorrent,  
          L('MenuPause'),      
          subtitle=None,
          summary=None,
          thumb=R(ICON),
          art=R(ART)
        ),
        hash=hash
      )
    )
    dir.Append(
      Function(
        DirectoryItem(
          RemoveTorrent,
          L('MenuRemove'),
          subtitle=None,
          summary=None,
          thumb=R(ICON),
          art=R(ART)
        ),
        hash=hash
      )
    )
    dir.Append(
      Function(
        DirectoryItem(
          DeleteTorrent,
          L('MenuDelete'),
          subtitle=None,
          summary=None,
          thumb=R(ICON),
          art=R(ART)
        ),
        hash=hash
      )
    )
  return dir</code></pre>
 
<h2>Torrent action functions</h2>
<p>Each of the torrent action functions called (<code class="prettyprint">ViewFiles</code>, <code class="prettyprint">ResumeTorrent</code>, etc.) could have been references to a more generic function with an action option passed in but I decided to keep them distinct and separate so that any extra customisation that might be done later would be easier to do rather than hacking it in. This isn't so much a problem with this plugin but if this were to be adapted for another torrent client, there might be specific hoops that needed jumped through.</p>
<p>I won't go through each of them in detail as they are all very similar. Instead, I'll just describe one of them – <code class="prettyprint">RemoveTorrent</code>.</p>
 
<p>Each Function menu item (pretty much every menu item in this plugin) takes at least one argument: <code class="prettyprint">sender</code>. This tells Plex where it's supposed to return control after it's finished here. The second argument is the id of the torrent we want to act on.</p>
<pre><code class="prettyprint">def RemoveTorrent(sender, hash):</code></pre>
  
<p>We define the action to perform and the arguments to pass to Transmission.</p>
<pre><code class="prettyprint">  action = "torrent-remove"
  arguments = { "ids" : hash }</code></pre>
  
<p>Call Transmission's RPC via the RTC method defined earlier catching the results and any errors returned.</p>
<pre><code class="prettyprint">  error, result = RTC(action, arguments)</code></pre>
 
<p>If there's an error, any error, display it. Otherwise, display a success method. Both of these are displayed as a popup MessageContainer.</p>
<pre><code class="prettyprint">  if error != None:
    return MessageContainer("Error", error)
  else:
    return MessageContainer("Transmission", L('ActionTorrentRemoved'))</code></pre>
 
<p>Okay, so the middle section of the plugin might not be that interesting. Next time I'll cover the clever built-in XML parsing bits and everything'll be cool again. I promise.</p>      </div>
]]></description>
<pubDate>Thu, 23 Sep 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Writing a Plex Plugin Part I</title>
<link>http://thingsinjars.com/post/297/writing-a-plex-plugin-part-i/</link>
<guid>http://thingsinjars.com/post/297/writing-a-plex-plugin-part-i/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-297">
        <p><a href="http://thingsinjars.com/post/297/writing-a-plex-plugin-part-i/">Writing a Plex Plugin Part I</a></p>
<p>In my awesome home cinema setup (about which I'll need to blog sometime), I use many pieces of inter-connected software and hardware. The hub, though, is the OS X computer in the middle running the <a href="http://www.plexapp.com">Plex Media Server</a> and the <a href="http://transmissionbt.com">Transmission BitTorrent client</a>. This post describes the plugin which ties them together.</p>

<p>I've just released version 1.0 of the Transmission plugin for the Plex Media Server. As with all good software projects, there were actually many releases before 1.0 but I thought this was the right time to write up a walk-through of what the code looks like and does. I didn't write the initial version of the plugin but I've maintained it since v0.7 and now pretty much rewritten everything a couple of times. I'll post my walkthrough in a few installments because it's quite long.</p>

<p>The code as it currently stands (v1.0) is available for download below but within a few days you should also be able to download it within 'Plex Online'</p>
<p><a href="http://thingsinjars.com/uploaded/other/Transmission.bundle.zip">Transmission Plugin for Plex Media Server v1.0</a></p>
<p>As Michael A. pointed out in the comments, I haven't actually mentioned anywhere below what it is that the plugin does. For a quick overview, check out the <a href="http://wiki.plexapp.com/index.php/Transmission">Plex wiki Transmission page</a>.</p>



<p>This plugin is built to be compatible with Plex Plugin Framework v1 which initially looked like quite a major change from the previous version of the framework but isn't really that different. For Plex plugins, every time an action is performed, the system generates a URL and passes it down through its own menu structure until it gets to a plugin that handles that URL. The plugin then deals with the info in the URL however it likes. In the previous versions of this plugin, the URL was parsed manually and split into strings separated by '/'</p>

<p>For example the URL:</p>
<pre><code class="prettyprint">/video/transmission/id/status/action/</code></pre>

<p>would first cause Plex to look in its 'video' menu item and find the plugin that said it could handle 'transmission' URLs. The plugin would take the rest of the string and separate it out. First contact the Transmission application, ask for all information about the torrent called 'id', check its 'status' and then perform the 'action' if possible.</p>

<p>The new plugin does pretty much the same except I no longer manually parse the URL. The plugin still registers with Plex to say it can handle URLs starting '/video/transmission' but then it passes functions through instead of URL-catching menu items. If you're familiar with JavaScript, it's like passing an anonymous function to handle something instead of catching the event manually.</p>

<p>Anyway, here's the python code with a running commentary:</p>

<h2>Imports</h2>
<p>First we import the Plex Media Server framework:</p>
<pre><code class="prettyprint">from PMS import *
from PMS.Objects import *
from PMS.Shortcuts import *</code></pre>

<p>These are a couple of handy functions from the very first version of the plugin which make the outputs much more readable.</p>
<pre><code class="prettyprint">from texttime  import prettyduration
from textbytes  import prettysize</code></pre>

<p>This next line actually causes Plex to issue a warning. These libraries won't all be available in the next version of the framework. Instead of urllib and urllib2, developers are to use the built-in HTTP module. Unfortunately, HTTP doesn't allow access to the headers of responses and the Transmission authentication system relies on exchanging a session ID via headers.</p>
<pre><code class="prettyprint">import urllib,urllib2,base64</code></pre>

<h2>Declarations</h2>
<p>Set up some constants to save typing later on</p>
<pre><code class="prettyprint">PLUGIN_PREFIX = "/video/transmission"
PLUGIN_TITLE = "Transmission"</code></pre>

<p>This is the first call to the Localisation module. Plex plugins allow for complete string localisation via a JSON file (I've only included English in this version because my torrent-related German and Japanese are poor). This will look in the JSON file for the key 'Title' and return whatever value is associated with it (or 'Title' if there is none).</p>
<pre><code class="prettyprint">NAME = L('Title')</code></pre>

<p>More shorthand</p>
<pre><code class="prettyprint">ART        = 'art-default.jpg'
ICON      = 'icon-default.png'
SETTINGS  = 'settings-hi.png'
PAUSE      = 'pause-hi.png'
RESUME    = 'resume-hi.png'
SEARCH    = 'search-hi.png'
TV        = 'tv-hi.png'

TRANSMISSION_WAITING      = 1
TRANSMISSION_CHECKING      = 2
TRANSMISSION_DOWNLOADING  = 4
TRANSMISSION_SEEDING      = 8
TRANSMISSION_PAUSED        = 16</code></pre>


<h2>Definitions</h2>
<h3>Required</h3>
<p>Here is where we start the plugin code. This is one of the standard functions which gets called when the plugin is initialised.</p>
<pre><code class="prettyprint">def Start():</code></pre>
  
<p>Tell Plex we can handle '/video/transmission' URLs and that our main function is called 'MainMenu'</p>
<pre><code class="prettyprint">  Plugin.AddPrefixHandler(
    PLUGIN_PREFIX, 
    MainMenu, 
    PLUGIN_TITLE, 
    ICON, 
    ART)

  MediaContainer.art = R(ART)
  MediaContainer.title1 = NAME
  DirectoryItem.thumb = R(ICON)</code></pre>


<p>Another standard function, this handles the preferences. To connect to Transmission, you need the URL and port it is running on (127.0.0.1:9091 if it's on the same machine as the Plex Media Server) and the username and password if you have set them.</p>
<pre><code class="prettyprint">def CreatePrefs():
    Prefs.Add(id='hostname', type='text', default='127.0.0.1:9091', label='Hostname')
    Prefs.Add(id='username', type='text', default='', label='Username')
    Prefs.Add(id='password', type='text', default='', label='Password', option='hidden')</code></pre>


<p>This is called immediately after the preferences dialog is submitted. This is the most basic checking you can do but it could include a call to Transmission to verify the info provided.</p>
<pre><code class="prettyprint">def ValidatePrefs():
    u = Prefs.Get('username')
    p = Prefs.Get('password')
    h = Prefs.Get('hostname')
    if( h ):
        return MessageContainer(
            "Success",
            "Info provided is ok"
        )
    else:
        return MessageContainer(
            "Error",
            "You need to provide url, username, and password"
        )</code></pre>

<p>You'll notice the return here is a MessageContainer. That's Plex's version of an alert. It doesn't generate a new page, just pops up a little window.</p>

<h3>Custom</h3>
<p>That was the end of the predefined functions, the plugin proper starts here. As Transmission requires a username, password and a short-lived session ID (since Transmission v1.53) to perform actions, we define a function which will attempt to make a connection with just username & password. Transmission will then send back a 409 Conflict response to basically say "Urk, that's not quite right. If you want to talk to me, you'll need this:" and give us our session ID in a header.</p>
<pre><code class="prettyprint">def GetSession():
  h = Prefs.Get('hostname')
  u = Prefs.Get('username')
  p = Prefs.Get('password')
  url = "http://%s/transmission/rpc/" % h
  request = { "method" : "session-get" }
  headers = {}
  if( u and p and h):
    headers["Authorization"] = "Basic %s" % 
      (base64.encodestring("%s:%s" % (u, p))[:-1])
    try:
      body = urllib2.urlopen(
        urllib2.Request(
          url, 
          JSON.StringFromObject(request), 
          headers
        )
      ).read()
    except urllib2.HTTPError, e:
      if e.code == 401 or e.code == 403:
        return L('ErrorInvalidUsername'), {}
      return e.hdrs['X-Transmission-Session-Id']
    except:
      return L('ErrorNotRunning'), {}</code></pre>

<p>Once the HTTP module allows access to returned headers, we will be able to use something like this to set global authorisation once and forget about it:</p>
<pre><code class="prettyprint">response = HTTP.Request(
    url, 
    { "method" : "session-get" }, 
    headers={}, 
    cacheTime=None
    )
HTTP.SetPassword(h,u,p)
HTTP.SetHeader(
  'X-Transmission-Session-Id', 
  response.headers['X-Transmission-Session-Id']
  )</code></pre>

<h3>Remote Transmission Calls</h3>
<p>This uses the RPC API of Transmission to do everything we need. We pass into the function 'What we want to do' and 'Who we want it done to' basically.</p>
<pre><code class="prettyprint">def RTC(method, arguments = {}, headers = {}):
  h = Prefs.Get('hostname')
  u = Prefs.Get('username')
  p = Prefs.Get('password')
  url = "http://%s/transmission/rpc/" % h

  session_id = GetSession()

  request = {
    "method":    method,
    "arguments":  arguments
  }</code></pre>

<p>Setup authentication here because, even though we've already gotten the session ID, it's useless if we don't actually use it.</p>
<pre><code class="prettyprint">  if( u and p ):
    headers["Authorization"] = "Basic %s" %
      (base64.encodestring("%s:%s" % (u, p))[:-1])

  headers["X-Transmission-Session-Id"] = session_id</code></pre>

<p>Now that we've built our instruction, throw it at Transmission and see what comes back.</p>
<pre><code class="prettyprint">  try:
    body = urllib2.urlopen(
      urllib2.Request(
        url, 
        JSON.StringFromObject(request), 
        headers)
      ).read()
  except urllib2.HTTPError, e:
    if e.code == 401 or e.code == 403:
      return L('ErrorInvalidUsername'), {}
    return "Error reading response from Transmission", {}
  except urllib2.URLError, e:
    return e.reason[1], {}

  result = JSON.ObjectFromString(body)</code></pre>

<p>We don't do error handling here as we want this function to be as generic as possible so we send anything we receive straight back to the calling function.</p>
<pre><code class="prettyprint">  if result["result"] == "success":
    result["result"] = None

  if result["arguments"] == None:
    result["arguments"] = {}

  return result["result"], result["arguments"]</code></pre>


<h2>Menus</h2>
<p>Right, we've got our helper methods set up, we're ready to make our first menu. This is the main one we mentioned earlier.</p>
<pre><code class="prettyprint">def MainMenu():</code></pre>
  
<p>You can set your menu screen to be laid out as “List”, “InfoList”, “MediaPreview”, “Showcase”, “CoverFlow”, “PanelStream” or “WallStream”. I'm keeping it simple here. Also, there's an extra call to <code class="prettyprint">GetSession</code> just to check everything's fine and wake the app up.</p>
<pre><code class="prettyprint">    dir = MediaContainer(viewGroup="List")
    GetSession()</code></pre>

<p>Pretty much all the menu items throughout the rest of this plugin are added using the same code which boils down to:</p>
<pre><code class="prettyprint">  dir.Append(
    Function(
      DirectoryItem(
        FunctionName,
        "Pretty Menu Item Name",
        subtitle="Short subtitle",
        summary="Longer menu item summary and description",
        thumb=R(ICON),
        art=R(ART)
      )
    )
  )</code></pre>

<p>Starting in the middle, this reads as:</p>
<ul>
<li>Create a <code class="prettyprint">DirectoryItem</code>.</li>
<li>When this item is selected, use the function <code class="prettyprint">FunctionName</code> to handle it.</li>
<li>Display the text <code class="prettyprint">"Pretty Menu Item Name"</code> for this item</li>
<li>Display the text <code class="prettyprint">"Short subtitle"</code> underneath this item (or None)</li>
<li>Display the text <code class="prettyprint">"Longer menu item summary and description"</code> for this item if required (or None)</li>
<li>Use the resource called ICON (mentioned above) as the icon for this item</li>
<li>Use the resource ART as the background </li>
<li>This is a <code class="prettyprint">Function</code> menu item</li>
<li>Finally, <code class="prettyprint">Append</code> this to the current menu</li>
</ul>

<p>The first two main menu items are built exactly like that:</p>
<pre><code class="prettyprint">  dir.Append(
    Function(
      DirectoryItem(
        TorrentList,
        "Torrents",
        subtitle=None,
        summary="View torrent progress and control your downloads.",
        thumb=R(ICON),
        art=R(ART)
      )
    )
  )
  dir.Append(
    Function(
      DirectoryItem(
        SearchTorrents,
          "Search for a torrent",
          subtitle=None,
          summary="Browse the TV shows directory or search for files to download.",
          thumb=R(SEARCH),
          art=R(ART)
        )
      )
    )</code></pre>

<p>This is a special 'Preferences' item that will call the Prefs functions defined at the top.</p>
<pre><code class="prettyprint">  dir.Append(
    PrefsItem(
      title="Preferences",
      subtitle="Set Transmission access details",
      summary="Make sure Transmission is running and 'Remote access' is enabled then enter the access details here.",
      thumb=R(SETTINGS)
    )
  )</code></pre>
  

<p>A quick note: the function 'R' here, much like the localisation one 'L' above is a built-in helper function. It handles resources such as images. If you're developing a plugin and can't understand why your icon images are caching so much, it might be because you're going through this function.</p>

  

<p>Send the directory (or Menu) back to Plex</p>
<pre><code class="prettyprint">    return dir</code></pre>

<p>The rest of the code deals with torrent control and some clever built-in site scraping functionality which I'll cover later.</p>      </div>
]]></description>
<pubDate>Thu, 16 Sep 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Maze 1k</title>
<link>http://thingsinjars.com/post/296/maze-1k/</link>
<guid>http://thingsinjars.com/post/296/maze-1k/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-296">
        <p><a href="http://thingsinjars.com/post/296/maze-1k/">Maze 1k</a></p>
<ul><li><a href="http://thingsinjars.com/widgets/js1k3.html">Random perfect maze generation, solution and rendering in 1011 bytes</a></li></ul>

<p>Okay, this is the last one for a while. Really.</p>

<p>Unlike my previous 1k JavaScript demos, I really had to struggle to get this one into the 1024 byte limit. I'd already done all the magnification and optimization techniques I knew of so I had to bring in some things which were new to me from <a href="http://qfox.nl/notes/111">qfox.nl</a> and <a href="http://benalman.com/news/2010/08/organ1k-js1k-contest-entry/">Ben Alman</a> and a few other places. This, combined with some major code refactoring, brought it down from 1.5k to just under 1. In the process, all possible readability was lost so here's a quick run through what it does and why.</p>

<h2>First up, a bunch of declarations.</h2>

<p>These are the colours used to draw the maze. Note, I used the shortest possible way to write each colour (<code class="prettyprint">red</code> instead of <code class="prettyprint">#F00</code>, <code class="prettyprint">99</code> instead of <code class="prettyprint">100</code>). The value stored in the maze array (mentioned later) refers not only to the type of block it is but also to the index of the colour in this array, saving some space.</p>
<pre><code class="prettyprint">u = ["#eff", "red", "#122", "rgba(99,255,99,.1)", "#ff0"],</code></pre>

<p>This is used for the number of blocks wide and high the maze is, the number of pixels per block, the size of the canvas and the redraw interval. Thanks to <a href="http://github.com/cowboy/js1k-organ1k/blob/master/organ1k.js">Ben Alman</a> for pointing out in his article how to best use a constant.</p>
<pre><code class="prettyprint"> c = 21,</code></pre>

<p>Here is the reference to the canvas. Mid-minification, I did have a bunch of function shortcuts here - <code class="prettyprint">r=Math.random</code>, for instance - but I ended up refactoring them out of the code.</p>
<pre><code class="prettyprint">m = document.body.children[0];</code></pre>

<p>For most of the time when working on this, the maze was wider than it was high because I thought that made a more interesting maze. When it came down to it, though, it was really a matter of bytesaving to drop the distinct values for width and height. After that, we grab the canvas context so we can actually draw stuff.</p>
<pre><code class="prettyprint">m.width = m.height = c * c;
h = m.getContext("2d");</code></pre>

<h2>The drawing function</h2>
<p>The generation and solution algorithm is quite nice and all but without this to draw it on the screen, it's really just a mathematical curio. This takes a colour, x and y and draws a square.</p>

<pre><code class="prettyprint">l = function (i, e, f) {
  h.fillStyle = i;
  h.fillRect(e * c, f * c, c, c)
};</code></pre>

<h2>Designing a perfect maze</h2>

<p>"You've got 1 minute to design a maze it takes 2 minutes to solve."<br />- Cobb, Inception.</p>

<p>Apologies for the unnecessary Inception quote. It's really not relevant.</p>

<p>Algorithmically, this is a fairly standard <a href="http://en.wikipedia.org/wiki/Maze_solving_algorithm">perfect maze</a> generator. It starts at one point and randomly picks a direction to walk in then it stops picks another random direction and repeats. If it can't move, it goes back to the last choice it made and picks a different direction, if there are no more directions, all blocks have been covered and we're done. In a perfect maze, there is a path (and only one path) between any two randomly chosen points so we can make the maze then denote the top left as the start and the bottom right as the end. This particular algorithm takes 2 steps in every direction instead of 1 so that we effectively carve out rooms and leave walls. You can take single steps but it's actually more of a hassle.</p>

<p>For more on how this kind of maze-generation works, check out this article on <a href="http://www.emanueleferonato.com/2008/12/06/perfect-maze-generation-tile-based-version/">Tile-based maze generation</a>.</p>

<h3>Blank canvas</h3>
<p>This is a standard loop to create a blank maze full of walls with no corridors. The <code class="prettyprint">2</code> represents the 'wall' block type and the colour <code class="prettyprint">#122</code>. The only really odd thing about this is the code <code class="prettyprint">f-->0</code> which is not to be read 'as f tends to zero' but is instead 'decrement f by 1, is it greater than zero?'</p>
<pre><code class="prettyprint">g = function () {
  v = [];  //our stack of moves taken so we can retrace our steps.
  for (i = [], e = c; e-- > 0;) {
    i[e] = [];
    for (f = c; f-- > 0;) i[e][f] = 2
  }</code></pre>

<p>By this point, we have a two-dimensional JavaScript array filled with 2s</p>

<h3>Putting things in</h3>
<pre><code class="prettyprint">  f = e = 1;    // our starting point, top left.
  i[e][f] = 0; // us, the zippy yellow thing</code></pre>

<h3>Carving out the walls</h3>
<p>This is our first proper <em>abuse</em> of the standard for-loop convention. You don't need to use the three-part structure for 'initialize variable; until variable reaches a different value; change value of variable'. It's 'do something before we start; keep going until this is false; do this after every repetition' so here we push our first move onto the stack then repeat the loop while there's still a move left on the stack.</p>
<pre><code class="prettyprint">  for (v.push([e, f]); v.length;) {</code></pre>

<p>P here is the list of potential moves from our current position. For every block, we have a look to see what neighbours are available then concatenate that cardinal direction onto the strong of potential moves. This was originally done with bitwise flags (the proper way) but it ended up longer. It's also a bit of a nasty hack to set p to be 0 instead of "" but, again, it's all about the bytes.</p>
<pre><code class="prettyprint">  p = 0;</code></pre>

<h3>Can we walk this way?</h3>
<p>These are all basically the same and mean 'if we aren't at the edge of the board and we're looking at a wall, we can tunnel into it.'.</p>
<pre><code class="prettyprint"> if (e < 18 && i[e + 2][f] == 2) p += "S"
 if (e >= 2 && i[e - 2][f] == 2) p += "N";
 if (f >= 2 && i[e][f - 2] == 2) p += "W";
 if (i[e][f + 2] == 2) p += "E";

 if (p) { //    If we've found at least one move
  switch (p[~~ (Math.random() * p.length)]) { // randomly pick one</code></pre>
<p>If there was anything to note from that last chunk, it would be that the operator <code class="prettyprint">~~</code> can be used to floor the current value. It will return the integer below thye current value.</p>

<h3>Take two steps</h3>
<p>This is a nice little hack. Because we're moving two spaces, we need to set the block we're on and the next one to be 0 (empty). This takes advantage of the right-associative unary operator 'decrement before' and the right associativity of assignment operators. It subtracts 1 from e (to place us on the square immediately above) then sets that to equal 0 then subtracts 1 from the new e (to put us on the next square up again) and sets that to equal the same as the previous operation, i.e. 0.</p>
<pre><code class="prettyprint">  case "N":
      i[--e][f] = i[--e][f] = 0;
      break;</code></pre>

<h3>Do the same for s, w and e</h3>
<pre><code class="prettyprint">    case "S":
      i[++e][f] = i[++e][f] = 0;
      break;
    case "W":
      i[e][--f] = i[e][--f] = 0;
      break;
    case "E":
      i[e][++f] = i[e][++f] = 0
    }</code></pre>

<p>Whichever move we chose, stick that onto the stack.</p>
<pre><code class="prettyprint">    v.push([e, f])</code></pre>

<h3>If there were no possible moves, backtrack</h3>
<pre><code class="prettyprint">  } else {
    b = v.pop(); //take the top move off the stack
    e = b[0]; // move there
    f = b[1]
  }
 }</code></pre>

<h3>End at the end</h3>
<p>At the very end, set the bottom right block to be the goal then return the completed maze.</p>
<pre><code class="prettyprint">  i[19][19] = 1;
  return i
};</code></pre>

<h2>Solver</h2>
<p>This is the solving function. Initially, it used the same algorithm as the generation function, namely 'collect the possible moves, randomly choose one' but this took too much space. So instead it looks for spaces north, then south, then west, then east. It follows the first one it finds.</p>
<pre><code class="prettyprint">s = function () {</code></pre>

<p>Set the block type of the previous block as 'visited' (rgba(99,255,99,.1) the alpha value makes the yellow fade to green).</p>
<pre><code class="prettyprint">  n[o][y] = 3;</code></pre>

<h3>A bit of ternary background</h3>
<p>This next bit looks worse than it is. It's the ternary operator nested several times. The ternary operator is a shorthand way of writing:</p>
<pre><code class="prettyprint">if ( statement A is true ) {
  Do Action 1
} else {
  Do Action 2
}</code></pre>

<p>In shorthand, this is written as:</p>

<pre><code class="prettyprint">Statement A ? Action 1 : Action 2;</code></pre>

<p>In this, however, I've replace Action 2 with another ternary operator:</p>

<pre><code class="prettyprint">Statement A ? Action 1 : ( Statement B ? Action 2 : Action 3 );</code></pre>

<p>And again, and again. Each time, it checks a direction, if it's empty, mark it as visited and push the move onto our stack.</p>
<pre><code class="prettyprint">(n[o + 1][y] < 2) ?
  (n[++o][y] = 0, v.push([o, y])) :
    (n[o - 1][y] < 2) ?
      (n[--o][y] = 0, v.push([o, y])) :
        (n[o][y - 1] < 2) ?
          (n[o][--y] = 0, v.push([o, y])) :
            (n[o][y + 1] < 2) ?
              (n[o][++y] = 0, v.push([o, y])) :</code></pre>

<h3>If none of the neighbours are available, backtrack</h3>
<pre><code class="prettyprint">                (b = v.pop(), o = b[0], y = b[1]);</code></pre>

<h3>Show where we are</h3>
<p>Finally, set our new current block to be yellow</p>
<pre><code class="prettyprint">  n[o][y] = 4;</code></pre>

<h3>Are we there yet?</h3>
<p>If we are at the bottom right square, we've completed the maze</p>
<pre><code class="prettyprint">  if (o == 19 && y == 19) {
  n = g();    //Generate a new maze
  o = y = 1; //Move us back to the top right
  s()     //Solve again</code></pre>

<p>If we haven't completed the maze, call the solve function again to take the next step but delay it for 21 milliseconds so that it looks pretty and doesn't zip around the maze too fast.</p>
<pre><code class="prettyprint">  } else setTimeout(s, c);</code></pre>

<h3>Paint it black. And green. And yellow.</h3>
<p>This is the code to render the maze. It starts at the top and works through the whole maze array calling the painting function with each block type (a.k.a. colour) and position.</p>
<pre><code class="prettyprint">    for (d in n) for (a in n[d]) l(u[n[d][a]], a, d)
  };</code></pre>

<h2>Start</h2>
<p>This is the initial call to solve the maze. The function s doesn't take any arguments but by passing these in, they get called before s and save a byte that would have been used if they had been on a line themselves.</p>
<pre><code class="prettyprint">s(n = g(), o = y = 1)</code></pre>

<h2>Done</h2>
<p>This little demo isn't as visually appealing as the <a href="http://thingsinjars.com/post/294/art-maker-1k/">Art Maker 1k</a> or as interactive as the <a href="http://thingsinjars.com/post/292/elementally-my-dear-javascript/">Spinny Circles 1k</a> but it is quite nice mathematically. There are now some astounding pieces of work in the <a href="http://js1k.com">JS1K demo competition</a>, though. I do recommend spending a good hour playing about with them all. Don't, however, open a bunch of them in the background at the same time. Small code isn't necessarily memory-efficient and you could quite easily grind your computer to a standstill.</p>      </div>
]]></description>
<pubDate>Thu, 19 Aug 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Art Maker 1K</title>
<link>http://thingsinjars.com/post/294/art-maker-1k/</link>
<guid>http://thingsinjars.com/post/294/art-maker-1k/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-294">
        <p><a href="http://thingsinjars.com/post/294/art-maker-1k/">Art Maker 1K</a></p>
<p>Even though the rules for <a href="http://js1k.com">js1k</a> only let me make one submission, I couldn't stop myself making another. This one is inspired by those pseudo-romantic pictures that you get <a href="http://fueledbyphotos.com/">all</a> <a href="http://icanread.tumblr.com/">over</a> <a href="http://everythingsright.com/">tumblr</a> that get reblogged endlessly (actually, it was inspired by the blog <a href="http://thatisntart.com/">That Isn't Art</a> by someone with the same opinion as myself).</p>

<p>It randomly creates a sentence, adds some softly-moving almost bokeh coloured-circles and look, I made an art! Wait for the sentence to change or click (or touch) to change it yourself.</p>

<p><a href="http://thingsinjars.com/widgets/js1k2.html">Art Maker 1k</a></p>

<p>And of course, don't forget the original <a href="http://thingsinjars.com/widgets/js1k.html">spinny-circles 1k</a></p>      </div>
]]></description>
<pubDate>Thu, 12 Aug 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>The quest for Extreme JavaScript Minification</title>
<link>http://thingsinjars.com/post/293/the-quest-for-extreme-javascript-minification/</link>
<guid>http://thingsinjars.com/post/293/the-quest-for-extreme-javascript-minification/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-293">
        <p><a href="http://thingsinjars.com/post/293/the-quest-for-extreme-javascript-minification/">The quest for Extreme JavaScript Minification</a></p>
<p>As <a href="http://blah.thingsinjars.com/post/292/elementally-my-dear-javascript/" title="Elementally, my dear JavaScript">described in detail previously</a>, I've recently taken part in the <a href="http://js1k.com">JS1K</a> competition where you have to squeeze something cool and clever into 1024 bytes of JavaScript. The quest to condense has become quite addictive and I found myself obsessing over every byte. This is the kind of stuff that the <a href="http://code.google.com/closure/compiler/">Closure Compiler</a> does quite well automatically but there are some cases where you just need to get in there and manually tweak.</p> 

<p>Here are some of the tricks I've picked up in my struggle for extreme minification:</p>

<h2>Basic improvements</h2>
<h3>Use short variable names.</h3> 
<p>This one's fairly obvious. A more useful addition to this is:</p>
<h3>Shorten long variable names.</h3>
<p>If you're going to be accessing an element more than once, especially if it's a built-in element like 'document', you'll save a few bytes every time you reference it if you create a shortened reference to it.</p>
<pre><code class="prettyprint">  document.body.style.overflow="hidden"
  document.body.style.background="red"
  (74 characters)
</code></pre>
<p>can shorten to</p>
<pre><code class="prettyprint">  d=document;b=d.body;s=b.style;
  s.overflow="hidden";
  s.background="red"
  (69 characters)
</code></pre>
<p>and any references to <code class="prettyprint">s</code> after are going to save 19 characters every time.</p>
<h3>Remove whitespace</h3>
<p>This one's so obvious, I don't need to mention it.</p>
<h3>Set Interval</h3>
<p>The extremely handy <code class="prettyprint">setInterval</code> function can take either a function or a string. If you give it an anonymous function declaration:</p>
<pre><code class="prettyprint">  setInterval(function(){x++;y--},10);
</code></pre>
<p>You will use up more characters than if you give it just the inside of the function as a string:</p>
<pre><code class="prettyprint">  setInterval('x++;y--',10);
</code></pre>
<p>But the outcome will be the same.</p>

<h2>Little-used aspects</h2>
<p>Not many people use JavScript's scientific notation unless they're doing scientific stuff but it can be a great byte saver. The number <code class="prettyprint">100</code> is equivalent to <code class="prettyprint">1 * 10^2</code> which is represented in JavaScript as 1E2. That's not a great saving for 100 but 1000 is 1E3, 10000 is 1E4. Every time you go up a factor of 10, you save 1 byte.</p>


<h2>Fight your good style tendencies</h2>
<p>In the war against space, you have to bite the bullet and accept that you may need to sacrifice some of your hard-earned practices. But only this once. Don't get in to the habit, okay?</p>
<h3>No zeroes</h3>
<pre><code class="prettyprint">  0.5  = .5
</code></pre>
<p>Yeah, it looks ugly but it works and saves a byte.</p>
<h3>Naked clauses</h3>
<pre><code class="prettyprint">  if {
    :
    :
  } else y
</code></pre>
<p>The <code class="prettyprint">y</code> looks so naked out there. No braces to keep it warm. But if you only have one statement in your else clause, you don't need them...</p>
<h3>No semi-final. . . final-semi. . . Semi-colon. No final colon.</h3>
<p>You don't need a semi-colon on your last line, even if it does make it look as though you've stunted its growth.</p>

<h2>The final few bytes</h2>
<h3>Operator precedence</h3>
<p>You don't need brackets. Brackets are handy for you as the programmer to remember what's going on when and to reduce ambiguity but if you plan correctly, most of the time you won't need brackets to get your arithmetic to work out.</p>
<pre><code class="prettyprint">  b.getMilliseconds()/(a*250) 
      is the same as
  b.getMilliseconds()/a/250 
</code></pre>
<h3>Shorthand notation</h3>
<pre><code class="prettyprint">  l=l+1;l=l%14;
  l++;l%=14;
  l=++l%14;
</code></pre>
<p>The three lines above are equivalent and in order of bytes saved.</p>
<h3>Shorthand CSS</h3>
<p>If you need to set some CSS values in your script, remember to pick the most appropriate short form. Instead of <code class="prettyprint">s.background='black'</code>, use  <code class="prettyprint">s.background='#000'</code> but instead of <code class="prettyprint">s.background='#F00'</code>, use <code class="prettyprint">s.background='red'</code>. In the same vein, the statements <code class="prettyprint">margin="0px"</code> and <code class="prettyprint">margin=0</code> mean the same but the latter saves bytes.</p>

<h2>Don't be generic</h2>
<p>One final thing to mention is that these little challenges are not the norm. If you find yourself trying to squeeze code down like this you're probably working on a very specific project. Use that to your advantage and see if there are any savings to be made by discarding your usual policies on code reuse. In the JS1K challenge, we're provided with a specific <a href="http://js1k.com/demo">HTML page</a> and an empty script tag. One good saving made here (and mentioned in my previous post) was the way I grabbed the reference to the canvas element. The standard method is to use the id assigned to the canvas.</p>
<pre><code class="prettyprint">  d.getElementById('c')
</code></pre>
<p>Which is a good generic solution. No matter what else was on the page, no matter what order stuff was in, this would return the canvas. However, we have a very specific case here and the canvas is always going to be in the same place - the first child of the body element. That means we can do this instead:</p>
<pre><code class="prettyprint">  b.children[0]
</code></pre>
<p>This makes use of the reference we grabbed to the body earlier. If the page were rearranged, this would stop working but as it won't, we've saved 8 bytes.</p>

<h2>In conclusion</h2>
<p>Yes, this is all quite silly but it's also fun and tricky. Attempting these kinds of challenges keep us developers mindful of what it is we actually do and that makes it an extremely productive silly hobby.</p>      </div>
]]></description>
<pubDate>Sun, 08 Aug 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Elementally, my dear JavaScript</title>
<link>http://thingsinjars.com/post/292/elementally-my-dear-javascript/</link>
<guid>http://thingsinjars.com/post/292/elementally-my-dear-javascript/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-292">
        <p><a href="http://thingsinjars.com/post/292/elementally-my-dear-javascript/">Elementally, my dear JavaScript</a></p>
<p><a href="http://www.angryrobotzombie.com">The Angry Robot Zombie Factory</a> launched its second iPhone/iPad app this week. I haven't mentioned it much yet because I spotted a minor typo in the final version after it had been approved so I submitted an update immediately. To get an early copy (like those misprinted stamps where the plane is upside down), go check out <a href="http://itunes.apple.com/app/the-elementals/id383675775?mt=8">The Elementals</a>. It's free, too. It's a simple, cartoonish periodic table.</p>
<p>Yesterday, the <a href="http://js1k.com">1k JavaScript demo contest</a> (<a href="http://twitter.com/#search?q=js1k">#js1k</a>) caught my eye. The idea is to create something cool using 1024bytes of JavaScript or less. I rootled around in the middle of The Elementals, grabbed the drawing function and 20 minutes later had made <a href="http://js1k.qfox.nl/demo/21">my entry</a>.</p>
<p>The code I submitted is quite minified but isn't obfuscated. When it's unfolded, you can follow the flow fairly easily.</p>

<pre><code class="prettyprint">var d = document,
b = d.body,
s = b.style,
w = innerWidth,
h = innerHeight,
v = b.children[0],
p = 2 * Math.PI,
Z = 3,
x = tx = w / 2,
y = ty = h / 2;
</code></pre>

<p>The above is a bunch of declarations. Using things like <code class="prettyprint">d = document</code> and <code class="prettyprint">b = d.body</code> allows reuse later on without having to resort to the full <code class="prettyprint">document.body.style</code> and saves a bunch of characters. When you've got such a small amount of space to play with, every character counts (mind you, the <a href="http://en.wikipedia.org/wiki/ZX81">ZX81</a> only had 1k of RAM and look what you could do with that). Now that I'm looking at it, I think I could have tidied this a bit more. Darn. The sneaky bit about this code is the way we grab the reference to the canvas. The code <code class="prettyprint">d.getElementById('c')</code> uses 21 characters but if we look at the provided HTML, we can use the fact that the canvas is the first child of the body element. The code <code class="prettyprint">b.children[0]</code> uses 13 characters instead.</p>

<pre><code class="prettyprint">s.margin = "0px";
s.background = "black";
s.overflow = "hidden";
v.width = w;
v.height = h;
t = v.getContext("2d");
</code></pre>

<p>This sets the provided canvas to be the full width and height of the window then grabs the drawing context of it so we can make pretty pictures.</p>

<pre><code class="prettyprint">zi = function () {
 Z++;
 Z %= 14
};
m = function (X) {
 return (X * 200) % 255
};
</code></pre>

<p>Functions to be reused later. <code class="prettyprint">zi</code> increases the number of spinning circles and is used by onmousedown and ontouchstart (oh yes, it works on the iPad, too). <code class="prettyprint">m</code> is a mapping of the index of the circle to a colour. The 200 is arbitrary. I played about a bit until I found some colour combinations I liked.</p>

<pre><code class="prettyprint"> d.ontouchstart = function (e) {
 zi();
 tx = e.touches[0].pageX;
 ty = e.touches[0].pageY
};
d.onmousemove = function (e) {
 tx = e.clientX;
 ty = e.clientY
};
d.onmousedown = zi;
</code></pre>

<p>Setting the event handlers.</p>

<pre><code class="prettyprint">function r() {
 t.globalCompositeOperation = 'lighter';
</code></pre>

<p>I played about with the <a href="https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html">various composite operations</a>. Lighter seemed the nicest.</p>

<pre><code class="prettyprint"> t.clearRect(0, 0, w, h);
 t.save();
 x = x + (tx - x) / 20;
 y = y + (ty - y) / 20;
 t.translate(x, y);
</code></pre>

<p>Originally, the circles followed the mouse pointer exactly but it lacked any life. By adding in this bit where the movement is delayed as if pulling against friction, it suddenly became a lot more fun and dynamic.</p>

<pre><code class="prettyprint"> var c = new Date();
 for (var i = 1; i       </div>
]]></description>
<pubDate>Wed, 04 Aug 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>PhoneGap - The Drupal of App development</title>
<link>http://thingsinjars.com/post/291/phonegap---the-drupal-of-app-development/</link>
<guid>http://thingsinjars.com/post/291/phonegap---the-drupal-of-app-development/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-291">
        <p><a href="http://thingsinjars.com/post/291/phonegap---the-drupal-of-app-development/">PhoneGap - The Drupal of App development</a></p>
<p>I'm a fan of <a href="http://drupal.org/">Drupal</a> even though I don't use it that often. I like that I can see exactly what's going on. I can easily follow the execution from URL request to page serve.</p>
<p>What I usually end up doing on any Drupal project is:</p>
<ol>
	<li>build the majority of the site in a few hours</li>
	<li>find one small piece of functionality missing that's absolutely essential</li>
	<li>dig into the core to make it happen</li>
	<li>find a simpler way of doing it and step out of the core a bit</li>
	<li>find an even simpler way and step back a bit more</li>
	<li>figure out how to do it in a single module file and put the core back the way it was.</li>
</ol>
<p>That probably seems utterly inefficient but it has served me well since Drupal 4 and it means I've got a really good picture in my head of the internal workflow.</p>
<p>This is in stark comparison to other systems, particularly some .NET CMSs where a request comes in, <em>something</em> happens and the page is served. There are even some PHP frameworks and CMSs where everything is so abstracted, the only way you can get an accurate picture of what is happening is to already <em>have</em> an accurate picture of what is happening.</p>
<p>I've used several different ones and I keep coming back to Drupal (also, recently, <a href="http://grabaperch.com/">Perch</a>, but that's besides the point here).</p>
<p><em>“What on earth does this have to do with PhoneGap?”</em> I hear you ask. Quite rightly, too.</p>
<p>When I was planning <a href="http://harmoniousapp.com/">Harmonious</a>, I looked at various frameworks for turning a combination of HTML, CSS & JavaScript into an app - <a href="http://www.phonegap.com/">PhoneGap</a>, <a href="http://www.appcelerator.com/">Appcelerator Titanium</a>, <a href="http://rhomobile.com/">Rhomobile</a>. Rhomobile (or the Rhodes Framework) is built on Ruby so I didn't investigate too far. That's not to say it's not a good framework, I couldn't say either way. The idea behind using one of these frameworks is to save you the time of having to learn Objective-C and seeing as I've only done very minimal amounts of Ruby, I'd be replacing 'learn Objective-C' with 'learn Ruby'. That said, I've always thought Ruby developers opinion of themselves was <a href="http://god.rubyforge.org/">slightly too high</a>.</p>
<p>The first framework I properly spent some time with was Appcelerator. It seemed quite shiny and I liked having single interface access to compilation for iPhone and Android but I wasn't so keen on having to sign up for an account with them for no obvious reason. Some further investigation suggested that this was so you could send your project to their servers for proprietary cross-platform compilation of your desktop app. This is less useful, however, if you're developing just for iPhone and Android as for both, you need the SDK installed locally and the compilation is done on your own machine.</p>
<p>The main thing that I wasn't comfortable with in Appcelerator was that there seemed to be a lot happening behind the scenes. This is not necessarily a bad thing, of course, but it started that little buzz in the back of my head that I get when working on .NET. When I press 'compile', I want to know exactly <em>what</em> it's doing. I want to know exactly how it takes my JavaScript and embeds it, when does it include its own API files and what do I change to make it do stuff it doesn't do by default?</p>
<p>After that, I moved to PhoneGap (version 0.8.3) and found myself immediately falling into my Drupal workflow. The app fell into place in less than an hour (with a liberal sprinkling of <a href="http://www.jqtouch.com/">jQTouch</a> and the <a href="http://www.glyphish.com/">Glyphish</a> icons). I then needed to take a screenshot and couldn't see an obvious way to do it but, due to the nature of PhoneGap being completely <a href="http://github.com/sintaxi/phonegap">open-source</a>, it was easy to spot where to jump into the code. I hacked in a screenshot function in another hour, spent another half hour making it better and another making it simpler. Just to complete the cycle, I have now wrapped up all my code into a plugin and removed my hacking from the core. Hmmm... that all seemed eerily familiar.</p>
<p>That's not to say PhoneGap is perfect. All the benefits of a completely open-source project referred to previously also come with all the drawbacks. The current version (0.9.0) is fiendishly difficult to download and get started with. It has been split into one parent project and several child projects (one per mobile platform) and it's no longer obvious what you do. It's easy enough if you're already set up but actually getting there is tricky. The most common failing of any open-source project is also true: poor documentation. There's a wiki but it's mostly out-of-date. There's a section on phonegap.com called 'docs' but they're also out-of-date. There's an API reference but it's autogenerated from comments and is also out-of-date. The only place to get accurate information is the Google group but that's not documentation, that's solutions to problems.</p>
<p>There have also been some claims that PhoneGap is unstable and crashes but personally, I haven't seen that. It's possible that the crashes and performance issues are the result of memory leaks in the JavaScript. Appcelerator automatically runs <a href="http://www.jslint.com/">JSLint</a> on your code before compilation so it will highlight any problems. If you can fit that into your standard workflow, you might be able to avoid some of the instability.</p>

<h2>Additional comments</h2>

<p>It seems that <a href="http://disqus.com">Disqus</a> (the commenting system I'm using below) has some problems with Safari 5 & Chrome so this comment was sent via <a href="http://gist.github.com/">gist</a> (I knew I shouldn't have stopped using <a href="http://blah.thingsinjars.com/post/180/noodle/" title="Noodle">Noodle</a>).</p>
<p>I'll respond later. I've just got back from the Apple store and have toys to play with.</p>


<p><em>Comment from Jeff Haynie (<a href="http://twitter.com/jhaynie">@jhaynie</a>)</em></p>
<p>A few comments about Appcelerator.</p>
<p>1. We're completely open source and you can see all our active development every single commit on github.com/appcelerator.  We have plenty of outside core open source contributors.</p>
<p>2. Yeah, to do what we're doing, it's complicated - much more than Phonegap - so it does mean with complexity it's hard to grok.  however, the source is all there. Also, it's full extensible through our SDKs and we this SDK as the way we build Titanium itself.</p>
<p>3. For Desktop, we _only_ upload to our build servers as a convenience to cross-platform packaging.  Nothing mysterious and all the scripts we run are included (and open source) so you can run them on your own. Plenty of our customers do this behind the firewall.  When you're developing locally (say on a OSX machine), it's all local during dev. Only cross-platform packaging is done as a convenience to developers.  We have to pay for this bandwidth and storage and we do it to make it easier.  And it's free.</p>
<p>Hope this clarifies some of the above.   Phonegap's a great project and we love the team - but I think we're trying to do different things and come at it from different approaches. In the end, this is good for developers as it gives everyone more choice based on their needs.</p>      </div>
]]></description>
<pubDate>Thu, 17 Jun 2010 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Crowdsourced Weather - Part 2</title>
<link>http://thingsinjars.com/post/255/crowdsourced-weather---part-2/</link>
<guid>http://thingsinjars.com/post/255/crowdsourced-weather---part-2/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-255">
        <p><a href="http://thingsinjars.com/post/255/crowdsourced-weather---part-2/">Crowdsourced Weather - Part 2</a></p>
<p>So, I couldn't help myself. I had a niggling idea at the back of my head that I needed to get out. After coming up with this <a href="http://blah.thingsinjars.com/post/254/crowdsourced-weather/">Twitter weather</a> idea last week, I decided to spend a couple of hours this weekend building it. As if I didn't have other things I should have been doing instead...</p>

<p>It works pretty much exactly how the pseudocode I mentioned last time describes. Every few minutes, a script will search Twitter for mentions of any weather words from several different languages. It will then look up the location of the person who tweeted that and store it. Single reports might be wrong and users might not have stored their actual location but over a large enough sample, this system becomes more accurate. The script removes any matching twets older than 6 hours.</p>

<p>To display, I actually ended up using <a href="http://en.wikipedia.org/wiki/Geohash">Geohashes</a> instead of <a href="http://www.geotude.com/">Geotudes</a> because it is easier to simplify them when you zoom out just by cutting off the tail of the hash. For example, the physical area denoted by gcvwr3qvmh8vn (the geohash for Edinburgh) is contained within gcvwr3 which is itself contained within gcv. There are a few <a href="http://en.wikipedia.org/wiki/Geohash#Limitations">technical problems with geohashes</a> but it seems the best fit for this purpose. If anyone knows of any better suggestion, please let  me know. I do realise that this is quite possibly the slowest, most inefficient JavaScript I've ever written because it makes an AJAX call for every <a href="http://wiki.xkcd.com/geohashing/Graticule">graticule</a> and it probably should just send the South-East and North-West bounds and get back an array of them but, like I said, there were other things I should have been doing. Because the overlaid grid changes resolution based on zoom level, there are a few places where it is either tragically slow (resolution too fine) or terribly inaccurate (resolution too rough). That's just a case of tweaking the algorithm. Similarly, it's set to display reports of weather if there are 2 or more matches but it could be tweaked to only show if a larger number have reported something.</p>

<p>So go, play with the <a href="http://blah.thingsinjars.com/widgets/weather/index.html">Twitter-generated weather map</a>. If someone can come up with a good, catchy name, or some better graphics, that'd be great, thanks.</p>


<p>Source code is available: <a href="http://thingsinjars.com/uploaded/other/twitter-weather-1.0.zip">twitter-weather-1.0.zip [Zip - 298KB]</a>.</p>
<p>You'll need your own Twitter login and database account to use it.</p>
      </div>
]]></description>
<pubDate>Mon, 21 Dec 2009 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Crowdsourced Weather</title>
<link>http://thingsinjars.com/post/254/crowdsourced-weather/</link>
<guid>http://thingsinjars.com/post/254/crowdsourced-weather/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-254">
        <p><a href="http://thingsinjars.com/post/254/crowdsourced-weather/">Crowdsourced Weather</a></p>
<p>This is a more general version of the <a href="http://uksnow.benmarsh.co.uk/">#uksnow map</a> idea. It's a crowd-sourced weather map which relies on the fact that any one individual tweet about the weather might be inaccurate but given a large enough sample, enough people will mention the weather in their area to make this a workable idea. It doesn't require people to tweet in a particular format.</p>

<h2>To get info</h2>

<pre>
Have an array of weather words in various languages (rain, hail, snow, schnee, ame, yuki)
every 5 minutes:
	foreach weatherword
		search twitter for that word
			http://search.twitter.com/search.atom?q=rain
		retrieve latest 100 tweets
		foreach
			get user info
				http://twitter.com/users/show.xml?screen_name=username
			get user.location if available
			geocode
			save:
				username, time, lat, long, <a href="http://www.geotude.com/">geotude</a>, weatherword
		Remove any tweets about this weatherword older than 6 hours.
			
</pre>

<h2>To display info</h2>
<pre>
Show a Google map
Based on current Zoom level, split the current map into about 100 geotudes
foreach geotude
	search database for any weather results for that block (probably using an ilike "1234%" on the geotude field)
	sort by weatherword count descending
	draw an icon on top of that block to show the most common weatherword
	
If the user zooms in, recalculate geotudes and repeat.
</pre>

<p>I quite like that this uses <a href="http://www.geotude.com/">geotudes</a> which I think are an excellent idea.</p>

<p>I built a <a href="http://blah.thingsinjars.com/widgets/weather/">very basic version of this</a>. Read more about it in <a href="http://blah.thingsinjars.com/post/255/crowdsourced-weather---part-2/">Part 2</a>.</p>
      </div>
]]></description>
<pubDate>Thu, 17 Dec 2009 00:00:00 GMT</pubDate>
<category>development</category>
</item><item>
<title>Building an Objective-C growlView</title>
<link>http://thingsinjars.com/post/250/building-an-objective-c-growlview/</link>
<guid>http://thingsinjars.com/post/250/building-an-objective-c-growlview/</guid>
<description><![CDATA[
        <div class="teaser html" id="teaser-250">
        <p><a href="http://thingsinjars.com/post/250/building-an-objective-c-growlview/">Building an Objective-C growlView</a></p>
<p><em>Wherein our intrepid hero learns some Objective-C and figures out the easy bits are actually quite hard.</em></p>

  <p>This is a little guide on how to write a growl plugin to automatically send notifications as tweets. If you just want the finished thing: <a href="http://cloud.github.com/downloads/thingsinjars/GrowlBird/GrowlBird_0.2.8.zip">GrowlBird.zip [Zip - 228KB]</a></p>
<p>A couple of days ago, I decided to give myself a little software development task to write a <a href="http://twitter.com">Twitter</a> <a href="http://growl.info">Growl</a> view. Growl is a centralised notification system for Mac OS X that lots of other applications can use so that there's one consistent way of showing notifications. </p>
<h2>Background</h2>
<p>The idea behind this little experiment wasn't to have tweets appear as growl notifications, there are already plenty of apps that do this, the idea was to have growl notifications sent to Twitter. Some friends have started organising a crowdsourced <a href="http://rotacoo.com/fridaymix/">Friday afternoon playlist</a> via <a href="http://spotify.com">Spotify</a> and I thought it'd be handy if Spotify tweeted each song as it started. The easiest way I could think of doing this was to tap into the fact that Spotify sends a Growl notification on track start and get the Growl display plugin to tweet it as well [<a href="http://thingsinjars.com/post/250/building-an-objective-c-growlview/#note-already">1</a>]. </p>
<h2>Build</h2>
<p>I downloaded the <a href="http://growl.info/files/DisplaySample.zip">Growl Display Plugin Sample 1.2 [Zip - 186 KB]</a> from the <a href="http://growl.info/downloads_developers.php">developer downloads</a> page and the <a href="http://mattgemmell.com/2008/02/22/mgtwitterengine-twitter-from-cocoa">MGTwitterEngine</a> library. I then downloaded <a href="http://developer.apple.com/technology/xcode.html">Xcode</a> so I could do the development. I have to point out here that this was my first foray into Objective-C programming and, indeed, my first attempt at anything vaguely C-related since I wrote a command-line calculator about 12 years ago. If I do it wrong, please forgive me.</p>
<p>The first thing to do was open the sample project in Xcode, figure out what files do what, etc. There is very little documentation on how Growl views or display styles work so I pretty much just spend an hour reading all the source from top to bottom. Here's a quick summary:</p>

  Sample_Prefix.pchPre-compiled header. Stuff that's included before every pre-compiled fileGrowl/Folder containing standard Growl stuff. Don't need to touch.GrowlSampleDisplay.hHeader file, didn't need to change anythingGrowlSampleDisplay.mClass for setting up things. Again, didn't touch [<a href="http://thingsinjars.com/post/250/building-an-objective-c-growlview/#note-bugged">2</a>].GrowlSamplePrefs.hDefining default preference values and naming functions to handle them. More on this later.GrowlSamplePrefs.mThe actual functions mentioned in the previous header fileGrowlSampleWindowController.hNot doing anything visual, really so I didn't need to mess around with thisGrowlSampleWindowController.mAs aboveGrowlSampleWindowView.hDeclaring objects needed for executionGrowlSampleWindowView.mInstantiating the objects then actually using them later on.
<p>Again, I'm not used to doing this stuff so if I'm using the wrong terminology, just pretend I'm not.</p>
<p>I then dragged the MGTwitterEngine library into the project drawer, saved and built. At this point it successfully did nothing different which is what I was hoping it would do. Well, it popped up the 'This is a Preview of the Sample Display' message using the MusicVideo style which is what it does when you don't screw with it.</p>

  <h2>Testing growlView</h2>
  <p>It's not actually that easy to test growlView plugins. You can't simply add and remove them. To install, you double-click on it. You should be able to see it listed in the Display tab of the preference pane. To <em>re-install</em>, you need to delete ~/Library/Preferences/com.Growl.GrowlHelperApp, ~/Library/Application Support/Growl/Plugins/Sample.growlView and restart growl (click on the paw in the menu bar). It's a bit of a hassle.</p>

<p>The next thing was to include the MGTwitterEngine. In GrowlSampleWindowController.h, #import "MGTwitterEngine.h" and create a new object. I just followed the instructions in the <a href="http://svn.cocoasourcecode.com/MGTwitterEngine/README.txt">README</a> but be sure to follow <em>all</em> of them. If you get errors about LibXML not being installed or YAJL not working, don't worry, you just need to make sure you set USE_LIBXML to 0 in all the places you're supposed to. GrowlSampleWindowController.h now contains this:</p>
<pre><code class="prettyprint">
#import "GrowlDisplayWindowController.h"
#import "MGTwitterEngine.h"

@class GrowlBirdWindowView;

@interface GrowlBirdWindowController : GrowlDisplayWindowController {
	CGFloat						frameHeight;
	NSInteger					priority;
	NSPoint						frameOrigin;
	MGTwitterEngine *twitterEngine;
}
@end</code></pre>
<p>In GrowlSampleWindowController.m, I then instantiated the new object:</p>
<pre><code class="prettyprint">
  @implementation GrowlBirdWindowController
  - (id) init {
  	  :
  	  :
      twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];
	    [twitterEngine setUsername:@"growlbirdtest" password:@"testgrowlbird"];
	  }
	  :</code></pre>
<p>And then modified the setNotification function to also send an update:</p>
<pre><code class="prettyprint">
- (void) setNotification: (GrowlApplicationNotification *) theNotification {
    :
	[view setTitle:title];
	[view setText:text];
  NSLog(@"sendUpdate: connectionIdentifier = %@", [twitterEngine sendUpdate:[NSString stringWithFormat:@"%@, %@", title, text]]); // The new line
  :
  }</code></pre>
<p>That was enough to get growl to send messages to appear on http://twitter.com/growlbirdtest but it doesn't make it that useful for anybody else, to be honest. The next thing to figure out was the preferences. </p>
<h2>Preferences</h2>
<p>Without documentation, this took a bit longer that I expected. To start off changing the english version before worrying about localization, find the GrowlBirdPrefs.xib in resources/en.lproj/ and open it. Interface Builder will launch then you can double-click on 'Window' and see the layout of the preference pane. Search in the Library for 'text' and drag a text field into the window then spend about half and hour clicking round the interface. Open up the various inspectors (right-click on an object), look through the different tabs, click between the newly added text field and the sliders and drop-downs that are already there just to see what's different. Once I was a bit familiar, I opened the connections tab so that I could bind the value of the text field to the value 'twitterUsername' in my code. I checked 'value', Bind to 'File's Owner' and entered 'twitterUsername' in Model Key Path. I then repeated this for twitterPassword using a Secure Text Field from the Library. The option nextKeyView is used to say which item is tabbed to next when you're navigating with the keyboard so to keep things tidy, I dragged lines from nextKeyView from each of them to the right places in the layout.</p>
<p>Back in the code, I added new default preferences in GrowlSamplePrefs.h:</p>
<pre><code class="prettyprint">
  #define Sample_USERNAME_PREF		@"Username"
  #define Sample_DEFAULT_USERNAME		@"growlbirdtest"

  #define Sample_PASSWORD_PREF		@"Password"
  #define Sample_DEFAULT_PASSWORD		@"testgrowlbird"
  :
  :
  @interface GrowlBirdPrefs : NSPreferencePane {
  	IBOutlet NSSlider *slider_opacity;
  	IBOutlet NSString *twitterUsername;
  	IBOutlet NSString *twitterPassword;
  }</code></pre>
<p>and named some handlers for them:</p>
<pre><code class="prettyprint">
  - (NSString *) twitterUsername;
  - (void) setTwitterUsername:(NSString *)value;
  - (NSString *) twitterPassword;
  - (void) setTwitterPassword:(NSString *)value;</code></pre>
<p>Be careful here, I got confused and didn't have the same spelling here for twitterUsername and twitterPassword as I had put in the interface builder as I hadn't realised the two were directly connected. They are. Obviously. The next thing to do is to write the code for these handlers:</p>
<pre><code class="prettyprint">
  - (NSString *) twitterUsername {
  	NSString *value = nil;
  	READ_GROWL_PREF_VALUE(Sample_USERNAME_PREF, SamplePrefDomain, NSString *, &value);
  	return value;
  }
  - (void) setTwitterUsername:(NSString *)value {
  	WRITE_GROWL_PREF_VALUE(Sample_USERNAME_PREF, value, SamplePrefDomain);
  	UPDATE_GROWL_PREFS();
  }
  - (NSString *) twitterPassword {
  	NSString *value = nil;
  	READ_GROWL_PREF_VALUE(Sample_PASSWORD_PREF, SamplePrefDomain, NSString *, &value);
  	return value;
  }
  - (void) setTwitterPassword:(NSString *)value {
  	WRITE_GROWL_PREF_VALUE(Sample_PASSWORD_PREF, value, SamplePrefDomain);
  	UPDATE_GROWL_PREFS();
  }
</code></pre>

<p>Build and reinstall and this will now show the same preference pane as before but with two new text fields which allow you to enter your username and password. In fact, build at several stages along the way. Every time you make a change, in fact. If something breaks, check the error log to see if it's something predictable that should have broken at that point or if you've done something wrong. Also, keep the OS X log app Console open in the background. It will spew out error messages if you do something wrong. It's also good to have your code write out console messages to keep a track on what your code is doing like so:</p>
<pre><code class="prettyprint">
  - (NSString *) twitterPassword {
  	NSString *value = nil;
  	READ_GROWL_PREF_VALUE(Bird_PASSWORD_PREF, SamplePrefDomain, NSString *, &value);
  	NSLog(@"twitterPassword = %@", value);
  	return value;
  }
</code></pre>

<p>You'll notice we're still sending messages to the growlbirdtest account because, even though we are reading and saving the username and password, we're not doing anything with them. That's easily remedied by editing GrowlSampleWindowView.m again and replacing the hard-coded login details with a couple of lines to read from the preferences or fall back on the default:</p>
<pre><code class="prettyprint">
  twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];
	NSString *twitter_username = Bird_DEFAULT_USERNAME;
	NSString *twitter_password = Bird_DEFAULT_PASSWORD;
	READ_GROWL_PREF_VALUE(Bird_USERNAME_PREF, SamplePrefDomain, NSString *, &twitter_username);
	READ_GROWL_PREF_VALUE(Bird_PASSWORD_PREF, SamplePrefDomain, NSString *, &twitter_password);
	[twitterEngine setUsername:twitter_username password:twitter_password];
	NSLog(@"Twitter Login: username = %@", twitter_username);
</code></pre>
<p>And, hooray! It works and posts to the account for which you entered details. Sort of. Some apps double-post. I haven't figured out why yet.</p>
<h2>Renaming</h2>
<p>After all that, the final bit (which I thought would be the easiest) was to rename the growlView from 'Sample' to 'Bird'. I have read that in the latest version of Xcode (which presumably comes with Snow Leopard), there's a global 'Rename' which will do all the relevant stuff for you. If you don't have that, you'll need to read <a href="http://arustisha.wordpress.com/2009/03/08/on-the-renaming-of-xcode-projects/">'On the Renaming of Xcode Projects'</a> and do everything there. If you're still finding your growlView is called Sample, manually open every Info.plist you can find, 'Get Info' on everything, scour through the settings for the different build environments (Debug and Release)... It took longer to rename the project than to actually build it.</p>


<p>A trivial aside, I have also added two fields to the preferences for tweet prefix and tweet postfix in exactly the same way the username and password were added. I leave the details to the interested reader.</p>


<p>You should now have a completed, installable growlView/Growl View/Growl Display/growlStyle/whatever it's actually called. You can export the current <a href="http://github.com/thingsinjars/GrowlBird">Git project</a> to have a look around or you can just download the finished <a href="http://cloud.github.com/downloads/thingsinjars/GrowlBird/GrowlBird_0.2.8.zip">GrowlBird.zip [Zip - 228KB]</a> if you like. Note, the Git project isn't guaranteed buildable at any moment in time, I might break it. The localisations still need done and the layout of the prefPane isn't the greatest, either.</p>


	<p>[<a id="note-already" href="http://thingsinjars.com/post/250/building-an-objective-c-growlview/#already">1</a>] Since writing this, I have discovered that someone else <a href="http://clickontyler.com/blog/2009/01/forward-your-growl-notifications-to-twitter/">already made a growlView</a> to do this, it just didn't show up on any of my Google searching.</p>
	<p>[<a id="note-bugged" href="http://thingsinjars.com/post/250/building-an-objective-c-growlview/#bugged">2</a>] It turns out that I did have to modify these in the end due to a <a href="http://github.com/thingsinjars/GrowlBird/commit/0647d13355aad60401b67261a5bab0a59ed4c602">silly bug</a>. Like I said, this is my first attempt at this kind of thing.</p>
      </div>
]]></description>
<pubDate>Sun, 01 Nov 2009 00:00:00 GMT</pubDate>
<category>development</category>
</item></channel>
</rss>