<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss version="2.0">
  <channel>
    <title>Bamboo Blog</title>
    <link>http://blog.new-bamboo.co.uk</link>
    <description>...</description>
    <language>en-us</language>
    <pubDate>Wed, 26 Oct 2011 00:00:00 +0000</pubDate>
    <lastBuildDate>Wed, 26 Oct 2011 00:00:00 +0000</lastBuildDate>
    <managingEditor>info@new-bamboo.co.uk (Damien Tanner)</managingEditor>
    <webMaster>info@new-bamboo.co.uk (Damien Tanner)</webMaster>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/newbamboo" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="newbamboo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
      <title>Experiments with the HTML5 Audio Data API</title>
      <link>http://blog.new-bamboo.co.uk/2011/10/26/experiments-with-the-html5-audio-data-api</link>
      <author>oliver.n@new-bamboo.co.uk (olivern)</author>
      <comments>http://blog.new-bamboo.co.uk/2011/10/26/experiments-with-the-html5-audio-data-api#disqus_thread</comments>
      <description>&lt;p&gt;About a month ago we had a hack day at New Bamboo, a day where all the bambinos were free to work on any kind of project they wanted to.  I decided to experiment with the HTML5 Audio Data Api, and &lt;a href="http://canvas.fm"&gt;canvas.fm&lt;/a&gt;, (&lt;a href="http://github.com/olivernn/canvas.fm"&gt;code&lt;/a&gt;) is the outcome of that experiment.&lt;/p&gt;

&lt;p&gt;Canvas.fm is a small app that allows you to listen to music available on &lt;a href="http://soundcloud.com"&gt;SoundCloud&lt;/a&gt;.  Whilst the audio is playing it draws a visualisation of the current song using HTML5 canvas.  It uses a server component, powered by Node.js, to convert SoundCloud's streaming MP3 audio into the OGG format - which Firefox supports.&lt;/p&gt;

&lt;h2&gt;Audio Data API&lt;/h2&gt;

&lt;h3&gt;Browser specifics&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://wiki.mozilla.org/Audio_Data_API"&gt;audio data API&lt;/a&gt; was originally introduced in Firefox 4 in the second half of 2010.  Using this API it is possible to read &amp;amp; write audio data from both audio and video elements.&lt;/p&gt;

&lt;p&gt;It is worth noting that more recently a webkit audio data API has also emerged.  The Mozilla implementation is, at the time of writing, significantly simpler and comes with much more comprehensive documentation and examples.&lt;/p&gt;

&lt;p&gt;Because I originally only had a day to put something together I decided to focus on the Mozilla implementation of the audio data API.  I hope in the future to be able to make canvas.fm work on both webkit and firefox.&lt;/p&gt;

&lt;h3&gt;Implementation Details&lt;/h3&gt;

&lt;p&gt;There are a number of events that the Mozilla audio API gives us which we can hook into to manipulate the audio data.  In canvas.fm we are only reading audio data so we are primarily interested in the &lt;code&gt;loadedMetaData&lt;/code&gt; event and the &lt;code&gt;MozAudioAvailable&lt;/code&gt; event.&lt;/p&gt;

&lt;h4&gt;Loaded Meta Data&lt;/h4&gt;

&lt;p&gt;The loaded meta data event is fired, as the name suggests, when the browser has loaded the meta data for this audio element.  This event is not specific to the audio data API, but it signals that we can now gain access to some meta information about the audio that we will later need to process the data.&lt;/p&gt;

&lt;p&gt;Specifically these are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the number of channels available in the audio source  &amp;mdash; 1 for mono, 2 for stereo etc.&lt;/li&gt;
&lt;li&gt;sampleRate &amp;mdash; the number of samples per second in the audio which is typically around 44.1KHz.&lt;/li&gt;
&lt;li&gt;frameBufferLength &amp;mdash; this will be discussed in the next section.&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;MozAudioAvailable&lt;/h4&gt;

&lt;p&gt;This event is where the bulk of the processing happens.  The event handler is passed the frame buffer and the time in the audio track that the first element of this frame buffer represents.&lt;/p&gt;

&lt;p&gt;The frame buffer is a typed array of floats that represent the decoded audio data.  Each element of the array represents a tiny sample of the audio that is being played, with values normalised between 1 and -1.  The values actually represent the sum of all the amplitudes of frequencies for a particular channel at a particular point in time.&lt;/p&gt;

&lt;p&gt;The length of this array can be obtained from the audio elements frameBufferLength that we grabbed in the &lt;code&gt;loadedMetaData&lt;/code&gt; event handler.  The full length will be this value multiplied by the number of channels because the channel data is actually interleaved with each other, e.g. [channel1, channel2, channeln, channel1, channel2, channeln...].&lt;/p&gt;

&lt;h4&gt;Fast Fourier Transform&lt;/h4&gt;

&lt;p&gt;Ultimately we want the amplitudes of the various frequencies that make up the audio being played, rather than the sum of all the frequencies for a channel, which is what we've currently got.&lt;/p&gt;

&lt;p&gt;This transformation is possible using &lt;a href="http://en.wikipedia.org/wiki/Fourier_analysis"&gt;Fourier Analysis&lt;/a&gt;, the detail of which is in the realm of physics and &lt;em&gt;way&lt;/em&gt; beyond the scope of this article.  Essentially we are transforming the original data, which is in the time domain, into what we need to graph, which is data represented in the frequency domain.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://www.dspguide.com/ch12.htm"&gt;Fast Fourier Transform&lt;/a&gt; algorithm, &lt;a href="https://github.com/corbanbrook/dsp.js"&gt;implemented in JavaScript&lt;/a&gt;, does all the hard work for us. What we end up with is an array of frequency amplitudes, which is precisely what we need to draw our visualisation.&lt;/p&gt;

&lt;h2&gt;Visualisation&lt;/h2&gt;

&lt;p&gt;An obvious choice for visualising our audio data would be a very familiar graphic equaliser.  There are already several of these around, and although they are a good first step I wanted to do more.  These kind of visualisations only allow you to see what is happening now, without giving an impression of the song as a whole.&lt;/p&gt;

&lt;p&gt;I decided to use a variation on the traditional graphic equaliser. I wanted to draw a disc, showing the various changes in frequency strength throughout a certain piece of music.  In the end you would end up with a circle, showing the frequency shifts and variations of the whole song, hopefully it would also produce a visually interesting image.&lt;/p&gt;

