<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Alice, Bob, and Mallory: Category JavaScript</title>
    <link>http://www.alicebobandmallory.com/articles/category/javascript</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>metasyntactics</description>
    <item>
      <title>Sudoku solver in CoffeeScript</title>
      <description>&lt;p&gt;&lt;a href="http://jashkenas.github.com/coffee-script/"&gt;CoffeeScript&lt;/a&gt; is inspired by Ruby and Python but what's most peculiar with it is that it compiles to JavaScript. The generated JavaScript isn't all that bad and it even passes &lt;a href="http://www.javascriptlint.com/"&gt;JavaScript lint&lt;/a&gt; without warnings.&lt;/p&gt;

&lt;p&gt;"Underneath all of those embarrassing braces and semicolons, JavaScript has always had a gorgeous object model at its heart." - Jeremy Ashkenas&lt;/p&gt;

&lt;p&gt;About a week ago I stumbled on the very clever &lt;a href="http://norvig.com/sudoku.html"&gt;Sudoku solver by Peter Norvig&lt;/a&gt;. I have nothing (or at least not much) against Python but I pretty soon checked out the Ruby translations of the solver. I then &lt;a href="https://gist.github.com/914326"&gt;refactored one&lt;/a&gt; of the solutions to get a chance to get to know the algorithm better.&lt;/p&gt;

&lt;p&gt;Now that I finally &lt;a href="http://jashkenas.github.com/coffee-script/#installation"&gt;installed CoffeeScript&lt;/a&gt; the Sudoku solver came to mind. I dived in head first and got in trouble pretty soon. It turns out that Array Comprehensions in CoffeeScript differs some from the List Comprehensions in Python.&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#080;font-weight:bold"&gt;def&lt;/span&gt; &lt;span style="color:#06B;font-weight:bold"&gt;cross&lt;/span&gt;(&lt;span style="color:#036;font-weight:bold"&gt;A&lt;/span&gt;, &lt;span style="color:#036;font-weight:bold"&gt;B&lt;/span&gt;):&lt;tt&gt;
&lt;/tt&gt;       &lt;span style="background-color:#fff0f0;color:#D20"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style=""&gt;Cross product of elements in A and elements in B.&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;       &lt;span style="color:#080;font-weight:bold"&gt;return&lt;/span&gt; [a+b &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; a &lt;span style="color:#080;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#036;font-weight:bold"&gt;A&lt;/span&gt; &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; b &lt;span style="color:#080;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#036;font-weight:bold"&gt;B&lt;/span&gt;]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;returns an one-dimensional array if you call it with two arrays (or strings).&lt;/p&gt;

&lt;p&gt;But in CoffeeScript &lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;cross = (&lt;span style="color:#036;font-weight:bold"&gt;A&lt;/span&gt;, &lt;span style="color:#036;font-weight:bold"&gt;B&lt;/span&gt;) -&amp;gt; (a+b &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; a &lt;span style="color:#080;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#036;font-weight:bold"&gt;A&lt;/span&gt; &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; b &lt;span style="color:#080;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#036;font-weight:bold"&gt;B&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;returns a two-dimensional array.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jashkenas/coffee-script/issues/1191"&gt;The jury&lt;/a&gt; is still out on &lt;a href="http://stackoverflow.com/questions/5685449/nested-array-comprehensions-in-coffeescript"&gt;if this is intended&lt;/a&gt; or not but either way the &lt;a href="http://en.wikipedia.org/wiki/List_comprehension"&gt;array  comprehensions&lt;/a&gt; in CoffeeScript are still very useful.&lt;/p&gt;

&lt;div style="background-color: #F0F0F0"&gt;
&lt;font color="red"&gt;EDIT 2011-06-02&lt;/font&gt;&lt;br&gt;
It's been decided that this is by design. The issue has been closed.
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 For the &lt;code&gt;cross&lt;/code&gt;-function I ended up with&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;cross = (&lt;span style="color:#036;font-weight:bold"&gt;A&lt;/span&gt;, &lt;span style="color:#036;font-weight:bold"&gt;B&lt;/span&gt;) -&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  results = []&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; a &lt;span style="color:#080;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#036;font-weight:bold"&gt;A&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; b &lt;span style="color:#080;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#036;font-weight:bold"&gt;B&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      results.push a + b&lt;tt&gt;
&lt;/tt&gt;  results&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;div style="background-color: #F0F0F0"&gt;
&lt;font color="red"&gt;EDIT 2011-06-02&lt;/font&gt;&lt;br&gt;
Using `map` I could have got much closer to the Ruby version.
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;cross = (cols, rows) -&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  [].concat (cols.map (x) -&amp;gt; rows.map (y) -&amp;gt; y+x)...&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

I'm still more of a map/reduce guy than a list comprehension ninja.
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
You can find the &lt;a href="https://gist.github.com/927782"&gt;CoffeScript Sudoku solver as a Gist&lt;/a&gt;. &lt;strike&gt;Compile it with&lt;br/&gt;
&lt;code&gt;coffee -c sudoku.coffee&lt;/code&gt;&lt;br/&gt;
and then run it with&lt;br/&gt;
&lt;code&gt;node sudoku.js&lt;/code&gt;&lt;/strike&gt;&lt;/p&gt;

&lt;p&gt;I don't know how I missed it but as Trevor pointed out below all you have to do is&lt;br/&gt;
&lt;code&gt;coffee sudoku.coffee&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;
    1 2 3 4 5 6 7 8 9
  |------+-----+-----|
A | 4 8 3|9 2 1|6 5 7|
B | 9 6 7|3 4 5|8 2 1|
C | 2 5 1|8 7 6|4 9 3|
  |------+-----+-----|
D | 5 4 8|1 3 2|9 7 6|
E | 7 2 9|5 6 4|1 3 8|
F | 1 3 6|7 9 8|2 4 5|
  |------+-----+-----|
G | 3 7 2|6 8 9|5 1 4|
H | 8 1 4|2 5 3|7 6 9|
I | 6 9 5|4 1 7|3 8 2|
  |------+-----+-----|
&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://alicebobandmallory.com/sudoku.js.html"&gt;Here's&lt;/a&gt; the generated &lt;a href="http://alicebobandmallory.com/sudoku.js.html"&gt;sudoku.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the only CoffeeScript I've ever written but I already like it (more than JavaScript). Please correct me if I strayed from the CoffeeScript way. &lt;/p&gt;</description>
      <pubDate>Tue, 19 Apr 2011 15:46:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:12b7c916-c5eb-4510-ac0a-0efcfd241225</guid>
      <author>Jonas Elfström</author>
      <link>http://www.alicebobandmallory.com/articles/2011/04/19/sudoku-solver-in-coffeescript</link>
      <category>Ruby</category>
      <category>JavaScript</category>
    </item>
    <item>
      <title>Encrypt images in JavaScript</title>
      <description>&lt;p&gt;In browsers that supports the HTML5 &lt;a href="http://en.wikipedia.org/wiki/Canvas_element"&gt;canvas &lt;/a&gt; it's possible to read the raw image data. I figured that this makes it possible to encrypt images on the client. Why would one ever want to encrypt images client-side? One use case could be to send images to a server that only those who know the password can decrypt (host-proof hosting).&lt;/p&gt;

&lt;p&gt;I used &lt;a href="http://code.google.com/p/crypto-js/"&gt;Crypto-JS&lt;/a&gt; to encrypt with &lt;a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard"&gt;AES&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Rabbit_%28cipher%29"&gt;Rabbit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First I get the &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspixelarray"&gt;CanvasPixelArray&lt;/a&gt; from the &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata"&gt;ImageData&lt;/a&gt; object.&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; ctx = document.getElementById(&lt;span style="color:#04D"&gt;'l&lt;/span&gt;eif&lt;span style="color:#04D"&gt;')&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;                  .getContext(&lt;span style="color:#04D"&gt;'2&lt;/span&gt;d&lt;span style="color:#04D"&gt;')&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; imgd = ctx.getImageData(&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;,&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;,width,height);&lt;tt&gt;
&lt;/tt&gt;&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; pixelArray = imgd.data;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;br/&gt;
The pixel array has four bytes for each pixel as &lt;a href="http://en.wikipedia.org/wiki/RGBA_color_space"&gt;RGBA&lt;/a&gt; but Crypto-JS encrypts a string, not an array. At first I used &lt;code&gt;.join()&lt;/code&gt; and &lt;code&gt;.split(",")&lt;/code&gt; to get from array to string and back. It was slow and the string got much longer than it had to be. Actually four times longer. To save even more space I decided to discard the alpha channel.  
&lt;br/&gt;
&lt;br/&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#080;font-weight:bold"&gt;function&lt;/span&gt; canvasArrToString(a) {&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; s=&lt;span style="background-color:#fff0f0;color:#D20"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#666"&gt;// Removes alpha to save space.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; i=&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;; i&amp;lt;pix.length; i+=&lt;span style="color:#00D;font-weight:bold"&gt;4&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;    s+=(String.fromCharCode(pix[i])&lt;tt&gt;
&lt;/tt&gt;        + String.fromCharCode(pix[i+&lt;span style="color:#00D;font-weight:bold"&gt;1&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;        + String.fromCharCode(pix[i+&lt;span style="color:#00D;font-weight:bold"&gt;2&lt;/span&gt;]));&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;return&lt;/span&gt; s;&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;br/&gt;
That string is what I then encrypt. I sticked to `+=` after reading &lt;a href="http://www.sitepen.com/blog/2008/05/09/string-performance-an-analysis/"&gt;String Performance an Analysis&lt;/a&gt;.  
&lt;br/&gt;
&lt;br/&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; encrypted = Crypto.Rabbit.encrypt(imageString, password);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;br/&gt;
I used a small 160x120 pixels image. With four bytes for each pixels that gives 76800 bytes. Even though I stripped the alpha channel the encrypted image still takes up 124680 bytes, 1.62 times bigger. Using  `.join()` it was 384736 bytes, 5 times bigger. One cause for it still being larger than the original image is that Crypto-JS returns a &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;Base64&lt;/a&gt; encoded string and that adds something like 37%.  
&lt;br&gt;
&lt;br&gt;
Before I could write it back to the canvas I had to convert it to an array again.  
&lt;br/&gt;
&lt;br/&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#080;font-weight:bold"&gt;function&lt;/span&gt; canvasStringToArr(s) {&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; arr=[];&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; i=&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;; i&amp;lt;s.length; i+=&lt;span style="color:#00D;font-weight:bold"&gt;3&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; j=&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;; j&amp;lt;&lt;span style="color:#00D;font-weight:bold"&gt;3&lt;/span&gt;; j++) {&lt;tt&gt;
&lt;/tt&gt;      arr.push(s.substring(i+j,i+j+&lt;span style="color:#00D;font-weight:bold"&gt;1&lt;/span&gt;).charCodeAt());&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    arr.push(&lt;span style="color:#00D;font-weight:bold"&gt;255&lt;/span&gt;); &lt;span style="color:#666"&gt;// Hardcodes alpha to 255.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;return&lt;/span&gt; arr;&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;br/&gt;
Decryption is simple.
&lt;br/&gt;
&lt;br/&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; arr=canvasStringToArr(&lt;tt&gt;
&lt;/tt&gt;              Crypto.Rabbit.decrypt(encryptedString, password));&lt;tt&gt;
&lt;/tt&gt;imgd.data=arr;&lt;tt&gt;
&lt;/tt&gt;ctx.putImageData(imgd,&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;,&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt;);&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;br/&gt;

Tested in Firefox, Google Chrome, WebKit3.1 (Android 2.2), iOS 4.1, and a very recent release of Opera.  
&lt;br/&gt;
&lt;br/&gt;
&lt;table style="width: 366pt; border-collapse: collapse;" width="487" border="0" cellpadding="0" cellspacing="0"&gt;

&lt;colgroup&gt;&lt;col style="width: 160pt;" width="213"&gt;&lt;col style="width: 62pt;" width="82"&gt;&lt;col style="width: 48pt;" width="64" span="3"&gt;&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border: 0.5pt solid windowtext; background-color: transparent; width: 160pt; min-height: 12.75pt;" width="213" height="17"&gt;
&lt;strong&gt;&lt;font face="Arial" size="2"&gt;Browser / Action in milliseconds&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: windowtext; background-color: transparent; width: 62pt;" width="82"&gt;
&lt;strong&gt;&lt;font face="Arial" size="2"&gt;Enc. Rabbit&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: windowtext; background-color: transparent; width: 48pt;" width="64"&gt;
&lt;strong&gt;&lt;font face="Arial" size="2"&gt;Dec. Rabbit&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: windowtext; background-color: transparent; width: 48pt;" width="64"&gt;
&lt;strong&gt;&lt;font face="Arial" size="2"&gt;Enc. AES&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: windowtext; background-color: transparent; width: 48pt;" width="64"&gt;
&lt;strong&gt;&lt;font face="Arial" size="2"&gt;Dec. AES&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Google Chrome 6.0.472.62 C2D@1.86GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;136&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;130&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;236&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;222&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Opera 10.63 P4HT@3GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;246&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;252&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;438&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;437&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Google Chrome 6.0.472.63 P4HT@3GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;280&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;648&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;303&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;547&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Firefox 3.6.10 Phenom II X4 945@3GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;494&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;321&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1876&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1745&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Firefox 3.6.10 i5@3,5GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;366&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;193&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1639&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1410&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Firefox 3.6.10 C2D@1.86GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;760&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;367&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2417&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1983&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Firefox 3.6.10 P4HT@3GHz&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;880&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;440&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;4000&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;3500&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;Nokia N900 Chrome&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1764&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;1975&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2509&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2508&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;WebKit 3.1 (HTC Desire)&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2000&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2200&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;3300&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;3400&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;iPhone 3GS iOS 4.1&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2130&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;2071&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;7198&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;7131&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;N900 Firefox Mobile&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;3411&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;3508&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;19308&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;19466&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;N900 native (MicroB)&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;4681&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;4300&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;24560&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;20973&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;tr style="min-height: 12.75pt;" height="17"&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt; border-style: none solid solid; border-color: windowtext; background-color: transparent; min-height: 12.75pt;" height="17"&gt;
&lt;font face="Arial" size="2"&gt;X10 Mini Pro, Android 1.6&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;7464&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;" align="right"&gt;
&lt;font face="Arial" size="2"&gt;7747&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;"&gt;
&lt;font face="Arial" size="2"&gt;timeout&lt;/font&gt;&lt;/td&gt;
&lt;td style="border-width: medium 0.5pt 0.5pt medium; border-style: none solid solid none; border-color: windowtext; background-color: transparent;"&gt;
&lt;font face="Arial" size="2"&gt;timeout&lt;/font&gt;&lt;/td&gt;

&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&amp;nbsp;  &lt;/p&gt;

&lt;p&gt;A &lt;a href="http://plea.se/me/cryptimage.html"&gt;demo&lt;/a&gt; can be found &lt;a href="http://plea.se/me/cryptimage.html"&gt;here&lt;/a&gt;.
&lt;br/&gt;&lt;br/&gt;
&lt;font color="red"&gt;EDIT 2010-10-17&lt;/font&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Warning&lt;/strong&gt; I've noticed that the encrypted strings aren't compatible between browsers. At least not in between Google Chrome and Firefox. I don't know why.&lt;/p&gt;

&lt;p&gt;I also tried to add deflate/inflate and that compresses my test image to a third of the raw size and in Google Chrome it also halved the execution time. In Firefox Rabbit got about 50% slower and AES about 50% faster with deflate/inflate.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://plea.se/me/cryptimage2.html"&gt;Here's a demo of this&lt;/a&gt;. 
&lt;br&gt;&lt;br&gt;
&lt;font color="red"&gt;EDIT 2010-10-21&lt;/font&gt;&lt;br&gt;&lt;br&gt;
Added a preprocessing filter of the raw image data inspired by &lt;a href="http://www.w3.org/TR/PNG-Filters.html"&gt;PNG&lt;/a&gt; type 1 sub filter. Presented my idea to Fredrik and he returned a formula. Thanks!
&lt;br&gt;
The result wasn't what I had hoped for, a measly 6% smaller. I also tried to save the image as real PNG and that one is 20480 bytes.
20480*1.37=28057 bytes (Base64 overhead) and my homemade format is 38336 bytes. Not a fantastic result but not that horrible either.
&lt;br&gt;&lt;br&gt;
&lt;a href="http://plea.se/me/cryptimage3.html"&gt;Here's a demo of this&lt;/a&gt;. &lt;/p&gt;</description>
      <pubDate>Thu, 14 Oct 2010 23:40:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:1cb3eec8-d3a1-48f2-bb32-024bbf4cbe96</guid>
      <author>Jonas Elfström</author>
      <link>http://www.alicebobandmallory.com/articles/2010/10/14/encrypt-images-in-javascript</link>
      <category>Cryptography</category>
      <category>JavaScript</category>
    </item>
    <item>
      <title>JavaScript hash table keys</title>
      <description>&lt;p&gt;In JavaScript you can add properties to objects dynamically. You can access those properties both by &lt;code&gt;object.foo&lt;/code&gt; and &lt;code&gt;object['foo']&lt;/code&gt;. The later is commonly used to use JavaScript objects as &lt;a href="http://en.wikipedia.org/wiki/Hash_table"&gt;hash tables&lt;/a&gt; (associative arrays).&lt;/p&gt;

&lt;p&gt;While implementing &lt;a href="http://stackoverflow.com/questions/2380019/generate-8-unique-random-numbers-between-1-and-100/2380513#2380513"&gt;a simplistic unique random number generator&lt;/a&gt; I happened to use &lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/keys"&gt;keys(obj)&lt;/a&gt;. Unfortunately &lt;code&gt;keys(obj)&lt;/code&gt; is part of &lt;a href="http://en.wikipedia.org/wiki/ECMAScript"&gt;ECMAScript&lt;/a&gt; 5. See chapter 15.2.3.14 in &lt;a href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf"&gt;ECMA-262&lt;/a&gt;. The web browsers of today mostly implements ECMAScript 3.&lt;/p&gt;

&lt;p&gt;Here's an implementation of &lt;code&gt;keys(obj)&lt;/code&gt; for ECMAScript 3 browsers (tested in Google Chrome, IE8 and Firefox 3.5). If the browser already has a keys function then nothing will be done.&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (typeof keys == &lt;span style="background-color:#fff0f0;color:#D20"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style=""&gt;undefined&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;tt&gt;
&lt;/tt&gt;{ &lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; keys = &lt;span style="color:#080;font-weight:bold"&gt;function&lt;/span&gt;(ob) &lt;tt&gt;
&lt;/tt&gt;  {&lt;tt&gt;
&lt;/tt&gt;    props=[];&lt;tt&gt;
&lt;/tt&gt;    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (k in ob) &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (ob.hasOwnProperty(k)) props.push(k);&lt;tt&gt;
&lt;/tt&gt;    &lt;span style="color:#080;font-weight:bold"&gt;return&lt;/span&gt; props;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;&lt;br/&gt;
The simplistic unique random number generator looks like this&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span style="color:#080;font-weight:bold"&gt;function&lt;/span&gt; uniqueRndNumbers(min, max, quantity) {&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#339;font-weight:bold"&gt;var&lt;/span&gt; ht={}, i=quantity;&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;while&lt;/span&gt; ( i&amp;gt;&lt;span style="color:#00D;font-weight:bold"&gt;0&lt;/span&gt; || keys(ht).length&amp;lt;quantity) &lt;tt&gt;
&lt;/tt&gt;    ht[Math.floor(Math.random()*(max-min+&lt;span style="color:#00D;font-weight:bold"&gt;1&lt;/span&gt;))+min]=i--;&lt;tt&gt;
&lt;/tt&gt;  &lt;span style="color:#080;font-weight:bold"&gt;return&lt;/span&gt; keys(ht);&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;&lt;br/&gt;
This function has not undergone any serious testing. Also if the &lt;code&gt;quantity&lt;/code&gt; is more than a fraction of &lt;code&gt;(max-min)&lt;/code&gt; then another algorithm like the &lt;a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle"&gt;Fisher–Yates shuffle&lt;/a&gt; might be a better choice.&lt;/p&gt;</description>
      <pubDate>Fri, 05 Mar 2010 17:42:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:27e04911-d089-4122-8a96-ad529a9b8b3b</guid>
      <author>Jonas Elfström</author>
      <link>http://www.alicebobandmallory.com/articles/2010/03/05/javascript-hash-table-keys</link>
      <category>JavaScript</category>
    </item>
  </channel>
</rss>