&lt;p&gt;To make this possible without having to keep state of the whole frequency spectrum for a whole song, we can take advantage of canvas transformations.  The canvas code that is doing the drawing doesn't change its position as the audio is being played. Instead we rotate the canvas to prevent the canvas overwriting existing lines, and to give us the circular image that we want.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var draw = function (samples) {
  samples.forEach(function (sample) {
    intensity = sample * 10
    ctx.fillStyle = 'rgba(0,0,0, ' + intensity + ')'
    ctx.fillRect(0, 512 - i, 1, 1)
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above snippet shows the draw function that takes care of drawing on the canvas drawing context, &lt;code&gt;ctx&lt;/code&gt;.  On each sample of the song we rotate the canvas by an amount that means the canvas is rotated a full 360&amp;deg;, or 2&amp;pi; radians, by the time the audio is complete.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var rotate = function (rad) {
  ctx.rotate(rad)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Streaming Audio&lt;/h2&gt;

&lt;p&gt;The SoundCloud API is very simple and, most importantly for canvas.fm, allows us to get access to a streaming MP3 of any track available on the SoundCloud service.  Unfortunately Firefox doesn't support the MP3 audio format due to licensing issues.&lt;/p&gt;

&lt;p&gt;Thankfully it is relatively trivial to convert MP3s to Firefox's preferred audio format, OGG.  Since canvas.fm allows users to search and choose from the entire SoundCloud music catalogue, we cannot pre-convert all of these audio streams.&lt;/p&gt;

&lt;p&gt;Instead, Canvas.fm uses Node.js to handle SoundCloud's incoming MP3 stream, and then pipes this into ffmpeg, giving us an OGG formatted audio stream which we can then pipe into an HTTP response.  Using Node.js makes this kind of stream handling incredibly simple and efficient.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var track = Track.create({id: request.params['track_id']}),
    converter = Converter.create();

track.stream(function (err, trackStream) {
  if (err) throw(err)

  trackStream.pipe(converter.process.stdin)
  converter.process.stdout.pipe(response)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Above is an excerpt from the HTTP request handler in the canvas.fm Node.js app.  &lt;code&gt;track&lt;/code&gt; is a simple wrapper around the SoundCloud API.  Calling the stream method makes a few HTTP requests to SoundCloud's API and then yields the MP3 stream to the callback.&lt;/p&gt;

&lt;p&gt;Inside the callback we use the &lt;a href="http://nodejs.org/docs/v0.4.12/api/streams.html#stream.pipe"&gt;pipe&lt;/a&gt; method built into Node.js to take the MP3 stream and pipe it into the &lt;code&gt;converter&lt;/code&gt; object.  This is just a wrapper around an ffmpeg child process.  We can then pipe the output of this ffmpeg process back into the response.&lt;/p&gt;

&lt;p&gt;The pipe method takes care of any complexity in handling these streams, making sure that they are always kept in-sync by pausing, draining and resuming streams as required.  All this means that, regardless of the size of the MP3 file from SoundCloud, the memory footprint of the Node.js process doesn't grow in size.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Combining these technologies made it fairly simple to put together a fairly sophisticated looking visualisation.  Below are a few samples of the images that canvas.fm can produce.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://canvas.fm/tracks/9430023/image/medium" alt="la mezcla" /&gt;
&lt;img src="http://canvas.fm/tracks/9223210/image/medium" alt="hot chip" /&gt;
&lt;img src="http://canvas.fm/tracks/15399781/image/medium" alt="tensnake" /&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 26 Oct 2011 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2011/10/26/experiments-with-the-html5-audio-data-api</guid>
    </item>
    <item>
      <title>Translation of Matz Q&amp;A article after joining Heroku</title>
      <link>http://blog.new-bamboo.co.uk/2011/7/12/translation-of-matz-q-a-article-after-joining-heroku</link>
      <author>makoto@new-bamboo.co.uk (makoto)</author>
      <comments>http://blog.new-bamboo.co.uk/2011/7/12/translation-of-matz-q-a-article-after-joining-heroku#disqus_thread</comments>
      <description>&lt;p&gt;NOTE from translator:&lt;/p&gt;

&lt;p&gt;This is a translation of an article from "PublicKey" - Enterprise IT x Cloud Computing x Web Technology / Blog.&lt;/p&gt;

&lt;p&gt;Mr Junichi Niino kindly allowed me to translate &lt;a href="http://www.publickey1.jp/blog/11/ruby_heroku.html"&gt;his original article&lt;/a&gt; from Japanese to English.&lt;/p&gt;

&lt;p&gt;Also, special thanks to &lt;a href="http://twitter.com/#!/knowtheory"&gt;@knowtheory&lt;/a&gt; for editing my translation.&lt;/p&gt;

&lt;h2&gt;Title: "I am looking forward to accelerating Ruby's progress" - Q&amp;amp;A with Matz regarding joining Heroku as a chief architect.&lt;/h2&gt;

&lt;p&gt;Date: 13th July 2011&lt;/p&gt;

&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;As mentioned in my previous article, It has been announced that Yukihiro Matsumoto (Matz) is joining Heroku as Chief Architect of Ruby. I asked Matz about the story behind his future role via email.&lt;/p&gt;

&lt;blockquote&gt;&lt;h4&gt;My mission is to make Ruby core more functional and higher quality.&lt;/h4&gt;&lt;/blockquote&gt;

&lt;h3&gt;PublicKey (Q going forward): Can you explain to me how this came about?&lt;/h3&gt;

&lt;p&gt;Mr Matsumoto (Matz going forward): When I last met Mr Marc Benioff (CEO of Salesforce.com) he asked me how he could support the development of Ruby.&lt;/p&gt;

&lt;p&gt;So I told him that I want to improve the situation which the majority of Ruby Core developers face, that they are either doing their work in their own spare time or they worry about their job security.&lt;/p&gt;

&lt;p&gt;He said he could provide us some support and that's why I decided to join Salesforce.com through Heroku (Note: Several members of Ruby Core are currently under negotiation to join Heroku).&lt;/p&gt;

&lt;p&gt;So, the core of our work will not change. Our mission is to develop Ruby Core, to make Ruby more functional and higher quality. Having said that, I am expecting that the job security we are being provided and Ruby usage feedback we get from heavy Ruby users such as Heroku will accelerate the progress of Ruby development. Otherwise, there would be no point to accepting the offer.&lt;/p&gt;

&lt;p&gt;However, joining Heroku as Chief Architect does not mean that I swear loyalty to Heroku and Salesforce.com. This does not change relationship with NaCl and Rakuten which continue to support me and for whom I also remain chairman of the Ruby association.&lt;/p&gt;

&lt;p&gt;As for the reason for the title? I picked the name "Chief Architect" out of multiple options as it sounded most business neutral. I am not going to be involved with any business decision about Heroku in future.&lt;/p&gt;

&lt;h3&gt;Q: Do you have any expectation about your role at Heroku?&lt;/h3&gt;

&lt;p&gt;Matz: As I already mentioned, it basically remains the same, but our development progress will be faster. Besides that, I would like to have closer communication with Heroku, so that we can work out removing constraints (if any) about using Ruby in cloud environments.&lt;/p&gt;

&lt;p&gt;Also, I would like to preserve my good relationship with other companies such as Engine Yard and VMWare and their trust that I am "&lt;em&gt;Ruby's&lt;/em&gt; Matz" even after joining Heroku.&lt;/p&gt;

&lt;h3&gt;Q: Do you have any vision of Ruby and Cloud at this moment?&lt;/h3&gt;

&lt;p&gt;Matz: To be frank, Many of Ruby Core developers (including myself) do not have much interest in the Web, but it is clear that cloud computing has become more and more important. So I would like to receive more input from these cloud environment and reflect that into the future direction of Ruby.&lt;/p&gt;

&lt;h3&gt;Q: Are you going to work in Silicon Valley, or join from Matsue remotely?&lt;/h3&gt;

&lt;p&gt;Matz: My lifestyle won't change (my working style may change though), so it is most likely that I will join the development from Matsue remotely.&lt;/p&gt;

&lt;p&gt;As far as I am concerned, I don't feel that moving to Silicon Valley would necessarily make me happier than i am now.&lt;/p&gt;

&lt;p&gt;However, I would like to have more direct communication with people in San Francisco/Silicon Valley (including Heroku) a few times a year.&lt;/p&gt;

&lt;p&gt;(NOTE: To be precise, the headquarters of Heroku are in San Francisco, not Silicon Valley, but it says "Silicon Valley company" at the press release.)&lt;/p&gt;

&lt;h3&gt;Q: Any other comment?&lt;/h3&gt;

&lt;p&gt;Matz: I have heard that many people (outside of Japan) did not know that Ruby core team hasn't had a sustainable development model until now. I hope this movement becomes a role model for any Japanese software developer who publishes information from Japan.&lt;/p&gt;

&lt;p&gt;Q: Thank you.&lt;/p&gt;
</description>
      <pubDate>Tue, 12 Jul 2011 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2011/7/12/translation-of-matz-q-a-article-after-joining-heroku</guid>
    </item>
    <item>
      <title>Degradable JavaScript Applications Using HTML5 pushState</title>
      <link>http://blog.new-bamboo.co.uk/2011/2/2/degradable-javascript-applications-using-html5-pushstate</link>
      <author>oliver.n@new-bamboo.co.uk (olivern)</author>
      <comments>http://blog.new-bamboo.co.uk/2011/2/2/degradable-javascript-applications-using-html5-pushstate#disqus_thread</comments>
      <description>&lt;h2&gt;What is the problem?&lt;/h2&gt;

&lt;p&gt;Using the location hash to keep track of current page state and enable back button navigation is more and more common with large, full featured, client side JavaScript apps.  Whilst the behaviour this gives is definitely an improvement to the user experience, implementing this with the location hash has some &lt;a href="http://isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs"&gt;shortcomings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thankfully, as with everything else on the web, HTML5 is here to solve all your problems, with two methods and an event, &lt;code&gt;pushState&lt;/code&gt;, &lt;code&gt;replaceState&lt;/code&gt; &amp;amp; &lt;code&gt;onpopstate&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;What is pushState?&lt;/h2&gt;

&lt;h3&gt;pushState &amp;amp; replaceState&lt;/h3&gt;

&lt;p&gt;The history object gains two new methods, &lt;code&gt;pushState&lt;/code&gt; &amp;amp; &lt;code&gt;replaceState&lt;/code&gt;, that allow us to change the
current location of the browser without making an HTTP request.  These new locations are stored in the
browsers history so that both the back and forward button work as expected.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;history.pushState({foo: "bar"}, "foo page", "/foo")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have a modern browser you can try out the above code in the console.  You should see the url bar
change to http://blog.new-bamboo.co.uk/foo.  The browser doesn't check whether that url exists on the
server, it does't even make an HTTP request.  You'll notice that if you press the back button the url
will change back, and pressing forward will set it to http://blog.new-bamboo.co.uk/foo again.&lt;/p&gt;

&lt;p&gt;The other method, &lt;code&gt;replaceState&lt;/code&gt;, is very similar but instead of pushing a new state into the browsers
history it replaces the current state (as the name suggests).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;history.replaceState({foo: "baz"}, "bar page", "/bar")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Both methods take three params, a state object (more about this later), a title and a url.  The title
is currently ignored by browsers, my guess is that at some point it will set the window title.  The url
param is what is used to set the current location in the browsers url bar.  It is an optional parameter
and if omitted the current location will be used.  You can read more about these methods at &lt;a href="https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history"&gt;MDC&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;onpopstate&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;onpopstate&lt;/code&gt; event fires whenever the browser location changes from the use of the back or forward button being used, regardless of whether &lt;code&gt;pushState&lt;/code&gt; or &lt;code&gt;replaceState&lt;/code&gt; were used to set the current location.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;window.onpopstate = function (event) {
  // see what is available in the event object
  console.log(event)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Used in combination with the &lt;code&gt;pushState&lt;/code&gt; &amp;amp; &lt;code&gt;replaceState&lt;/code&gt; it can be used to handle changes in the browsers location.  If the &lt;code&gt;popstate&lt;/code&gt; event is fired as a result of navigating to a point in history that was added with either &lt;code&gt;pushState&lt;/code&gt; or &lt;code&gt;replaceState&lt;/code&gt; then the state object passed when calling those methods will be available as &lt;code&gt;event.state&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately there is no native &lt;code&gt;onpushstate&lt;/code&gt; event, so to be notified of when something is pushed onto
the history you will have to roll your own.  Again to get more details about this event head over to &lt;a href="https://developer.mozilla.org/en/DOM/window.onpopstate"&gt;MDC&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;pushState vs location.hash&lt;/h2&gt;

&lt;p&gt;pushState has some considerable advantages over location.hash for the purpose of not breaking the back button.  Firstly, although it is now part of the HTML5 spec, the &lt;code&gt;onhashchange&lt;/code&gt; event is not supported everywhere, and until recently checking for changes to the hash required polling.&lt;/p&gt;

&lt;p&gt;Also, as the name suggests, the &lt;code&gt;onhashchange&lt;/code&gt; event only fires when the hash changes, it is not possible to detect when the same location is navigated to consecutively.  With push state you can push the same location onto the browser history as many times as you wish and &lt;code&gt;onpopstate&lt;/code&gt; will fire for each of these locations.&lt;/p&gt;

&lt;p&gt;The biggest short comings of using the location hash are that the url anchor is a purely client side piece of information.  When navigating to a location with an anchor the server is never sent the hash proportion of the location.  This can cause issues when JavaScript is not available to provide the routing based on the hash location.&lt;/p&gt;

&lt;p&gt;Since the whole url can be changed when using &lt;code&gt;pushState&lt;/code&gt;, any time that url is navigated to without JavaScript available, the server gets the full location.  This allows a server to respond with the full request.&lt;/p&gt;

&lt;h2&gt;Davis.js vs Sammy.js&lt;/h2&gt;

&lt;p&gt;Here at New Bamboo we have made full use of &lt;a href="http://sammyjs.org/"&gt;Sammy.js&lt;/a&gt; for over a year now for routing in JavaScript applications and it has served us well.  Sammy.js uses location.hash for its routing so that you can use links with an anchor to control page state.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;a href="#/hello/bob"&amp;gt;Say Hello to Bob&amp;lt;/a&amp;gt;
&amp;lt;a href="#/hello/dave"&amp;gt;Say Hello to Dave&amp;lt;/a&amp;gt;

var app = Sammy(function () {
  this.get('#/hello/:name', function (ctx) {
    alert('Hello ' + ctx.params['name'])
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above example shows a very simple Sammy app.  When clicking on the links the location hash changes and the route is run, displaying a friendly greeting.  This works brilliantly when JavaScript is available, however if the links are clicked and there is no JavaScript then nothing will happen.  The server wouldn't know anything about our intention to greet either Bob or Dave.&lt;/p&gt;

&lt;p&gt;I created a small library called &lt;a href="https://github.com/olivernn/davis.js"&gt;Davis.js&lt;/a&gt;, which is heavily influenced by Sammy, and that uses &lt;code&gt;pushState&lt;/code&gt; rather than location hash for its routing, the above example using Davis looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;a href="/hello/bob"&amp;gt;Say hello Bob&amp;lt;/a&amp;gt;
&amp;lt;a href="/hello/dave"&amp;gt;Say hello Dave&amp;lt;/a&amp;gt;

var app = Davis(function () {
  this.get('/hello/:name', function (req) {
    alert('Hello ' + req.params['name'])
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see the two are almost identical, the only difference is the href of the links.  If JavaScript is unavailable with the Davis example, then clicking on the links will make a regular request to the server.  As long as the server can also respond to the &lt;code&gt;/hello/:name&lt;/code&gt; route then the user will still get their friendly greeting.&lt;/p&gt;

&lt;p&gt;Davis really is just a simplified version of Sammy using HTML5 pushState - be sure to check out a slightly more complex example and the docs.&lt;/p&gt;

&lt;h2&gt;Reuseable templates for dryer code&lt;/h2&gt;

&lt;p&gt;Where Davis really shines is in combination with a templating system that can be shared between both the client and the server.  A good choice for this would be &lt;a href="http://mustache.github.com/"&gt;Mustache&lt;/a&gt; templates.  A simple greeting template might look like this.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Hello {{name}}&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If both the server and the client use this exact same template to respond to the &lt;code&gt;/hello/:name&lt;/code&gt; route then it is relatively simple to make our simple app degrade gracefully when JavaScript is unavailable.   So our JavaScript route might look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;this.get('/hello/:name', function (req) {
  var html = Mustache.to_html("&amp;lt;h1&amp;gt;Hello {{name}}&amp;lt;/h1&amp;gt;", {name: req.params['name']});
})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the server, using Sinatra for example, could use the same template and do the same thing.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;get '/hello/:name' do
  Mustache.render("&amp;lt;h1&amp;gt;Hello {{name}}&amp;lt;/h1&amp;gt;", {:name =&amp;gt; params[:name]})
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mustache is currently very easy to integrate into Sinatra apps, however it isn't as straightforward with a Rails app.  With the help of &lt;a href="https://github.com/markevans"&gt;Mark Evans&lt;/a&gt; I have put together a simple gem called &lt;a href="https://github.com/olivernn/poirot"&gt;Poirot&lt;/a&gt; that enables use of Mustache partials within a Rails 3 app.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# in greetings controller

def show
  @name = params[:name]
end

# in app/views/greetings/show.html.erb

&amp;lt;!-- to include the template for JavaScript to share --&amp;gt;
&amp;lt;%= template_include_tag "greeting" %&amp;gt;

&amp;lt;%= render :partial =&amp;gt; "greeting" %&amp;gt;

# in app/views/greetings/_greeting.html.mustache
&amp;lt;h1&amp;gt;Hello {{name}}&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The gem gives the templates access to all the instance variables defined in the controller and the normal Rails view helpers.  A default view class is created but if you need more control over what variables are available in the Mustache template you can extend it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# in app/views/greetings/greeting.rb

module Greetings
  class Greeting &amp;lt; Poirot::View
    def time
      Time.now
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The greeting mustache template would now also have access to the current time.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Using HTML5 pushState in combination with re-useable templates can provide a good starting point for more degradable and accessible JavaScript applications.  Support for pushState is good in all good modern browsers, it is already being used by &lt;a href="https://github.com/blog/760-the-tree-slider"&gt;GitHub&lt;/a&gt; and Flickr, so the next time you need some kind of back button support in JavaScript apps why not try it out.&lt;/p&gt;
</description>
      <pubDate>Thu, 03 Feb 2011 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2011/2/2/degradable-javascript-applications-using-html5-pushstate</guid>
    </item>
    <item>
      <title>Learning Japanese the Rubyist way </title>
      <link>http://blog.new-bamboo.co.uk/2010/12/15/learning-japanese-the-rubyist-way</link>
      <author>makoto@new-bamboo.co.uk (makoto)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/12/15/learning-japanese-the-rubyist-way#disqus_thread</comments>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Step 1: How to read Japanese characters&lt;/li&gt;
&lt;li&gt;Step 2: Japanese and OO&lt;/li&gt;
&lt;li&gt;Step 3: Japanese and functional&lt;/li&gt;
&lt;li&gt;Step 4: Writing Japanese programming language in Ruby&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Ruby Advent Calendar&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Have you ever thought about learning Japanese, but it looks too difficult to learn?
Surprisingly, Japanese and Ruby share some common features and concepts. This is a shortcut version of my presentation called "Japanese and Ruby" which I presented at &lt;a href="http://lrug.org"&gt;LRUG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you finish reading this post, hopefully you find Japanese language less magical, and may even add "Learn Japanese" to one of your 2011 new year resolutions.&lt;/p&gt;

&lt;p&gt;Learning a new language always has a bit of steep learning curve. Go and get some coffee before you start!!&lt;/p&gt;

&lt;h2&gt;Step 1: How to read Japanese characters&lt;/h2&gt;

&lt;p&gt;One of the first big hurdle when learning a language is to remember all characters. This is not a issue if you are learning a language based on alphabet, but many non western languages have their own character sets.&lt;/p&gt;

&lt;p&gt;To make the matters worse, Japanese uses three different character set, Kanji (Chinese character), Hiragana, and Katakana. Hiragana and Katakana each has 46 characters and there are a lots of Kanji (possibly 50,000, though we use ONLY 2000 ~ 3000 in daily use).&lt;/p&gt;

&lt;p&gt;Here is the mapping of Hiragana, Katakana, and Alphabet.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Nihongo_ichiran_01-converted.svg/531px-Nihongo_ichiran_01-converted.svg.png" title="Hiragana Katakana Kanji" alt="Hiragana Katakana Kanji" /&gt;&lt;/p&gt;

&lt;p&gt;(The diagram is from &lt;a href="http://en.wikipedia.org/wiki/Japanese_language"&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The point here is not to overwhelm you with the amount of information, but to let you think "WHY" Japanese uses 3 character sets.&lt;/p&gt;

&lt;p&gt;Originally, Japanese did not have its own character set, so we used to borrow characters from China (Kanji). Since Chinese grammar and Japanese grammar are completely different, it was not easy to map all these Kanji into Japanese sentence.
That's when Hiragana and Katakana were born to supplement Kanji. Hiragana is often used as a glue to combine words into sentence where Kanji alone is not good enough.&lt;/p&gt;

&lt;p&gt;For example "行" is a Kanji character which means "to go". Japanese has many different ways to change the ending of verb (eg: goes) end we use Hiragana to supplement.
Here are the examples.&lt;/p&gt;

&lt;table border="1" cellspacing="0"&gt;
  &lt;tr&gt;
    &lt;th&gt;Japanese&lt;/th&gt;
    &lt;th&gt;Alphabet&lt;/th&gt;
    &lt;th&gt;Meaning&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;行く&lt;/td&gt;
    &lt;td&gt;Iku&lt;/td&gt;
    &lt;td&gt;I go&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt; 行かない&lt;/td&gt;
    &lt;td&gt;Ikanai&lt;/td&gt;
    &lt;td&gt;I do not go&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt; 行こう&lt;/td&gt;
    &lt;td&gt;Ikou&lt;/td&gt;
    &lt;td&gt;Let's go, the more casual way&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt; 行きましょう&lt;/td&gt;
    &lt;td&gt;Ikimasho&lt;/td&gt;
    &lt;td&gt;Let's go, the more polite way&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt; 行け&lt;/td&gt;
    &lt;td&gt;Ike&lt;/td&gt;
    &lt;td&gt;Go, very non polite way&lt;/td&gt;
  &lt;/tr&gt;

&lt;/table&gt;


&lt;p&gt;NOTE: If the above examples do not look like Japanese, you have an encoding issue. Make sure that your browser encoding is set to UTF-8&lt;/p&gt;

&lt;p&gt;Katakana, on the other hand, was often used alongside with Kanji so that people can understand how to pronounce the Kanji. Nowadays, Katakana is often used to represent new words which came from foreign countries.&lt;/p&gt;

&lt;p&gt;eg: &lt;ruby&gt;&lt;rb&gt;漢字&lt;/rb&gt;&lt;rp&gt;（&lt;/rp&gt;&lt;rt&gt;カンジ&lt;/rt&gt;&lt;rp&gt;）&lt;/rp&gt;&lt;/ruby&gt;,  ルビー&lt;/p&gt;

&lt;p&gt;(Trivia. The above example is expressed with html5 &lt;a href="http://www.quackit.com/html_5/tags/html_ruby_tag.cfm"&gt;ruby tag&lt;/a&gt; )&lt;/p&gt;

&lt;p&gt;(Another Trivia. Before multibyte became common, Japanese computers were only able to handle Alphabet and single-byte Katakana (eg: ﾙﾋﾞｰ), instead of multibyte (eg:  ルビー). Some banks' ATM slips still use this single byte Katakana)&lt;/p&gt;

&lt;p&gt;Even though they are the conventions, you can use Kanji, Katakana, and Hiragana interchangeably.&lt;/p&gt;

&lt;p&gt;The following 3 all means "Cherry blossom bloom" and pronounces the same "Sakura Saku"&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;桜咲く　
サクラさく　
さくらさく
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Trivia. The world "Karaoke" is the combination of Kanji "Kara"(空 , means "Empty")  and English "Oke" Orchestra.)&lt;/p&gt;

&lt;p&gt;Here is the quick recap of what you learnt so far.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kanji came first to import Chinese words&lt;/li&gt;
&lt;li&gt;Hiragana was created to suit for domestic use&lt;/li&gt;
&lt;li&gt;Katakana is used to adopt new words&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Doesn't this "There are many ways to achieve one thing" concept familiar with Ruby's philosophy?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ruby came first to bring concept of OO &amp;amp; Functional&lt;/li&gt;
&lt;li&gt;Ruby was created to suit for every day scripting use&lt;/li&gt;
&lt;li&gt;Ruby keeps evolving by adopting new concepts (Fiber, Multinationalization/M17N, Refinements etc)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Step 2: Japanese and OO&lt;/h2&gt;

&lt;p&gt;Satoshi Nakashima is a well known Japanese blogger who used to work at Microsoft as one of the development team members who shipped Windows 95 and Internet Explorer.&lt;/p&gt;

&lt;p&gt;He was once asked "Are there anything it helped to create Windows 95 as a Japanese?" He initially did not come up with anything, but then thought that Japanese grammar structure is more suited to Object Oriented programming. To explain his thought, I will explain you some basic Japanese grammar.&lt;/p&gt;

&lt;p&gt;English and Japanese has very different grammatical order.&lt;/p&gt;

&lt;p&gt;English grammar structure is called "SVO"(Subject - Verb - Object), while Japanese one is called "SOV"(Subject - Object - Verb)&lt;/p&gt;

&lt;p&gt;If I put "I eat bacon" in Japanese order, it is going to be "I bacon eat"(Watashi ha bacon wo tabemasu "私はベーコンを食べます")&lt;/p&gt;

&lt;p&gt;At first glance, English order is clearer as "what you do"(verb) comes next to "who does it"(subject). It's almost like command line options (eg: git clone url).&lt;/p&gt;

&lt;p&gt;The problem of command line options is that there are so many choices that it's hard to figure out which command you are supposed to use.&lt;/p&gt;

&lt;p&gt;On the other hand, Japanese grammatical order is more similar to GUI. You often (right-mouse) click an object you are interested, then it suggests the possible actions. This is much more user friendly because you do not have to know all the possible actions and its argument options.&lt;/p&gt;

&lt;p&gt;As you already know, Ruby is one of the best scripting languages to express OO (though you can write in procedural, or "command oriented way" if you wish)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Procedural 
open("box") 
open("car")
open("file", "foo.txt")  

# OO 
Box.new.open 
Car.new.open 
File.open("foo.txt")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the above example, they both do exactly the same thing, but the implementation will be quite different. For procedural example, I imagine that you have to keep adding nested "if" statement as logic becomes more complicated. On the other hand, the logic of OO way is kept isolated within each class.&lt;/p&gt;

&lt;h2&gt;Step 3: Japanese and functional&lt;/h2&gt;

&lt;p&gt;I often says Japanese is a politician's language.
What does this mean?
My definitions of politicians's are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they do not commit to anything unless necessary&lt;/li&gt;
&lt;li&gt;they mean different things depending on context&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In Japanese grammar, there is a term called "Postpositional" ("Pre-positional" is often used in English, such as &lt;em&gt;for&lt;/em&gt; you, &lt;em&gt;after&lt;/em&gt; dinner, and so on).
Postpositional is used to decide the role of noun which it supports. This enables you to change the order of structure very flexibly, chain as many sentence as you like, and also let you omit subject.&lt;/p&gt;

&lt;p&gt;Here are some examples of what I just said.&lt;/p&gt;

&lt;table border="1" cellspacing="0"&gt;
&lt;tr&gt;
  &lt;th&gt;Japanese&lt;/th&gt;
  &lt;th&gt;English&lt;/th&gt;
  &lt;th&gt;How to pronounce&lt;/th&gt;
  &lt;th&gt;Structure&lt;/th&gt;
  &lt;th&gt;How it is ordered if written in English&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;私はベーコンを食べます&lt;/td&gt;
  &lt;td&gt;I eat bacon&lt;/td&gt;
  &lt;td&gt;Watashi ha bacon wo tabemasu&lt;/td&gt;
  &lt;td&gt;SOV&lt;/td&gt;
  &lt;td&gt;I bacon eat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;ベーコンを私は食べます&lt;/td&gt;
  &lt;td&gt;I eat bacon&lt;/td&gt;
  &lt;td&gt;Bacon wo watashi ha tabemasu&lt;/td&gt;
  &lt;td&gt;OSV&lt;/td&gt;
  &lt;td&gt;Bacon I eat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;ベーコンを食べます&lt;/td&gt;
  &lt;td&gt;I eat bacon&lt;/td&gt;
  &lt;td&gt;Bacon wo tabemasu&lt;/td&gt;
  &lt;td&gt;OV&lt;/td&gt;
  &lt;td&gt;Bacon eat&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;


&lt;p&gt;And this is the example of chaining too much sentence together.&lt;/p&gt;

&lt;p&gt;&lt;example&gt;&lt;/p&gt;

&lt;p&gt;One of the common mistakes Japanese people make when writing a sentence is chaining too much, because it is very hard to digest the whole sequence (One of my friends explained this as "Don't write a sentence which could cause stack overflow").
What makes English very logical and concise (in my opinion) is because the subject and verb comes at the beginning.
Even though you can still write verbose sentence in English, this strict ordering forces you to write things relatively concise.&lt;/p&gt;

&lt;p&gt;On the other hand, you can write a lot of sentence in Japanese meaning nothing because it omits subject, and also the verb you used at the very end have very loose relationship to the sentence you started at the beginning.&lt;/p&gt;

&lt;p&gt;Now let's move back to how this (loosely) relates to some of the concepts in Ruby.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they do not commit to anything unless necessary =&gt; Lazy evaluation&lt;/li&gt;
&lt;li&gt;they mean different things depending on context =&gt; Block&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;eg:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% 10000.times =&amp;gt; #&amp;lt;Enumerator: 10000:times&amp;gt;

User.order('users.id DESC').limit(20).includes(:items)

File.open("/tmp.txt").each do |line|     
  puts line 
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Functional features of Ruby lets you do crazy metaprogramming. Though they are powerful, abusing may confuse people to understand the code and may cause unexpected bug ;-P&lt;/p&gt;

&lt;h2&gt;Step 4: Writing Japanese programming language in Ruby&lt;/h2&gt;

&lt;p&gt;So, how are you doing so far? Easy peasy Japanesey?&lt;/p&gt;

&lt;p&gt;(Trivia: the above expression is apparently common phrase in UK, derived from some TV commercial saying "easy peasy lemon squeezy")&lt;/p&gt;

&lt;p&gt;When you learn a new language, reading books/articles are not enough. You always need to practice.
Having said that, speaking to real Japanese people from day one may be a bit too difficult (or you just do not have a Japanese friend ;-( ), so here is a toy for you to play around.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/makoto/japanize"&gt;Japanize&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Some of my colleague once asked me "Are there any Japanese programming languages? What I mean is not just to be able to write Japanese text as string, but all programming syntax (such as "if", "loop") are actually in Japanese". Yes, there are some. &lt;a href="http://nadesi.com/"&gt;Nadeshiko&lt;/a&gt; and &lt;a href="http://www.scripts-lab.co.jp/mind/whatsmind.html"&gt;Mind&lt;/a&gt; are the ones.
However, I decided to write it myself using Ruby, and here is the result.&lt;/p&gt;

&lt;p&gt;&lt;object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345'&gt;&lt;param name='movie' value='http://screenr.com/Content/assets/screenr_1116090935.swf' /&gt;&lt;param name='flashvars' value='i=141953' /&gt;&lt;param name='allowFullScreen' value='true' /&gt;&lt;embed src='http://screenr.com/Content/assets/screenr_1116090935.swf' flashvars='i=141953' allowFullScreen='true' width='560' height='345' pluginspage='http://www.macromedia.com/go/getflashplayer'&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;Looks amazing, isn't it?&lt;/p&gt;

&lt;p&gt;Here are few more Japanese examples to understand what I just showed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'に' and 'を' are postpositional which means that the words in front of them (1 and 2) are objects.&lt;/li&gt;
&lt;li&gt;'たす'(hiragana) and '足す'(kanji + hiragana) are both verbs and mean "to add"&lt;/li&gt;
&lt;li&gt;'て' is also postpositional which says this is end of one sentence and next sentence will start (equivalent to "and")&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In my programme, I simply used postpositional as delimiters to split a Japanese phrase into words.&lt;/p&gt;

&lt;p&gt;(Trivia: Japanese words are not separated by space ,so tokeniziing Japanese are very important part of natural language processing)&lt;/p&gt;

&lt;p&gt;So&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;１に２をたして４を掛ける
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Becomes&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[1, 2, :+, 4, :*]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Japanese grammar is a bit like &lt;a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation"&gt;reverse polish notation&lt;/a&gt;, or a stack machine which is often used by a compiler to process a programming language. So the above array is equivalent to the following mathematical calculation.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe Evaluator do   
  it "must calculate all operands" do     
    Evaluator.new([1, 2, :+, 3 , :* , 1, :-, 2, :/]).       
      evaluate.must_equal ((((1+2) * 3) - 1 ) / 2)   
  end 
end 
# NOTE: This is minitest which comes by default in Ruby 1.9
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are a few more secrets&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ruby-1.9.2-p0 &amp;gt; 1
 =&amp;gt; 1 
ruby-1.9.2-p0 &amp;gt; １
NameError: undefined local variable or method `１' for main:Object
    from (irb):8
    from /Users/makoto/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `&amp;lt;main&amp;gt;'
ruby-1.9.2-p0 &amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you see the video closely, you can notice that the number I typed is slightly different from normal ascii number. It's unicode number, so it raises "undefined local variable or method" error.&lt;/p&gt;

&lt;p&gt;Since Japanese does not have any space between words, you can catch an entire sentence as a method&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ruby-1.9.2-p0 &amp;gt;  １に２をたす
NameError: undefined local variable or method `１に２をたす' for main:Object
    from (irb):9
    from /Users/makoto/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `&amp;lt;main&amp;gt;'
ruby-1.9.2-p0 &amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I just passes the entire expression as one method and catches at method_missing&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# -*- encoding: utf-8 -*-
def method_missing (*obj) 
  if 数字[obj[0][0]]
    parsed = Parser.new(obj[0].to_s).parse
    Evaluator.new(parsed).evaluate 
  else
    super 
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is how japanize works.&lt;/p&gt;

&lt;p&gt;When I was researching how to implement very simple compiler/interpreter, I learnt a lot from an article written by Koichi Sasada (the creator of Ruby 1.9  Virtual Machine). The article is written in Japanese, but there is one sample code which implements some basic VM functionalities in Ruby.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jp.rubyist.net/magazine/?0007-YarvManiacs"&gt;RubiMaVM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The code handles not just maths, but also loop and if statement. If you are curious enough, you could implement something similar on top of Japanize. I will accept pull request as long as it looks like Japanese !!&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Here are the list of things you learnt through this post.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Japanese uses 3 characters, Kanji, Hiragana, and Katakana.&lt;/li&gt;
&lt;li&gt;Japanese grammar structure is Subject - Object - Verb(SOV)&lt;/li&gt;
&lt;li&gt;Japanese order can be flexible thanks to postpositional&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Even though Matz did not intend to reflect Japanese language into the design of Ruby, I think there are certain influence, since anyone's thought is influenced by the language they use.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screen+shot+2010-12-02+at+00" src="http://blog.new-bamboo.co.uk/media/2010/12/17/02/20/00/506/Screen+shot+2010-12-02+at+00.32.20.jpg?m=resize&amp;amp;o[geometry]=400x300&amp;amp;s=80316ca4483e94d1" /&gt;&lt;/p&gt;

&lt;p&gt;(NOTE: @yukihiro_matz says "Japanese and Ruby? I try not to think too much about Japanese culture. The method chain looks like Japanese, but it's just a coincident. Having said that, the support of M17N is heavily influenced by the use case of Japanese people. Otherwise, I wouldn't spend too much time on such a hard problem".  You can compare how @matz_translated bot actually translated the sentence).&lt;/p&gt;

&lt;p&gt;If you are interested more, the full slide of my talk at LRUG is here.&lt;/p&gt;

&lt;div style="width:425px" id="__ss_6165968"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/inouemak/ruby-and-japanesepdf" title="Ruby and japanese"&gt;Ruby and japanese&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse6165968" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rubyandjapanesepdf-101214163926-phpapp01&amp;stripped_title=ruby-and-japanesepdf&amp;userName=inouemak" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse6165968" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rubyandjapanesepdf-101214163926-phpapp01&amp;stripped_title=ruby-and-japanesepdf&amp;userName=inouemak" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/inouemak"&gt;inouemak&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;


&lt;p&gt;The talk was videotaped, so it may be uploaded &lt;a href="http://skillsmatter.com/event/ajax-ria/japanese-and-ruby-and-processing-tweets-at-the-bbc/rl-311"&gt;here&lt;/a&gt; later.&lt;/p&gt;

&lt;h2&gt;Ruby Advent Calendar&lt;/h2&gt;

&lt;p&gt;This is Day 17 of &lt;a href="http://atnd.org/events/10439"&gt;Ruby Advent Calendar&lt;/a&gt;(Each day leading up to December 25th, one person posts an article to their blog and adds a link to their blog on the Advent Calendar). The previous entry was written by &lt;a href="http://matschaffer.com"&gt;matschaffer&lt;/a&gt; or &lt;a href="http://blog.joshsoftware.com/"&gt;gautamrege&lt;/a&gt; (order seems a bit screwed up), and the next will be written by &lt;a href="http://evan.tiggerpalace.com"&gt;elight&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Fri, 17 Dec 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/12/15/learning-japanese-the-rubyist-way</guid>
    </item>
    <item>
      <title>Ruby divide at RubyKaigi 2010 and what can you do as a Rubyist? (Part 2) </title>
      <link>http://blog.new-bamboo.co.uk/2010/9/19/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-2</link>
      <author>makoto@new-bamboo.co.uk (makoto)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/9/19/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-2#disqus_thread</comments>
      <description>&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/CFGBHyf6jZZslfOfyBlLrg?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_k-QRXbUACBU/TIGGPYYFwII/AAAAAAAACDI/HWPIneva5Mg/s400/R1001110.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/inouemak/Rubykaigi2010?feat=embedwebsite"&gt;Matz On Pusher&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;


&lt;h2&gt;Contents&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;At previous post&lt;/li&gt;
&lt;li&gt;"RubyKaigi must end (for now)"&lt;/li&gt;
&lt;li&gt;So, what can we do?&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;At previous post.&lt;/h2&gt;

&lt;p&gt;At &lt;a href="http://blog.new-bamboo.co.uk/2010/9/14/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-1"&gt;previous post&lt;/a&gt;, I went through the following Ruby divides I noticed during RubyKaigi 2010.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Japanese / English = Ruby core ML and many variable documentations are written in Japanese and non Japanese developers are hard to access such information.&lt;/li&gt;
&lt;li&gt;Committers / Users = There seems divides between C dvelopers (C Ruby committers ), Java developers (JRuby community), and the rest (Ruby users).&lt;/li&gt;
&lt;li&gt;Before / After Rails = Japanese Ruby scene is very unique from the rest of the world(aka Galapagos). Some part are very advanced, but others are missing important aspect of Rails culture (eg: github, rubygems).&lt;/li&gt;
&lt;li&gt;Hobby / Enterprise = The ratio of Japanese Rubyists who uses Ruby at day job seems low.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;These problems probably exist on any Ruby community(except English/Japanese bit) at certain extent, but the divide is especially deep in Japan, partly caused by the language gap, but some of them are inherent problems since Ruby was born in this country.&lt;/p&gt;

&lt;h2&gt;"RubyKaigi must end (at least once)"&lt;/h2&gt;

&lt;p&gt;Some of these problems have been pointed by &lt;a href="http://twitter.com/shyouhei"&gt;@shyouhei&lt;/a&gt;" a year ago at his blog called "Ruby Must end(at least once)"(The English translation is &lt;a href="http://github.com/makoto/japanese_fine_software_writings/wiki/Rubykaigi-must-die"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In his blog,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RubyKaigi is maintained by the hard work of the enthusiastic volunteers, but it is coming to the stage where the growth of Ruby community is going beyond the capacity of these volunteers.&lt;/li&gt;
&lt;li&gt;The majority of the attendees are simply happy to attend the Kaigi and mingle with other attendees, but these networking efforts do not result back to Ruby community to keep up the work (such as documentation, more ruby committers and maintainers for bug fixes).&lt;/li&gt;
&lt;li&gt;As a solution, &lt;strong&gt;RubyKaigi should end for now and think about new ways to have a sustainable and scalable organisation/community&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This idea became the foundation of the theme for RubyKaigi2010.&lt;/p&gt;

&lt;p&gt;Since the end of RubyKaigi, there have been a lot of conversation on Twittersphere suggesting various solutions, and some people actually made some actions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://twitter.com/pwim"&gt;@pwim&lt;/a&gt; started &lt;a href="http://www.tokyorubyistmeetup.org/"&gt;Tokyo Ruby User group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sarahmei.com/blog/2010/09/01/asakusa-rb/"&gt;asakusa.rb and sfruby.rb became syster meetups&lt;/a&gt; (by &lt;a href="http://twitter.com/a_matsuda"&gt;@a_matsuda&lt;/a&gt;, &lt;a href="http://twitter.com/sarahmei"&gt;@sarahmei&lt;/a&gt;, and &lt;a href="http://twitter.com/ultrasaurus"&gt;@ultrasaurus&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.amazon.co.jp/%E3%82%81%E3%82%93%E3%81%90%E3%82%8B%E3%82%81-Ruby-on-%E6%9D%BE%E6%B1%9F%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3%E3%83%BB%E3%82%AD%E3%83%A5%E3%83%BC%E3%83%93%E3%83%83%E3%82%AF%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/B003L7H9SA/ref=sr_1_5?ie=UTF8&amp;amp;s=food-beverage&amp;amp;qid=1273249165&amp;amp;sr=8-5"&gt;Mengurume Matsue Ramen&lt;/a&gt; contribute some of their sales to Ruby Association (NOTE: This was in action before/during the Kaigi, too).&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;img width = "300" src="http://ec2.images-amazon.com/images/I/51eX1j1CK1L._SS400_.jpg"&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;From "Ruby on 松江ラーメン・キュービックシリーズ" at amazon&lt;/p&gt;

&lt;h2&gt;So, what can we do?&lt;/h2&gt;

&lt;p&gt;I also spent a bit of time thinking about these problems, and here are my list of suggestions to both Japanese and non Japanese Rubyists. I would love to know other people's suggestions,too.&lt;/p&gt;

&lt;h3&gt;Read "What can you do as a Rubyist?"&lt;/h3&gt;

&lt;p&gt;Unlike list of &lt;a href="http://contributors.rubyonrails.org/"&gt;Rails contributors&lt;/a&gt;, Ruby has &lt;a href="http://www.ohloh.net/p/ruby/contributors"&gt;less contributors&lt;/a&gt; (RoR has 1600 contributors, while Ruby has about 700 for last 5 years each).&lt;/p&gt;

&lt;p&gt;About a year ago, &lt;a href="http://twitter.com/fdiary"&gt;@fdiary&lt;/a&gt; wrote an article called "What can you do as a Rubyist" at Rubyist Magazine (The full translation is &lt;a href="http://github.com/makoto/japanese_fine_software_writings/wiki/What-can-you-do-as-a-Rubyist"&gt;here&lt;/a&gt;). In this article, he talked about the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Ruby Software, so that you can hack and extend the system you actually make use of.&lt;/li&gt;
&lt;li&gt;Update to the latest (especially Ruby 1.9), take profiling, check memory usage, and report if you find any bugs.&lt;/li&gt;
&lt;li&gt;Do the periodic code review via commit logs, so that you will get better understanding about the software (great way to learn the code)&lt;/li&gt;
&lt;li&gt;When you get stack at bug fix, report and ask for help.&lt;/li&gt;
&lt;li&gt;Patrol blogs/twitter and help other people.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This is a great way to contribute to Ruby even if you are not the hard core C developers, and looks great way to improve your Ruby skills, debugging skills, and performance profiling/improvement skills.&lt;/p&gt;

&lt;h3&gt;Let's make Christmas Ruby&lt;/h3&gt;

&lt;p&gt;Hacking into Ruby source code seems hard. Why don't you start an easy and fun way first?&lt;/p&gt;

&lt;p&gt;The funniest Rubyist during the Kaigi was &lt;a href="http://twitter.com/technohippy"&gt;@technohippy&lt;/a&gt;. He is known as the "first and last author of Google Wave book". Apparently his book was printed on the day Google announced not to continue the Google Wave development. During his lightning talk, he mentioned 3 of his funny Ruby clones(objective ruby, xruby, and fruby). The best one was "Fuzzy Ruby" which has "if maybe", "if perhaps", and "if probably" syntax to return true in different probability.&lt;/p&gt;

&lt;script src="http://gmodules.com/ig/ifr?url=http://gimite.net/rails/iframe_gadget/xml%3Fscrolling%3Dtrue%26url%3Dhttps://docs.google.com/present/embed%253Fid%253Ddchb3tb2_201fz7kq3xf&amp;amp;synd=open&amp;amp;w=410&amp;amp;h=342&amp;amp;title=&amp;amp;border=%23ffffff%7C3px%2C1px+solid+%23999999&amp;amp;output=js"&gt;&lt;/script&gt;


&lt;p&gt;During the talk, he mentioned that we have passed the time to keep receiving christmas present from Matz, and now it is time to give something back to Matz.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;count = 0
1000.times do
  if true probably
    count += 1 
  end
end
puts count #=&amp;gt; 839
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://d.hatena.ne.jp/technohippy/20100123"&gt;fuzzy ruby example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This looks like just a joke (honestly, I don't think Matz is going to accept "if perhaps" as a new syntax), but I think this is a great way to get to know the Ruby internal, and it could potentially increase the number of Ruby committers in future.&lt;/p&gt;

&lt;p&gt;Here are the slides/videos about hacking Ruby internals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://prezi.com/tsuouxb3z4ln/jruby-hacking-guide/"&gt;Jruby Hacking Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hacking Parse.y = &lt;a href="http://www.slideshare.net/ujihisa/hacking-parsey-rubyconf-2009"&gt;Slide&lt;/a&gt;, &lt;a href="http://rubyconf2009.confreaks.com/19-nov-2009-17-15-hacking-parsey-tatsuhiro-ujihisa.html"&gt;Video&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;More sister user groups&lt;/h3&gt;

&lt;p&gt;It's great that asakusa.rb and sfruby.rb are sister groups after many foreign Rubyist visited Japan, but we can have more partnership among other Japanese ruby user groups and non Japanese ruby user group. Apparently there are more than &lt;a href="http://jp.rubyist.net/?RegionalRubyistMeetUp"&gt;20 ruby user groups&lt;/a&gt; in Japan. This is especially important for groups outside of Tokyo. Most foreigners tend to stay either in Tokyo or Kyoto, but you don't see many foreigners at other cities. Hence other regional Rubyists do not have chance to interact with non Japanese Rubyists. It would be fun if we can have Ruby User &lt;a href="http://en.wikipedia.org/wiki/Group_dating"&gt;GoKon&lt;/a&gt; to match up Japanese user groups and non Japanese user groups at next Ruby Kaigi!!&lt;/p&gt;

&lt;h3&gt;Let's go to RubyKaigi 2011&lt;/h3&gt;

&lt;p&gt;Last, not least. Let's go to next Ruby Kaigi and make the final Ruby Kaigi memorable event and also great start of something new.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;It's impossible to do everything I suggested here, but would be nice if you find something you could start from today, or you come up something else by reading this blog post. So what am I going to do? As you might have noticed, I started writing some of translations to &lt;a href="http://github.com/makoto/japanese_fine_software_writings/wiki"&gt;Japanese Fine Software Writings&lt;/a&gt; wiki. If you would like to add more Japanese software writing (doesn't necessarily have to be "fine" nor "Ruby"), or would like to contribute as editors, please feel free to edit the wiki.&lt;/p&gt;
</description>
      <pubDate>Tue, 21 Sep 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/9/19/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-2</guid>
    </item>
    <item>
      <title>Ruby divide at RubyKaigi 2010 and what can you do as a Rubyist? (Part 1)</title>
      <link>http://blog.new-bamboo.co.uk/2010/9/14/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-1</link>
      <author>makoto@new-bamboo.co.uk (makoto)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/9/14/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-1#disqus_thread</comments>
      <description>&lt;h1&gt;Ruby divide at RubyKaigi 2010 and what can you do as a Rubyist? (Part 1)&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/recompile_net/4935820587/" title="RubyKaigi 2010 Staff by Naoto Takai, on Flickr"&gt;&lt;img src="http://farm5.static.flickr.com/4134/4935820587_2169342225.jpg" width="500" height="333" alt="RubyKaigi 2010 Staff" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;It is almost 2 weeks since RubyKaigi finished. For full details of the conference, check out &lt;a href="http://jakescruggs.blogspot.com/2010/08/ruby-kaigi-2010-day-1.html"&gt;Jake Scruggs' near real time report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ruby Kaigi was one of the most memorable conferences I have ever attended. There were countless efforts by volunteer staff to make the conference as enjoyable as possible. I met lots of interesting people and enjoyed every conversation in the conference hall, hallways, and &lt;a href="http://en.wikipedia.org/wiki/Izakaya"&gt;Izakaya&lt;/a&gt; . All the topics discussed there were very thought provoking.&lt;/p&gt;

&lt;p&gt;The theme of this year's RubyKaigi ("Kaigi" means "Meeting")  was "Conflicts and Resolutions" and many talks covered various conflicts relating to the (especially Japanese) Ruby community like below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Japanese / English&lt;/li&gt;
&lt;li&gt;Committers / Users&lt;/li&gt;
&lt;li&gt;Before / After Rails&lt;/li&gt;
&lt;li&gt;Hobby / Enterprise&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The resolution to these conflicts was rather interesting.  &lt;a href="http://twitter.com/@takahashim"&gt;@takahashim&lt;/a&gt;, the chairman of the Japan Ruby Society, announced  next year's conference theme as the "Final RubyKaigi".  He proposed a big assignment to all of the attendees. "What would you do if you know that next RubyKaigi is the last?"&lt;/p&gt;

&lt;p&gt;As Jake mentioned, I suspect that many non Japanese attendees did not understand the whole context due to some language barriers.
During this post, I will try my best to explain the background of each conflict so that we can think together what we can do to the community and RubyKaigi 2011&lt;/p&gt;

&lt;h2&gt;Who am I ?&lt;/h2&gt;

&lt;p&gt;Before I start, here is a bit of introduction about myself which tells you why my experience made me a rare highbred between Japanese and non Japanese Rubyists.&lt;/p&gt;

&lt;p&gt;I was born and brought up in Japan. I worked in Tokyo as a DBA (DataBase Administrator) for 5 years, then moved to London 6 years ago. My encounter with Ruby is similar to most of you (non-Japanese Rubyists). I got to know Ruby through Ruby On Rails around 2006. As I learnt more about Rails, I learnt that the real power comes from its underlying language, Ruby.&lt;/p&gt;

&lt;p&gt;Even though I did not experience the pre-Rails era, I can access all the Japanese resources which were written before Rails stormed the Ruby community.
I also have been reading &lt;a href="http://jp.rubyist.net"&gt;Rubyist Magazine&lt;/a&gt;(ja) and kept dreaming about meeting these "legendary Japanese Ruby Hackers" one day. It was exciting not only to meet Matz, but also other Ruby committers and core community members. It was also a great honour to present as a speaker about "&lt;a href="http://rubykaigi.org/2010/en/events/6"&gt;Building Real Time Web&lt;/a&gt;" which was about doing WebSocket with (Javascript and ) Ruby, and a story about how we came up with &lt;a href="http://www.pusherapp.com"&gt;Pusher&lt;/a&gt;.&lt;/p&gt;

&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/j1VgynkdRRrnO-2BEy7giw?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_k-QRXbUACBU/TIGGU42pYII/AAAAAAAACD8/hAo6eXL4oNk/s400/R1001138.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;My speaker pass and Japanese fan with Matz cartoon &lt;a href="http://picasaweb.google.com/lh/sredir?uname=inouemak&amp;target=ALBUM&amp;id=5512834855732769345&amp;feat=embedwebsite"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;


&lt;h2&gt;Japanese / English&lt;/h2&gt;

&lt;p&gt;Before I headed to Japan, many people told me "wow, a ruby conference in Japan sounds interesting, but I don't speak Japanese, so wouldn't understand anything".
In short answer, that's fine. There were always at least 2 streams, one of which was in English (most English talks were done by some well known rubyists like &lt;a href="http://jp.rubyist.net"&gt;@wycats&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In long answer, you were able to enjoy even Japanese talks, thanks to a crowd sourcing real time translation effort led by &lt;a href="http://twitter.com/lchin"&gt;@lchin&lt;/a&gt; and &lt;a href="http://twitter.com/fdiary"&gt;@fdiary&lt;/a&gt;. There were 2 big IRC &amp;amp; Twitter streaming boards next to the presentation slides, which were created by  &lt;a href="http://twitter.com/lchin"&gt;@june29&lt;/a&gt; and used our own Pusher for the backend (the source code is &lt;a href="http://github.com/june29/rk2010stream"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The most surprising moment was when &lt;a href="http://twitter.com/yukihiro_matz"&gt;@yukihiro_matz&lt;/a&gt; appeared on stage as a English - Japanese interpreter during Rails 3 / Ruby 1.9.2 panel discussions. (this was the last minute replacement of Jeremy Kemper's keynote).&lt;/p&gt;

&lt;p&gt;I did not know that &lt;a href="http://twitter.com/tenderlove"&gt;@tenderlove&lt;/a&gt; (the author of Nokogiri) was the only person who has commit rights in both Ruby and Rails. During the panel discussion, &lt;a href="http://jp.rubyist.net"&gt;@wycats&lt;/a&gt; mentioned that there are communication problems between Japanese  and non Japanese Ruby developers. The mailing lists are divided into two (English/Japanese), and some of the most important discussions are done on the Japanese one.
They mentioned the past trial of translating all Japanese mailing lists into English, but it halted (due to lack of manpower). &lt;a href="http://twitter.com/yukihiro_matz"&gt;@yukihiro_matz&lt;/a&gt;  later tweeted his worry about merging the two into one English one, because he fully understands how hard it is for some Japanese committers to communicate difficult topics in English.&lt;/p&gt;

&lt;p&gt;Here is the panel discussion video.&lt;/p&gt;

&lt;script src="http://gmodules.com/ig/ifr?url=http://gimite.net/rails/iframe_gadget/xml%3Fscrolling%3Dtrue%26url%3Dhttp://player.vimeo.com/video/14548338&amp;amp;synd=open&amp;amp;w=400&amp;amp;h=300&amp;amp;title=&amp;amp;border=%23ffffff%7C3px%2C1px+solid+%23999999&amp;amp;output=js"&gt;&lt;/script&gt;


&lt;p&gt;It was hilarious to see &lt;a href="http://twitter.com/yukihiro_matz"&gt;@yukihiro_matz&lt;/a&gt; translating &lt;a href="http://jp.rubyist.net"&gt;@wycats&lt;/a&gt; 's complaint to a Japanese audience.&lt;/p&gt;

&lt;h2&gt;Committers / Users&lt;/h2&gt;

&lt;p&gt;One of the things you don't get at any other Ruby conferences is having the chance to meet Ruby core team members. I only knew a few names, so I was surprised to see that there were 26 of them on stage during Ruby 1.9.2 Q&amp;amp;A session.  According to &lt;a href="http://twitter.com/yugui"&gt;@yugui&lt;/a&gt;, the release manager of Ruby 1.9.2, the significant point of the release is spent (hence some delay) to pass all of the RubySpec (created by Rubinius team), so that other Ruby implementations can use the spec as a reference point to guarantee compatibility.&lt;/p&gt;

&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/PWeMZ_NrKvFo4nkUSN-m9A?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_k-QRXbUACBU/TIGGNEqg2tI/AAAAAAAACC0/x1jvwy1UFGg/s400/R1001105.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/lh/sredir?uname=inouemak&amp;target=ALBUM&amp;id=5512834855732769345&amp;feat=embedwebsite"&gt;rubykaigi2010&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;Besides the Q&amp;amp;A session, there were lots of other talks related to Ruby internals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/30"&gt;Keynote by Matz&lt;/a&gt;  = About Ruby 2.0 features&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/10"&gt;Best Imitation of Your Class&lt;/a&gt;  = Talk about Classbox which Matz mentioned at his keynote&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/7"&gt;We can make the GC X times slower than the original&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/84"&gt;How Did Yarv2llvm Fail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/85"&gt;AOT Compiler for Ruby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Unfortunately, they were all in Japanese (and the IRC translation logs don't seem to be available), but you can read their short summaries in English.&lt;/p&gt;

&lt;p&gt;One thing I realised during the conference is that RubyKaigi is actually a C developers' conference in disguise. I probably saw as much C code in the slides as Ruby code during the conference.
Apparently, there is a book called &lt;a href="http://www.loveruby.net/ja//rhg/"&gt;"Ruby Hacking Guide"&lt;/a&gt; and there are even "RHG book reading group"s in Japan. There is &lt;a href="http://rhg.rubyforge.org"&gt;an English version&lt;/a&gt;, but looks it is obsolete and not even complete.&lt;/p&gt;

&lt;p&gt;One of my personal concerns is the gap between these "Ruby committers" and normal Ruby users. I have seen a few of these committers assuming that most Rubyists are converts from C/Java, but that's not entirely true.&lt;/p&gt;

&lt;p&gt;I am a big fan of being a polyglot programmer, but learning C/Java as a Rubyist is a bit harder than going the opposite way, and I haven't seen lots of material targeting these. I hope someone knowledgeable in these languages gives a talk for "Introduction to C/C++/Java for Rubyists". Rubinius could fit into these gaps, but there were no related talks during the Kaigi.&lt;/p&gt;

&lt;h2&gt;Before / After Rails&lt;/h2&gt;

&lt;p&gt;For the majority of non Japanese Rubyists, it will be difficult to find someone around you who has never used Rails.&lt;/p&gt;

&lt;p&gt;However, this does not apply to many Japanese Rubyists because there were already other influential applications, such as tDiary, Hiki, qwik or Rabbit, most of which I've never heard before.&lt;/p&gt;

&lt;p&gt;"How to survive in a post rails world" was presented by &lt;a href="http://twitter.com/hsbt"&gt;@hsbt&lt;/a&gt;, one of the tDiary committers who recently started working in new company with a colleague who lives and breathes Rails and Github. Half of his slides are in Japanese, but you can still get some idea of what he talks about. He basically says that many of the "Before Rails" people still use sourceforge and raa, so suggests to put their work into Github.&lt;/p&gt;

&lt;div style="width:425px" id="__ss_5080879"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/hsbt/how-to-survive-in-post-rails-world" title="How to survive in post Rails&amp;#39; world."&gt;How to survive in post Rails&amp;#39; world.&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse5080879" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=20100829rubykaigi2010-100829071920-phpapp01&amp;stripped_title=how-to-survive-in-post-rails-world" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5080879" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=20100829rubykaigi2010-100829071920-phpapp01&amp;stripped_title=how-to-survive-in-post-rails-world" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/hsbt"&gt;Hiroshi SHIBATA&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;


&lt;p&gt;I was a bit surprised that some of the well known Japanese Rubyists don't actually use Github.
Since nowadays we assume that all the active projects are in Github, some of the "Before Rails" projects may be neglected just because they are not on Github. &lt;a href="http://twitter.com/hsbt"&gt;@hsbt&lt;/a&gt; stressed that it is now inevitable for Rubyists to live without such a system and suggested to move lots of good "Before Rails" heritage into some sort of social coding platform (NOTE: tDiary is still in active development and now they are hosted at github).&lt;/p&gt;

&lt;p&gt;Another related talk was done by &lt;a href="http://twitter.com/a_matsuda"&gt;@a_matsuda&lt;/a&gt; a week after the RubyKaigi at a conference called  &lt;a href="http://www.rubyworld-conf.org/en/"&gt;"Ruby World Conf"&lt;/a&gt; , organised in Matsue (Matz's home town).&lt;/p&gt;

&lt;p&gt;The title is "Ruby in the World, and Rails in Japan".&lt;/p&gt;

&lt;div style="width:425px" id="__ss_5159425"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/a_matsuda/rwc2010" title="Ruby in the World, and Rails in Japan"&gt;Ruby in the World, and Rails in Japan&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse5159425" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rwc2010-100908182603-phpapp01&amp;stripped_title=rwc2010" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5159425" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rwc2010-100908182603-phpapp01&amp;stripped_title=rwc2010" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/a_matsuda"&gt;Akira Matsuda&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;


&lt;p&gt;In his slides, he even says Japanese Ruby is a "Galapagos". The word "Galapagos" is often referred to Japanese mobile phone technologies. It evolved in a isolated place , so it is very unique (and often advanced), but has problems blending into the global standard.&lt;/p&gt;

&lt;p&gt;I recently saw some Japanese person tweeting that "Using Rails or Gems are very inconvenient because you can not install them on a shared hosting environment". This kind of conversation sounds so 2006 ~ 7 for us, because all Ruby/Rails people abroad just use a cheap VPS or Heroku for casual use.&lt;/p&gt;

&lt;h2&gt;Hobby / Enterprise&lt;/h2&gt;

&lt;p&gt;In the same slide, he also mentions that "Ruby super rockstars in japan tends not to work with Ruby but something LEGACY" . Apparently &lt;a href="http://twitter.com/tendorlove"&gt;@tendorlove&lt;/a&gt; asked him what these talented programmers do without Rails or Rubygems, and his answer was this.&lt;/p&gt;

&lt;div style="width:425px" id="__ss_5088127"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/mametter/ruby-esoteric-obfuscated-ruby-programming" title=" Ruby Ruby  - Esoteric, Obfuscated Ruby Programming"&gt; Ruby Ruby  - Esoteric, Obfuscated Ruby Programming&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse5088127" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rubykaigi2010-endoh-100830070932-phpapp01&amp;stripped_title=ruby-esoteric-obfuscated-ruby-programming" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5088127" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=rubykaigi2010-endoh-100830070932-phpapp01&amp;stripped_title=ruby-esoteric-obfuscated-ruby-programming" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/mametter"&gt;mametter&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;


&lt;p&gt;Playing Esoteric programming or code golf are actually a great way to brash up your programming skills, so doing it in itself is nothing wrong. However, it is sad if programmers with such high skills can not find Ruby related jobs when he/she wishes (NOTE: the above slide is just an example of a super-skilled Japanese Rubyist, and I don't know what he does for his day job).&lt;/p&gt;

&lt;p&gt;During one of the Kaigi events called "I am a Rubyist working abroad, any questions", I had a chance to ask all attendees how many people are actually using Ruby in their day job in Japan, and was surprised to see that less than half the people in the room raised hands. This is very similar to the situation during 2007 ~ 2008 in Europe (and @pat also said it was similar in Australia). Nowadays most Rubyists outside of Japan already work as full time Ruby (or Rails) programmers. This is rather unfortunate considering that Japan is where Ruby was born. I guess this is because Ruby has been seen as "hobby" language  for such a long time.&lt;/p&gt;

&lt;p&gt;There seemed to be strong interest to bring business to the ruby community during RubyKaigi. There were 3 sub events mostly focused on the business side.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/24"&gt;rake:money&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/25"&gt;Ruby Business Owner Kaigi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubykaigi.org/2010/en/events/100"&gt;Ruby powering 9 million dining tables (by CookPad)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I only attended the third event, organized by CookPad, and it was kind of interesting.
"Cookpad" is the most popular cooking recipe site  and 6th biggest Rails site in the world.&lt;/p&gt;

&lt;p&gt;The first half of the talk was about how to scale such a huge site, but the second half was about their working environment, and they stressed how much effort they were putting in to provide best working environment for developers (btw, they were recruiting both Japanese and non Japanese developers massively during the Kaigi). This is normal in America or Europe to attract talented developers, but it is very unusual in Japan, because the Japanese IT industry is often called 3K , "Kitsui"(Hard), "Kaerenai"(Can't go home), and "Kyuryo Yasui"(Low salary).&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Even though the RubyKaigi2010 was a big success, thanks to the hard work of all the volunteer staff and a combination of interesting talks covering a wide range of the Ruby divide, it revealed that the Japanese Ruby community is facing some growing pains.&lt;/p&gt;

&lt;p&gt;So, why is finishing RubyKaigi next year the solution?&lt;/p&gt;

&lt;p&gt;I will explain in more detail in the next post.&lt;/p&gt;
</description>
      <pubDate>Tue, 14 Sep 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/9/14/ruby-divide-at-rubykaigi-2010-and-what-can-you-do-as-a-rubyist-part-1</guid>
    </item>
    <item>
      <title>Adding awesome mini views to your web apps</title>
      <link>http://blog.new-bamboo.co.uk/2010/8/2/adding-awesome-mini-views-to-your-web-apps</link>
      <author>max@new-bamboo.co.uk (max)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/8/2/adding-awesome-mini-views-to-your-web-apps#disqus_thread</comments>
      <description>&lt;div style='float:left;margin:5px'&gt;&lt;img alt="Screen+shot+2010-08-02+at+17" src="http://blog.new-bamboo.co.uk/media/2010/08/02/09/50/14/845/Screen+shot+2010-08-02+at+17.35.32.jpg?m=resize&amp;amp;o[geometry]=300x200&amp;amp;s=e18c88ced8648383" /&gt;&lt;/div&gt; In a couple of our internal apps, we use a UI design paradigm that we affectionately call an "awesome bar". I really like these, and I think they make many types of applications much more useful and intuitive. While they have generally been hard to create in web apps, the introduction of canvas and inline SVG has made them a synch to put together. I see a lot of great examples of canvas and SVG that are absolutely mind-bending to look at, but very few examples which enhance the traditional applications and websites we use on a day-to-day basis. 


&lt;p&gt;I won't claim to have invented these, but I was reminded of how cool they are recently when I read this post: &lt;a href="http://blog.asmartbear.com/creativity-over-optimization.html"&gt;http://blog.asmartbear.com/creativity-over-optimization.html&lt;/a&gt;. I will give a brief explanation of what these are with some examples, why I think they rock, and some sample code.&lt;/p&gt;

&lt;h2&gt;What are awesome bars?&lt;/h2&gt;

&lt;p&gt;To give a quick introduction of what these are I have made a screencast of the awesome bar from our nifty scheduling application called Mandays. You will see that the horizontal bar at the bottom is a miniature representation of the grid at the top, and when you draw in it, the awesome bar at the bottom updates itself. You can then use the awesome bar to navigate your timeline.&lt;/p&gt;

&lt;p&gt;&lt;video controls&gt;
  &lt;source src="http://s3.amazonaws.com/bamboo-blog-assets/4718f2c8c7eda8b16ba1aed82bfa7567.mp4"  type="video/mp4"&gt;
  &lt;source src="http://s3.amazonaws.com/bamboo-blog-assets/304cdf006003d1692d4e833ef900f4fa.ogv"  type="video/ogg"&gt;
&lt;/video&gt;&lt;/p&gt;

&lt;h2&gt;What is so great about them?&lt;/h2&gt;

&lt;p&gt;Awesome bars allow you to view a piece of information at both a macro level and a micro level &lt;em&gt;simultaneously&lt;/em&gt;. With traditional scrollbars, there is always a percentage of a given "document" that is off the screen.&lt;/p&gt;

&lt;p&gt;However, as humans we seem to have the ability to put together a mental image of what a whole document looks like even though we view only a portion at a time. A commmenter on the blog post I linked to earlier says that:&lt;/p&gt;

&lt;blockquote&gt;
"It’s appealing because it *resembles* what it’s representing, whereas [a scrollbar] *symbolizes* that. It’s the difference between ‘bang’ and ‘the sound a gun makes when it’s shot’."
&lt;/blockquote&gt; 


&lt;p&gt;Awesome bars put the UI element in context. Searching for a specific spot in a document doesn't require scanning blindly through the whole thing via a small portal.&lt;/p&gt;

&lt;h2&gt;Types of interaction&lt;/h2&gt;

&lt;p&gt;In Mandays, the awesome bar allows interaction, and (controversially) replaces the native scrollbar. It simply provides you with a bit more context on where you are navigating too.&lt;/p&gt;

&lt;div style="float:right; margin: 5px"&gt;&lt;a href="http://truestoryapp.com"&gt;&lt;img alt="Truestoryapp" src="http://blog.new-bamboo.co.uk/media/2010/08/02/08/46/02/946/truestoryapp.jpg?m=resize&amp;amp;o[geometry]=300x200&amp;amp;s=cbe3ee935de65bdf" /&gt;&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;In our backlog management app called Truestory, the awesome bar can actually be interacted with directly. Though it has drag and drop of the main list, it was always a pain to take a story from the bottom to the top. With the awesome bar involved, we can drag stories to the approximate place in the backlog directly via the mini view.&lt;/p&gt;

&lt;p&gt;However, some minibars don't have any interactive elements, and are purely informational.&lt;/p&gt;

&lt;h2&gt;Building an awesome bar for a blog&lt;/h2&gt;

&lt;div style="float:left; margin: 5px;"&gt;&lt;a href="https://bamboo-blog-assets.s3.amazonaws.com/minibar.html"&gt;&lt;img alt="Screen+shot+2010-08-02+at+16" src="http://blog.new-bamboo.co.uk/media/2010/08/02/08/29/51/363/Screen+shot+2010-08-02+at+16.28.44.jpg?m=resize&amp;amp;o[geometry]=300x200&amp;amp;s=95fc848cb6c28990" /&gt;&lt;/a&gt;&lt;/div&gt; 


&lt;p&gt;As an example, I have built a very simple HTML application that demonstrates the minibar in use on a blog post with comments. The rationale for this is that it is often hard to tell from a scrollbar how long a given post is, and what percentage of the page is filled with comments. To cut to the chase, have a look at the demo &lt;a href="https://bamboo-blog-assets.s3.amazonaws.com/minibar.html"&gt;here&lt;/a&gt;, or poke about with the source &lt;a href="http://github.com/maxthelion/minibar"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a read-only awesome bar, and just shows which bit of the page you are viewing. The nice thing about it is that the concept is really simple, and therefore easy to tweak. I have used JQuery here to make it simpler, but you may want to replace those parts with your library of choice (things like offset and position of DOM elements are made easy by it).&lt;/p&gt;

&lt;h3&gt;Some canvas basics&lt;/h3&gt;

&lt;p&gt;I decided to use a canvas element for this example but SVG plus &lt;a href="http://raphaeljs.com/"&gt;raphael.js&lt;/a&gt;, would have been just as easy. There is a library to &lt;a href="http://excanvas.sourceforge.net/"&gt;make canvas work on IE&lt;/a&gt;, but I haven't bothered with it here.&lt;/p&gt;

&lt;p&gt;If you haven't used canvas before, all you really need to know for this example is that you can draw rectangles like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    ctx.fillRect(left_offset, top_offset, width, height); 
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The zero coordinate is the top left of the canvas by default, hence the left_offset and top_offset.&lt;/p&gt;

&lt;h3&gt;Layout&lt;/h3&gt;

&lt;p&gt;First I created a simple CSS layout with the blog post and comments on the left, and a &lt;code&gt;position:fixed&lt;/code&gt; minibar on the right.&lt;/p&gt;

&lt;h3&gt;Encapsulating the minibar code&lt;/h3&gt;

&lt;p&gt;Next comes a small MiniBar function that we can create with the necessary configuration.  When it is initialised, it sets the #minibar div and the canvas inside it to the height of the window (this would need to be bound to window resize in a proper application).&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    var resize_canvas = function(){
      canvas.height =  $(window).height();
    };
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Small potential gotcha is that canvas elements behave like images, and if you set the dimensions with CSS, the content of the canvas is scaled as well. What we are doing here is more like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;canvas height="PIXELS" &amp;gt;&amp;lt;/canvas&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Adopting a simpl[istic] scale factor&lt;/h3&gt;

&lt;p&gt;Once the canvas is set to the right height, we set about drawing the elements onto it. This is really easy, and just involves multiplying the height of the elements in the DOM with a scale factor derived from the ratio between the entire document and the viewable area.&lt;/p&gt;

&lt;p&gt;The scale factor looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    var scale_factor = function(){
      return $(window).height() / holder_elem.height();
    }
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;using the height of the body is probably more reliable if you have a header and footer etc.&lt;/p&gt;

&lt;h3&gt;Drawing some stuff&lt;/h3&gt;

&lt;p&gt;The first thing we draw is the yellow block of the main article. We get the height with JQuery, and apply the scale factor.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    var draw_content = function(){
      var   content_height = $('#content').height();
      ctx.fillStyle = "rgb(255,255,0)";  
      ctx.fillRect (0, 0, 100, content_height * scale_factor() );
    }
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;We set the colour manually, but could derive that from the element itself.&lt;/p&gt;

&lt;p&gt;Drawing the comments is a bit more involved because they have top offset, and I decided to highlight comments the author has made:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    var draw_comments = function(){
      $(".comment").each(function(){
        if (this.className.indexOf('author') != -1){
          ctx.fillStyle = "rgb(255, 100, 100)"; 
        } else {
          ctx.fillStyle = "rgb(200,200,200)";  
        }
        ctx.fillRect(0, $(this).offset().top * scale_factor(), 100, $(this).height() * scale_factor() );
      })
    }
&lt;/code&gt;&lt;/pre&gt;


&lt;h3&gt;Adding a viewer portal&lt;/h3&gt;

&lt;p&gt;We can use the same scale factor to place a box on the canvas to represent the part of the page we are viewing. The height of the box is the height of the window multiplied by the scale factor, and the distance from the top of the canvas is the scroll offset of the window.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    var draw_viewer = function(){
      ctx.fillStyle = "rgba(255,255,255,0.5)";  
      ctx.strokeRect(0, $(window).scrollTop() * scale_factor(), 100, $(window).height() * scale_factor() );
    }
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;We need the viewer to move when we scroll, so we bind to the window scroll method:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
    $(window).scroll(function(){ draw() })
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Because we have the view on the canvas itself, we have to clear the canvas first, and then redraw everything. This isn't very expensive though.&lt;/p&gt;

&lt;h2&gt;Taking the example forward&lt;/h2&gt;

&lt;p&gt;To make this more interactive, you could turn the viewer into a DOM element which has &lt;code&gt;position:absolute&lt;/code&gt;. This allows it to be dragged, which can in turn affect the scroll position of the entire page. However, this is relatively easy to do, and can be an exercise for anyone interested.&lt;/p&gt;
</description>
      <pubDate>Mon, 02 Aug 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/8/2/adding-awesome-mini-views-to-your-web-apps</guid>
    </item>
    <item>
      <title>HTML5-powered Ajax file uploads</title>
      <link>http://blog.new-bamboo.co.uk/2010/7/30/html5-powered-ajax-file-uploads</link>
      <author>pablo@new-bamboo.co.uk (pablo)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/7/30/html5-powered-ajax-file-uploads#disqus_thread</comments>
      <description>&lt;h2&gt;Introduction&lt;/h2&gt;




&lt;p&gt;File uploads have traditionally had very bad usability on the web. The standard solution was uploading files as part of a form, leaving the user to just wait until the process was done. We could offer barely any feedback of what was going on.&lt;/p&gt;




&lt;p&gt;Several options appeared to make the process more bearable for the user. Some alternatives were client-based, such as using some Flash-powered element like &lt;a href="http://swfupload.org/"&gt;SWFUpload&lt;/a&gt;. Other alternatives laid more on the side of the server, like leveraging Nginx's &lt;a href="http://blog.new-bamboo.co.uk/2007/11/23/upload-progress-with-nginx"&gt;mod_uploadprogress&lt;/a&gt; with a pinch of Ajax. However, there was still the question of why there was no solution that avoided proprietary technology, required minimal hassle OR was free of far-fetched hacks.&lt;/p&gt;




&lt;p&gt;Until now.&lt;/p&gt;




&lt;p&gt;An important part of &lt;a href="http://www.pandastream.com"&gt;Panda&lt;/a&gt; (new blog &lt;a href="http://blog.pandastream.com"&gt;here&lt;/a&gt; btw!), our video encoding service, is file uploads. Our users need to upload large videos and we offer an HTTP interface and a Javascript widget to do exactly that. However, our widget is based in Flash, and we would always rather offer solutions based on webstandards. Therefore, we set out to see how the upcoming HTML5 specification could help us. Specifically the features contained in two specs: the &lt;a href="http://dev.w3.org/2006/webapi/FileAPI/"&gt;File API&lt;/a&gt; and &lt;a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/"&gt;XMLHttpRequest Level 2&lt;/a&gt;. I'll explain here how to make effective use of them. If you're interested in seeing the end result checkout the &lt;a href="http://github.com/newbamboo/panda_uploader/tree/html5"&gt;panda_uploader plugin on Github&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;Compatibility and detection&lt;/h2&gt;




&lt;p&gt;At the time of writing, this technique only works in the latest &lt;strong&gt;Webkit&lt;/strong&gt; and &lt;strong&gt;Gecko&lt;/strong&gt; browsers. Therefore you will still need to fall back to other methods if you wish to support Internet Explorer, Opera or others.&lt;/p&gt;




&lt;p&gt;The best way to know if the client browser supports this feature (or any other feature for that matter) is &lt;a href="http://www.quirksmode.org/js/support.html"&gt;object detection&lt;/a&gt;. In short, use Javascript to check whether elements of the API exist or not. In this case, the code is the following:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;function supportAjaxUploadWithProgress() {
    return supportFileAPI() &amp;amp;&amp;amp; supportAjaxUploadProgressEvents();

    function supportFileAPI() {
        var fi = document.createElement('INPUT');
        fi.type = 'file';
        return 'files' in fi;
    };

    function supportAjaxUploadProgressEvents() {
        var xhr = new XMLHttpRequest();
        return !! (xhr &amp;amp;&amp;amp; ('upload' in xhr) &amp;amp;&amp;amp; ('onprogress' in xhr.upload));
    };
}&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;If the function &lt;code&gt;supportAjaxUploadWithProgress()&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;, you are good to go. If not, you'll have to revert to a different upload technique.&lt;/p&gt;




&lt;h2&gt;Simplest Ajax upload&lt;/h2&gt;




&lt;p&gt;The frontend code is pretty simple initially. The spec establishes that file input fields have a &lt;code&gt;files&lt;/code&gt; property that gives us access to some attributes of the file, like so:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;&amp;lt;input id="the-file" name="file" type="file" /&amp;gt;

var fileInput = document.getElementById('the-file');
console.log(fileInput.files); // A FileList with all selected files&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;Note that &lt;code&gt;fileInput.files&lt;/code&gt; is a &lt;code&gt;FileList&lt;/code&gt; because the HTML5 spec allows for file inputs to select multiple files. Let's keep it simple though, assuming only one file will be selected. The general case is easy to infer from there.&lt;/p&gt;




&lt;p&gt;Once the user selects a file, the list will be filled up with actual file objects:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;var file = fileInput.files[0];
console.log(file.fileName); // "my-holiday-photo.jpg"
console.log(file.size); // 1282632
console.log(file.type); // image/jpeg&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;You can use this file object as an argument to the &lt;code&gt;XMLHttpRequest.send()&lt;/code&gt; call, to send the file asynchronously over to the server:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload/uri', true);
xhr.send(file); // Simple!&lt;/code&gt;&lt;/pre&gt;




&lt;h2&gt;Feedback events&lt;/h2&gt;




&lt;p&gt;But we still don't have any feedback on how the upload process is going. Let's make the example complete with a simple progress indicator. This will show the progress on the debug console:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;var fileInput = document.getElementById('the-file');
var file = fileInput.files[0];

var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', onprogressHandler, false);
xhr.open('POST', '/upload/uri', true);
xhr.send(file); // Simple!

function onprogressHandler(evt) {
    var percent = event.loaded/event.total*100;
    console.log('Upload progress: ' + percent + '%');
}&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;Please note that the event is not set on the &lt;code&gt;xhr&lt;/code&gt; object itself, but on &lt;strong&gt;&lt;code&gt;xhr.upload&lt;/code&gt;&lt;/strong&gt;. If you get this wrong, you'll be notified of the progress of &lt;strong&gt;the response&lt;/strong&gt; from the server after the request is complete, rather than the upload preceding it.&lt;/p&gt;




&lt;p&gt;Additionally, there are some other events that can be useful:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;code&gt;xhr.upload.onloadstart&lt;/code&gt;: the upload begins&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xhr.upload.onload&lt;/code&gt;: the upload ends successfully&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xhr.upload.onerror&lt;/code&gt;: the upload ends in error&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xhr.upload.onabort&lt;/code&gt;: the upload has been aborted by the user&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;And of course we'll have to use our old friend &lt;code&gt;xhr.onreadystaterequest&lt;/code&gt; to read the response from the server.&lt;/p&gt;




&lt;h2&gt;Reading the raw data&lt;/h2&gt;




&lt;p&gt;There's still one problem though, which is not evident from just reading the code above. When a file is uploaded using this method, the browser will send a request whose content will be just the file contents as raw data. This means that your server-side framework won't be able to make it available to you as per normal.&lt;/p&gt;




&lt;p&gt;For example, in PHP normally you would use the &lt;code&gt;$_FILES&lt;/code&gt; global variable; in Rails the &lt;code&gt;params&lt;/code&gt; method; in Django &lt;code&gt;request.POST&lt;/code&gt; dictionary. None of these would work with this technique. It also means you won't be given the name of the file, which is normally available using the mentioned accessors.&lt;/p&gt;




&lt;p&gt;But don't worry, both things can be solved easily. First, the file name: you can pass it to the server on the very same upload request by putting it in a request header. For example:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;xhr.setRequestHeader("X-File-Name", file.name);&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;If you do this before calling &lt;code&gt;send()&lt;/code&gt;, you will be able to read the file name form the headers on the server side. Popular methods include:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;PHP: &lt;code&gt;$_SERVER['HTTP_X_FILE_NAME']&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Rails: &lt;code&gt;request.env['HTTP_X_FILE_NAME']&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Django: &lt;code&gt;request.META['HTTP_X_FILE_NAME']&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Now there's the matter of how to read the file itself. Again, this will depend on your server side technology:&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;PHP: &lt;code&gt;file_get_contents("php://input")&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Rails: &lt;code&gt;request.env['rack.input']&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Django: &lt;code&gt;request.raw_post_data&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Being a good netizen&lt;/h2&gt;




&lt;p&gt;Another small detail is that, by default, the request is sent without a mimetype. Depending on your setup, this may not be a problem for you, but it's recommended that you set it. This is so third party applications can interoperate better with your code. And makes you a good netizen!.&lt;/p&gt;




&lt;p&gt;For this, there's only one line you need to add to the code above:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;xhr.setRequestHeader("Content-Type", "application/octet-stream");&lt;/code&gt;&lt;/pre&gt;




&lt;h2&gt;Firefox!&lt;/h2&gt;




&lt;div style="width: 90%; padding: 0 1em; margin: 0 auto; border: 1px solid #888;"&gt;
  &lt;p&gt;This section was added as an update on 21/Oct/2010&lt;/p&gt;
&lt;/div&gt;




&lt;p&gt;Hang on, there's one last thing! Firefox implements the above from version 3.5, but there are a couple of pitfalls you have to be aware of.&lt;/p&gt;




&lt;h3&gt;Set events BEFORE opening the XmlHttp connection&lt;/h3&gt;




&lt;p&gt;Specially the "progress" event; otherwise Firefox won't fire it. This means that you have to do as follows:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;xhr.upload.addEventListener('progress', onprogressHandler, false);
xhr.open('POST', '/upload/uri', true);&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;Instead of the following, "wrong" code (for Firefox anyway!):&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;xhr.open('POST', '/upload/uri', true);
xhr.upload.addEventListener('progress', onprogressHandler, false);&lt;/code&gt;&lt;/pre&gt;




&lt;h3&gt;On Firefox 3.5, two names change&lt;/h3&gt;




&lt;p&gt;On Firefox 3.5, instead of &lt;code&gt;xhr.send()&lt;/code&gt; you have to do &lt;code&gt;xhr.sendAsBinary()&lt;/code&gt;. Also, instead of &lt;code&gt;file.name&lt;/code&gt;, the name of the file is stored in &lt;code&gt;file.fileName&lt;/code&gt;. Fortunately, Firefox 3.6 adopts the W3C convention and these changes don't apply.&lt;/p&gt;




&lt;p&gt;You can still support both conventions in you code. For the file name do the following:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;filename = file.name || file.fileName;&lt;/code&gt;&lt;/pre&gt;




&lt;p&gt;And for the &lt;code&gt;send()&lt;/code&gt; call, do is:&lt;/p&gt;




&lt;pre&gt;&lt;code class="javascript"&gt;if ('getAsBinary' in file) {
  // Firefox 3.5
  xhr.sendAsBinary(file.getAsBinary());
}
else {
  // W3C-blessed interface
  xhr.send(file);
}&lt;/code&gt;&lt;/pre&gt;




&lt;h2&gt;A complete example&lt;/h2&gt;




&lt;p&gt;We have published a complete example of how this works. It's on GitHub and you are invited to play with it:&lt;/p&gt;




&lt;p&gt;&lt;a href="http://github.com/newbamboo/example-html5-upload"&gt;http://github.com/newbamboo/example-html5-upload&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This uses Sinatra with a piece of Rack middleware that we have also made available separately, called &lt;a href="http://github.com/newbamboo/rack-raw-upload"&gt;Rack::RawUpload&lt;/a&gt;. This middleware will convert a raw upload into a normal request. This way, you won't need to fiddle around with the file name and its contents.&lt;/p&gt;

</description>
      <pubDate>Fri, 30 Jul 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/7/30/html5-powered-ajax-file-uploads</guid>
    </item>
    <item>
      <title>Custom event emitters in Javascript</title>
      <link>http://blog.new-bamboo.co.uk/2010/7/14/custom-event-emitters-in-javascript</link>
      <author>ismael@new-bamboo.co.uk (ismael)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/7/14/custom-event-emitters-in-javascript#disqus_thread</comments>
      <description>&lt;p&gt;&lt;object width="552" height="343"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=13181356&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=01AAEA&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=13181356&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=01AAEA&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="550" height="343"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Websockets-based activity dashboard app. Read on to know more about the ideas behind it&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;In this post I'll attempt to summarise some patterns for designing event-based Javascript applications extracted from our projects and previous blog posts on the subject. I'll end with an overview of the techniques described and how they play together in a real-world application. This post is a follow-up from a presentation at the &lt;a href="http://www.meetup.com/javascript-3/calendar/13838645/"&gt;London Javascript User Group&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Background&lt;/h2&gt;

&lt;p&gt;We've blogged about &lt;a href="http://blog.new-bamboo.co.uk/2010/1/26/why-your-javascript-apps-need-more-structure"&gt;Javascript patterns for complex applications&lt;/a&gt; before. If you're short on time, that post describes the way we lay out our client-side apps here at New Bamboo. It's an MVC-like setup where we have Model objects doing the persistence and data binding, and View objects listening to state change in those models via the observer patterns and custom events. If you haven't, I strongly recommend you read that post before this one.&lt;/p&gt;

&lt;p&gt;The key component of this approach is using custom events to decouple the communication between layers. This is a simple View example:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
var UserPane = function(event_source, $container){
  
  function update(event, user){
    $container.append('&amp;lt;li&amp;gt:'+user.name+'&amp;lt;/li&amp;gt:')
  }
  
  $(event_source).bind('user_added', update)
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;And you would use it like:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
new UserPane(document, $('ul#user_list'));

// Wrap DOM events and re-trigger with useful data using jQuery
$('#users input:radio').change(function(evt){
  $(document).trigger('user_added', {name: $(this).val()});
});
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The example defines a View class that knows in which DOM element to render content ($container) and binds itself to the 'user_added' event triggered on the document object by other layers in the application.&lt;/p&gt;

&lt;p&gt;We're passing the &lt;code&gt;document&lt;/code&gt; element as the source of events, but you're free to swap it by anything that you can bind to and trigger events from. It doesn't even need to be a DOM element, and this is where OO and evented programming starts to look less counter-intuitive than one might have thought: you can build your own Event Emitters and model your domain around them.&lt;/p&gt;

&lt;h2&gt;Event Emitters In the wild&lt;/h2&gt;

&lt;p&gt;That is exactly what libraries such as Node.js are doing with an &lt;a href="http://nodejs.org/api.html#eventemitter-14"&gt;EventEmitter&lt;/a&gt; class you can extend from. The following is an object that emits a "tick" event with a random number every 5 seconds.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
var EventEmitter = require('events').EventEmitter,
    puts = require('sys').puts;

var Ticker = function( interval ){
  var self = this, 
      nextTick = function(){
    self.emit('tick', Math.random(1000));
    setTimeout(nextTick, interval);
  }

  nextTick();
};

// Extend from EventEmitter 'addListener' and 'emit' methods
Ticker.prototype = new EventEmitter;

// A ticker instance with an interval of 5 seconds
var ticktock = new Ticker( 5000 );

// Bind an event handler to the 'tick' event
ticktock.addListener('tick', function( number ) {
  puts('number emitted: '+ number);
});
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The nice thing about this is that objects interacting with the Ticker instance only need to bind themselves to events emitted by it. There's no need for public methods apart from addListener (or $.bind in our previous jQuery example).&lt;/p&gt;

&lt;h2&gt;How we use Event Emitters&lt;/h2&gt;

&lt;p&gt;Back in the browser side of things, you can build event emitters that represent objects in your domain and trigger events when their status changes. Then other parts of the application can observe those events and react accordingly. A nice abstraction of this pattern is &lt;a href="http://blog.new-bamboo.co.uk/2010/3/7/the-js-model-layer"&gt;js-model&lt;/a&gt;, an ORM-like Javascript library we developed to model domain objects with extra server persistence baked-in.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
// Js-model example
var Post = Model("post")

Post.bind("add", function(new_post) {
  addObjectIntoUI(new_post)
})

// This will trigger the 'add' event on the Post object, 
// executing any handlers observing it.
var post = new Post({ foo: "bar" })
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;More info on js-model on &lt;a href="http://benpickles.github.com/js-model/"&gt;its documentation page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is also the approach that we've taken with our &lt;a href="http://pusherapp.com"&gt;Pusher&lt;/a&gt; websockets service. With it you can bind your local objects to events coming from the server in a completely transparent way.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
var server = new Pusher('you app key', 'some channel');

server.bind('user_added', function(user){
  $('ul#user_list').append('&amp;lt;li&amp;gt:'+user.name+'&amp;lt;/li&amp;gt:')
})
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;And of course you would build your own objects to do the binding and keep your main app clean and expressive.&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
new UserPane( server, $('ul#user_list') );
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;I talk about how this is done in &lt;a href="http://blog.new-bamboo.co.uk/2010/2/10/json-event-based-convention-websockets"&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Do it yourself&lt;/h2&gt;

&lt;p&gt;Because Pusher.js is framework-agnostic, we don't use jQuery's event-binding API. Instead, Pusher implements its own &lt;code&gt;bind&lt;/code&gt; method. But once you're using this pattern in one part of your app there's no reason you couldn't use it for the rest of your domain objects. The only thing they need to do is implement binding and triggering of events. &lt;a href="http://gist.github.com/464257"&gt;This&lt;/a&gt; is a simple abstract prototype you can use in your own objects. This is the Ticker example again using that snippet:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
/* Periodically send out dummy events 
--------------------------------------------*/
var Ticker = function( interval ){
  var self = this, 
      nextTick = function(){
    self.trigger('tick', Math.random(1000));
    setTimeout(nextTick, interval);
  }

  nextTick();
};

// Extend from AbstractEventsDispatcher 'bind' and 'trigger' methods
Ticker.prototype = new AbstractEventsDispatcher;

var ticktock = new Ticker( 5000 );

ticktock.bind('tick', function( number ) {
  puts('number emitted: '+ number);
});
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The only reason I've changed 'addListener' to 'bind' and 'emit' to 'trigger' is to keep it familiar for jQuery users.&lt;/p&gt;

&lt;p&gt;What's important here is that once you model your objects around this minimal event-centric interface ('bind' and 'trigger') it makes little difference what your event emitter objects actually do -and how they do it. You app can be fully evented while retaining the best bits of object orientation such as polymorphism and inheritance.&lt;/p&gt;

&lt;h2&gt;A working application&lt;/h2&gt;

&lt;p&gt;I've recently built an activity dashboard app that uses Pusher when deployed to production but a mocked, in-browser event emitter object in development to simulate a stream of events coming from the server. My View objects are oblivious to the origin of those events and just focus on binding to them and rendering them onscreen as they come. You can see it working on the video above.&lt;/p&gt;

&lt;p&gt;It starts by defining a series of self-contained widget objects. I then loop through them and instantiate each with the same instance of an event emitter -in this case Pusher or a mock server implementing &lt;code&gt;bind&lt;/code&gt; for custom events.&lt;/p&gt;

&lt;p&gt;This is the basic code:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
var server = new MockServer() // or new Pusher('app_key', 'channel_name'), or your own event emitter

// Instantiate widgets
for(widget in Widgets.available){
  new widget( server );
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;And this is a simplified widget that listens to 'closed_order' events and plays a sound using HTML5's audio tag:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
Widgets.available.soundAlert = function( server ){
  
  // add audio files to document
  var $audio = $('&amp;lt;audio src="/audio/alert.mp3" preload="true" /&amp;gt;').appendTo('body');

  function play(data){
    $audio.load().play();
  }
  
  // bind to events you want to alert
  server.bind( 'order_closed', play )
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;I can add as many widgets as I want (and even remove them, pause them and inspect them in run-time), with no dependencies between them. Because they bind themselves to events they're interested in, each one is completely &lt;a href="http://en.wikipedia.org/wiki/Orthogonality#Computer_science"&gt;orthogonal&lt;/a&gt; to the system.&lt;/p&gt;

&lt;p&gt;Finally, this is an example of the MockServer object I use to replace Pusher for development purposes:&lt;/p&gt;

&lt;pre&gt;&lt;code class="javascript"&gt;
/* Periodically send out dummy events 
--------------------------------------------*/
var MockServer = function(){

  var self = this, interval, event_names = ['order_closed', 'order_cancelled', 'order_shipped'];

  function randomEvent(){
    var event_name = event_names[Math.round(Math.random(2)*2)];
    
    self.trigger(event_name, {
      info: 'Mock order, 3 products',
      total: Math.random(1000)
    });
  }

  interval = setInterval(randomEvent, 2000);
};
// Extend event-binding interface
MockServer.prototype = new AbstractEventsDispatcher;
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Wrap up&lt;/h2&gt;

&lt;p&gt;This illustrates the general architecture that permeates all recent Javascript projects that we've developed. In future articles we'll talk about techniques and specific problems in more detail.&lt;/p&gt;

&lt;p&gt;Even though I've included an abstract class that I used for the examples on this page, the emphasis is on the patterns more than on particular implementations and APIs.&lt;/p&gt;
</description>
      <pubDate>Wed, 14 Jul 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/7/14/custom-event-emitters-in-javascript</guid>
    </item>
    <item>
      <title>Living on the edge of the WebSocket protocol</title>
      <link>http://blog.new-bamboo.co.uk/2010/6/7/living-on-the-edge-of-the-websocket-protocol</link>
      <author>makoto@new-bamboo.co.uk (makoto)</author>
      <comments>http://blog.new-bamboo.co.uk/2010/6/7/living-on-the-edge-of-the-websocket-protocol#disqus_thread</comments>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Getting Info&lt;/li&gt;
&lt;li&gt;So What’s Changed?&lt;/li&gt;
&lt;li&gt;What about version incompatibility?&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Hello. It's been a while since &lt;a href="http://blog.new-bamboo.co.uk/2009/12/30/brain-dump-of-real-time-web-rtw-and-websocket"&gt;I last blogged about WebSocket&lt;/a&gt;. It's been exciting that &lt;a href="http://github.com/miksago/node-websocket-server"&gt;many&lt;/a&gt; &lt;a href="http://m.onkey.org/2010/1/15/websockets-made-easy-with-cramp"&gt;new&lt;/a&gt; &lt;a href="http://socket.io"&gt;frameworks&lt;/a&gt; and services are out including our own &lt;a href="http://www.pusherapp.com/"&gt;Pusher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Having said that, we have to be aware that the protocol is still actively being changed.&lt;/p&gt;

&lt;p&gt;Just a few weeks ago, there was an important announcement at &lt;a href="http://blog.chromium.org/2010/06/websocket-protocol-updated.html"&gt;Chromium blog&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Developers should be aware that starting from WebKit nightly build r59903 and Chrome 6.0.414.0 (r47952), the client will talk to a server using -76 version of the protocol, so it will fail to open WebSocket connections with a WebSocket server based on draft-hixie-thewebsocketprotocol-75. Since -75 version of the protocol is obsoleted and no longer supported in future version of browsers, to support new clients you need to update the server implementation. (Note that Chrome 5 uses -75 version of protocol).&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;And I find this is a very bold statement.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The WebSocket protocol is still actively being changed. Until there is more consensus, we will continue to update our implementation to follow the latest draft of specification, rather than worrying about breaking changes.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This means that you (or the framework maintainer) must be aware of these changes and must act quickly to keep up to date.&lt;/p&gt;

&lt;p&gt;Luckily, there are already people who analysed these new changes and blogged about it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://axod.blogspot.com/2010/06/websocket-gets-update-and-it-breaks.html"&gt;WebSocket Gets update and it breaks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webreflection.blogspot.com/2010/06/websocket-handshake-76-simplified.html"&gt;Websocket handshake 76 simplified&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Martyn and I spent last Friday applying these changes to &lt;a href="http://github.com/igrigorik/em-websocket"&gt;em-websocket&lt;/a&gt; (which we use for &lt;a href="http://www.pusherapp.com"&gt;Pusher&lt;/a&gt;) and they're now available as of version 0.1.1. We're already seeing ~ 2% of clients connecting to pusherapp using the new protocol.&lt;/p&gt;

&lt;p&gt;I'd like to share our findings and hope that other framework/library authors will do the same. The last thing I want to hear is "WebSocket keeps changing and most frameworks/libraries/services are broken". That will not increase the general adoption of WebSocket.&lt;/p&gt;

&lt;p&gt;I also hope that this is technically interesting enough for people who want to know under the hood of WebSocket implementation, but not necessarily write a  framework. (NOTE: If you are interested in just using WebSocket in various languages, then you can use Pusher via &lt;a href="http://www.pusherapp.com/docs/libraries"&gt;various language bindings&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;Getting Info&lt;/h2&gt;

&lt;p&gt;First things first, you need to know about the fact that the change did happen, so here are a little bit of tips.&lt;/p&gt;

&lt;h3&gt;Follow Twitter&lt;/h3&gt;

&lt;p&gt;If you really want to stay ahead of the game, you should either follow @chromiumbuild or search "websocket" twitter keyword.
There are lots of noises, but you know about the change very soon. Twitter was buzzing a week before the update was announced on the chromium blog.&lt;/p&gt;

&lt;h3&gt;Use Chrome dev channel&lt;/h3&gt;

&lt;p&gt;Instead of using &lt;a href="http://www.google.com/chrome"&gt;normal chrome&lt;/a&gt;, you can use the &lt;a href="http://www.chromium.org/getting-involved/dev-channel"&gt;dev channel&lt;/a&gt; version.&lt;/p&gt;

&lt;p&gt;There is Stable/Beta/Dev channel and they get updated according to the &lt;a href="http://www.chromium.org/developers/calendar"&gt;schedule&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dev channel is updated every week and you are automatically updated as soon as you restart your browser, so you need to be aware of the consequences.&lt;/p&gt;

&lt;p&gt;You can also use &lt;a href="http://nightly.webkit.org/"&gt;Webkit Nightly build&lt;/a&gt;, but not sure where I can find the schedule of Safari update. Does anyone have an idea?&lt;/p&gt;

&lt;h3&gt;Reading the draft&lt;/h3&gt;

&lt;p&gt;Reading &lt;a href="http://www.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt"&gt;the entire draft &lt;/a&gt; (over 50 pages) is a pain. However, you can read just section 1 and 5 (18 pages together) to understand the change on the server side.&lt;/p&gt;

&lt;h3&gt;Referring to other implementations.&lt;/h3&gt;

&lt;p&gt;WebSocket implementation in Google Go and Pywebsocket are implemented by a Google engineer (Fumitoshi Ukai).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/pywebsocket"&gt;Pywebsocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/go/source/detail?spec=svn3f986a031b92a1b3cdaa3c3fceff19692ff21170&amp;amp;r=ef24ea09359c372ec0943aae5f42b3ff337e4713"&gt;GoogleGo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I highly recommend reading pywwebsocket source codes. It is an apache module, but &lt;code&gt;standalone.py&lt;/code&gt; can run on its own without configuring apache.&lt;/p&gt;

&lt;p&gt;When we were writing draft76 patch for Ruby server (em-websocket), we actually used "echo_client.py" to hit the Ruby server for testing.
This is much easier than checking via 2 browsers. pywebsocket is actually used to test Chromium browser implementation, so it will be highly likely kept up to date.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[example]$ ./echo_client.py -p 8080 --draft75
Send: Hello
Recv: Hello
Send: 日本
Recv: 日本

[example]$ ./echo_client.py -p 8080
Send: Hello
Recv: Hello
Send: 日本
Recv: 日本
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The detailed tutorial of how to install pywebsocket is &lt;a href="http://diffract.me/2009/12/websockets-tutorialexample-with-pywebsocket"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please note that you actually need to build and install it even when you use &lt;code&gt;standalone.py&lt;/code&gt;. If you don't do install, you will get the following error message.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[src]$ echo $PYTHONPATH 
/Users/makoto/src/pywebsocket-read-only/src 
[mod_pywebsocket]$ sudo python ./standalone.py -p 9999 
Traceback (most recent call last): 
  File "./standalone.py", line 474, in &amp;lt;module&amp;gt; 
    _main() 
  File "./standalone.py", line 361, in _main 
    default=handshake.DEFAULT_WEB_SOCKET_PORT, 
AttributeError: 'module' object has no attribute 
'DEFAULT_WEB_SOCKET_PORT'
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;If you understand Japanese&lt;/h3&gt;

&lt;p&gt;html5-developers-jp google group is very active and looks Google engineers are also following. I posted &lt;a href="http://groups.google.com/group/html5-developers-jp/browse_thread/thread/81e3aebcb7944af6"&gt;some questions&lt;/a&gt; prior to start implementing the upgrade support, and got lots of useful feedbacks (Yes, you can also show off your google translation skills by posting in Japanese, but don't forget that they do some funny translations).&lt;/p&gt;

&lt;h2&gt;So What's Changed?&lt;/h2&gt;

&lt;p&gt;This section goes into much more technical detail so may wish to skip it.&lt;/p&gt;

&lt;p&gt;The initial upgrade request was changed to include some extra handshake protocol, to make sure that it will fail fast if WebSocket request is received by non WebSocket server (especially normal HTTP server, unless the HTTP server opt in to handle this handshake protocol explicitly).&lt;/p&gt;

&lt;p&gt;It also added better way to handle closing phase which I will explain later.&lt;/p&gt;

&lt;h3&gt;Opening Handshake&lt;/h3&gt;

&lt;h4&gt;From Client to Server&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75#section-1.2"&gt;Old&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
WebSocket-Protocol: sample
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.2"&gt;New&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
Sec-WebSocket-Protocol: sample
Upgrade: WebSocket
Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
Origin: http://example.com

^n:ds[4U
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here are the list of changes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name("Web Socket" =&gt; "WebSocket")&lt;/li&gt;
&lt;li&gt;"Sec-" prefix&lt;/li&gt;
&lt;li&gt;New fields (Sec-WebSocket-Key1/2)&lt;/li&gt;
&lt;li&gt;Some random characters at the body of request/response (^n:ds[4U and 8jKS'y:G*Co,Wxa-)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;#2 &lt;code&gt;Sec-&lt;/code&gt; prefix, the explanation is described at &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.6"&gt;Security model&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;It is similarly intended to fail to establish a connection when data from other protocols, especially HTTP, is sent to a WebSocket server, for example as might happen if an HTML |form| were submitted to a WebSocket server. This is primarily achieved by requiring that the server prove that it read the handshake, which it can only do if the handshake contains the appropriate parts which themselves can only be sent by a WebSocket handshake; in particular, fields starting with |Sec-| cannot be set by an attacker from a Web browser, even when using |XMLHttpRequest|.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; I am not sure why &lt;code&gt;Sec-&lt;/code&gt; cannot be set from a Web browser (unless &lt;code&gt;Sec-&lt;/code&gt; is a reserved word for HTTP protocol). If you know any info, please comment.&lt;/p&gt;

&lt;p&gt;#3 and #4 are used for opening handshake and I will explain in next section.&lt;/p&gt;

&lt;h4&gt;From Server to Client&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75#section-1.2"&gt;Old&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.2"&gt;New&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Location: ws://example.com/demo
Sec-WebSocket-Protocol: sample

8jKS'y:G*Co,Wxa-
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The opening handshake protocol at server side is described in &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-5.2"&gt;13 steps&lt;/a&gt; (The client side handshake protocol has &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-4.1"&gt;45 steps!!&lt;/a&gt;, and this is another reason I use pywebsocket for client testing rather than creating my own client).&lt;/p&gt;

&lt;p&gt;The description steps are understandable, but quite hard to read, so it's better to read the source code of other implementations.
I refer to the pywebsocket version and &lt;a href="http://webreflection.blogspot.com/2010/06/websocket-handshake-76-simplified.html"&gt;php version&lt;/a&gt; described by &lt;a href="http://twitter.com/WebReflection"&gt;@WebReflection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are the steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract numbers at Key1(eg: 4 @1  46546xW%0l 1 5)  and concatenate them&lt;/li&gt;
&lt;li&gt;Count number of spaces at Key1&lt;/li&gt;
&lt;li&gt;Devide #1 by #2&lt;/li&gt;
&lt;li&gt;Change the format of #3 into "big-&lt;a href="http://en.wikipedia.org/wiki/Endianness"&gt;endian&lt;/a&gt; 32 bit integer"&lt;/li&gt;
&lt;li&gt;Repeat #1 by #4 for Key2(eg: 12998 5 Y3 1  .P00)&lt;/li&gt;
&lt;li&gt;Concatenate #4, #5, and the body(eg: &lt;code&gt;^n:ds[4U&lt;/code&gt;) of the request&lt;/li&gt;
&lt;li&gt;Digest the result in MD5 format&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Did you get it? Probably better to read the code. Here is the Ruby implementation.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def solve_challange(first, second, third)
  # Refer to 5.2 4-9 of the draft 76
  sum = (extract_nums(first) / count_spaces(first)).to_a.pack("N*") +
        (extract_nums(second) / count_spaces(second)).to_a.pack("N*") +
        third
  Digest::MD5.digest(sum)
end

def extract_nums(string)
  string.scan(/[0-9]/).join.to_i
end

def count_spaces(string)
  string.scan(/ /).size        
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Closing handshake&lt;/h3&gt;

&lt;p&gt;In earlier drafts, you could &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75#section-4.3"&gt;terminate connection&lt;/a&gt;, but there was no proper protocol to acknowledge the closing phase between client and server. This lack of "Orderly close" was criticised &lt;a href="http://blogs.webtide.com/gregw/entry/how_to_improve_websocket"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To solve this problem, &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.4"&gt;Closing handshake&lt;/a&gt; is specified so that both client and server can send a 0xFF frame with length 0x00 to begin the closing handshake.&lt;/p&gt;

&lt;h2&gt;What about version incompatibility?&lt;/h2&gt;

&lt;p&gt;The biggest disruption of the new draft is incompatibility with the prior version. Unfortunately, the draft version number is not specified at the HTTP request header (and probably won't be included until the draft get stabilised). For now it's easy enough to get by. You either&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A: Try with draft76, catch exception, and fallback with draft75&lt;/li&gt;
&lt;li&gt;B: Identify the version by checking newly added fields.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Pywebsocket uses A&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Handshaker(object):
    """This class performs Web Socket handshake."""

    def __init__(self, request, dispatcher, allowDraft75=False, strict=False):
        """Construct an instance.

        Handshaker will add attributes such as ws_resource in performing
        handshake.
        """

        if allowDraft75:
            self._fallbackHandshaker = draft75.Handshaker(
                request, dispatcher, strict)

    def do_handshake(self):
        try:
            self._handshaker.do_handshake()
        except HandshakeError, e:
            if self._fallbackHandshaker:
                self._logger.warning('fallback to old protocol')
                self._fallbackHandshaker.do_handshake()
                return
            raise e
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We (em-websocket) use B&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  version = request['Sec-WebSocket-Key1'] ? 76 : 75

  case version
  when 75
    Handler75.new(request, response, debug)
  when 76
    Handler76.new(request, response, debug)
  else
    raise "Must not happen"
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;The updated WebSocket protocol changes the opening and closing handshakes. For now we can support draft 75 and 76, though the implementation is a bit hacky. Our changes are tested against the pywebsocket script (which is used by both Chromium developers to test their own implementations), and against Chrome and Webkit development builds, but please let us know if we are missing anything.&lt;/p&gt;
</description>
      <pubDate>Tue, 15 Jun 2010 00:00:00 +0000</pubDate>
      <guid>http://blog.new-bamboo.co.uk/2010/6/7/living-on-the-edge-of-the-websocket-protocol</guid>
    </item>
  </channel>
</rss>

