<?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 xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>John Resig</title>
	
	<link>http://ejohn.org</link>
	<description>Blog, Projects, and Links</description>
	<lastBuildDate>Sat, 25 May 2013 22:00:54 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/JohnResig" /><feedburner:info uri="johnresig" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>42.381929</geo:lat><geo:long>-71.099084</geo:long><image><link>http://ejohn.org/</link><url>http://ejohn.org/files/jeresig-wordpress-sm.jpg</url><title>John Resig (ejohn.org)</title></image><feedburner:emailServiceId>JohnResig</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item>
		<title>Asm.js: The JavaScript Compile Target</title>
		<link>http://ejohn.org/blog/asmjs-javascript-compile-target/</link>
		<comments>http://ejohn.org/blog/asmjs-javascript-compile-target/#comments</comments>
		<pubDate>Wed, 03 Apr 2013 15:18:50 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5914</guid>
		<description><![CDATA[Like many developers I&#8217;ve been excited by the promise of Asm.js. Reading the recent news that Asm.js is now in Firefox nightly is what got my interest going. There&#8217;s also been a massive surge in interest after Mozilla and Epic announced (mirror) that they had ported Unreal Engine 3 to Asm.js &#8211; and that it [...]]]></description>
				<content:encoded><![CDATA[<p>Like many developers I&#8217;ve been excited by the promise of <a href="http://asmjs.org/">Asm.js</a>. Reading the recent news that <a href="https://blog.mozilla.org/luke/2013/03/21/asm-js-in-firefox-nightly/">Asm.js is now in Firefox nightly</a> is what got my interest going. There&#8217;s also been a massive surge in interest after <a href="https://blog.mozilla.org/blog/2013/03/27/mozilla-is-unlocking-the-power-of-the-web-as-a-platform-for-gaming/">Mozilla and Epic announced</a> (<a href="http://techcrunch.com/2013/03/27/mozilla-and-epic-games-bring-unreal-engine-3-to-the-web-no-plugin-needed/">mirror</a>) that they had ported Unreal Engine 3 to Asm.js &#8211; and that it ran really well.</p>
<p><center><iframe width="560" height="315" src="http://www.youtube.com/embed/XsyogXtyU9o" frameborder="0" allowfullscreen></iframe></center></p>
<p>Getting a C++ game engine running in JavaScript, using WebGL for rendering, is a massive feat and is largely due to the toolchain that Mozilla has developed to make it all possible.</p>
<p>Since the release of the Unreal Engine 3 port to Asm.js I&#8217;ve been watching the response on Twitter, blogs, and elsewhere and while some developers are grasping the interesting confluence of open technologies that&#8217;ve made this advancement happen I&#8217;ve also seen a lot of confusion: Is Asm.js a plugin? Does Asm.js make my regular JavaScript fast? Does this work in all browsers? I feel that Asm.js, and related technologies, are incredibly important and I want to try and explain the technology so that developers know what&#8217;s happened and how they will benefit. In addition to my brief exploration into this subject I&#8217;ve also asked <a href="http://calculist.org/">David Herman</a> (Senior Researcher at Mozilla Research) a number of questions regarding Asm.js and how all the pieces fit together.</p>
<h2>What is Asm.js?</h2>
<p>In order to understand <a href="http://asmjs.org/">Asm.js</a> and where it fits into the browser you need to know where it came from and why it exists.</p>
<p>Asm.js comes from a new category of JavaScript application: C/C++ applications that&#8217;ve been compiled into JavaScript. It&#8217;s a whole new genre of JavaScript application that&#8217;s been spawned by <a href="https://github.com/kripken/emscripten">Mozilla&#8217;s Emscripten project</a>.</p>
<p>Emscripten takes in C/C++ code, passes it through LLVM, and converts the LLVM-generated bytecode into JavaScript (specifically, Asm.js, a subset of JavaScript).</p>
<p><center><a href="http://i.imgur.com/1yoy1Fa.png"><img src="http://i.imgur.com/1yoy1Fal.png" style="max-width:560px;" /></a></center></p>
<p>If the compiled Asm.js code is doing some rendering then it is most likely being handled by WebGL (and rendered using OpenGL). In this way the entire pipeline is technically making use of JavaScript and the browser but is almost entirely skirting the actual, normal, code execution and rendering path that JavaScript-in-a-webpage takes.</p>
<p>Asm.js is a subset of JavaScript that is heavily restricted in what it can do and how it can operate. This is done so that the compiled Asm.js code can run as fast as possible making as few assumptions as it can, converting the Asm.js code directly into assembly. It&#8217;s important to note that Asm.js is just JavaScript &#8211; there is no special browser plugin or feature needed in order to make it work (although a browser that is able to detect and optimize Asm.js code will certainly run faster). It&#8217;s a specialized subset of JavaScript that&#8217;s optimized for performance, especially for this use case of applications compiled to JavaScript.</p>
<p>The best way to understand how Asm.js works, and its limitations, is to look at some Asm.js-compiled code. Let&#8217;s look at a function extracted from a real-world Asm.js-compiled module (from the <a href="https://developer.mozilla.org/en-US/demos/detail/bananabread">BananaBread demo</a>). I formatted this code so that it&#8217;d be a little bit saner to digest &#8211; it&#8217;s normally just a giant blob of heavily-minimized JavaScript:</p>
<style>.gist-data { max-height: 400px; }</style>
<p><script src="https://gist.github.com/jeresig/5293608.js"></script></p>
<p>Technically this is JavaScript code but we can already see that this looks nothing like most DOM-using JavaScript that we normally see. A few things we can notice just by looking at the code:</p>
<ul>
<li>This particular code only deals with numbers. In fact this is the case of all Asm.js code. Asm.js is only capable of handling a selection of different <a href="http://asmjs.org/spec/latest/#value-types">number types</a> and no other data structure (this includes strings, booleans, or objects).</li>
<li>All external data is stored and referenced from a single object, called the heap. Essentially this heap is a massive array (intended to be a <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays">typed array</a>, which is highly optimized for performance). All data is stored within this array &#8211; effectively replacing global variables, data structures, closures, and any other forms of data storage.</li>
<li>When accessing and setting variables the results are consistently coerced into a specific type. For example <code>f = e | 0;</code> sets the variable <code>f</code> to equal the value of <code>e</code> but it also ensures that the result will be an integer (<code>| 0</code> does this, converting an value into an integer). We also see this happening with floats &#8211; note the use of <code>0.0</code> and <code>g[...] = +(...);</code>.</li>
<li>Looking at the values coming in and out of the data structures it appears as if the data structured represented by the variable <code>c</code> is an <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/Int32Array">Int32Array</a> (storing 32-bit integers, the values are always converted from or to an integer using <code>| 0</code>) and <code>g</code> is a <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/Float32Array">Float32Array</a> (storing 32-bit floats, the values always converted to a float by wrapping the value with <code>+(...)</code>).</li>
</ul>
<p>By doing this the result is highly optimized and can be converted directly from this Asm.js syntax directly into assembly without having to interpret it, as one would normally have to do with JavaScript. It effectively shaves off a whole bunch of things that can make a dynamic language, like JavaScript, slow: Like the need for garbage collection and dynamic types.</p>
<p>As an example of some more-explanatory Asm.js code let&#8217;s take a look at an example from the <a href="http://asmjs.org/spec/latest/">Asm.js specification</a>:</p>
<pre><code>function DiagModule(stdlib, foreign, heap) {
    "use asm";

    // Variable Declarations
    var sqrt = stdlib.Math.sqrt;

    // Function Declarations
    function square(x) {
        x = +x;
        return +(x*x);
    }

    function diag(x, y) {
        x = +x;
        y = +y;
        return +sqrt(square(x) + square(y));
    }

    return { diag: diag };
}
</code></pre>
<p>Looking at this module it seems downright understandable! Looking at this code we can better understand the structure of an Asm.js module. A module is contained within a function and starts with the <code>"use asm";</code> directive at the top. This gives the interpreter the hint that everything inside the function should be handled as Asm.js and be compiled to assembly directly.</p>
<p>Note, at the top of the function, the three arguments: <code>stdlib</code>, <code>foreign</code>, and <code>heap</code>. The <code>stdlib</code> object contains references to a number of <a href="http://asmjs.org/spec/latest/#standard-library">built-in math functions</a>. <code>foreign</code> provides access to custom user-defined functionality (such as drawing a shape in WebGL). And finally <code>heap</code> gives you an <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/ArrayBuffer">ArrayBuffer</a> which can be viewed through a <a href="http://asmjs.org/spec/latest/#heap-view-types">number of different lenses</a>, such as Int32Array and Float32Array.</p>
<p>The rest of the module is broken up into three parts: variable declarations, function declarations, and finally an object exporting the functions to expose to the user.</p>
<p>The export is an especially important point to understand as it allows all of the code within the module to be handled as Asm.js but still be made usable to other, normal, JavaScript code. Thus you could, theoretically, have some code that looks like the following, using the above <code>DiagModule</code> code:</p>
<pre><code>document.body.onclick = function() {
    function DiagModule(stdlib){"use asm"; ... return { ... };}

    var diag = DiagModule({ Math: Math }).diag;
    alert(diag(10, 100));
};
</code></pre>
<p>This would result in an Asm.js DiagModule that&#8217;s handled special by the JavaScript interpreter but still made available to other JavaScript code (thus we could still access it and use it within a click handler, for example).</p>
<h2>What is the performance like?</h2>
<p>Right now the only implementation that exists is in <a href="https://blog.mozilla.org/luke/2013/03/21/asm-js-in-firefox-nightly/">nightly versions of Firefox</a> (and even then, for only a couple platforms). That being said early numbers show the performance being <em>really, really</em> good. For complex applications (such as the above games) performance is only around 2x slower than normally-compiled C++ (which is comparable to other languages like Java or C#). This is substantially faster than current browser runtimes, yielding performance that&#8217;s about 4-10x faster than the latest Firefox and Chrome builds.</p>
<p><a href="http://kripken.github.com/mloc_emscripten_talk/#/28"><img src="http://kripken.github.com/mloc_emscripten_talk/macro4b.png" style="max-width: 560px;"/></a></p>
<p>This is a substantial improvement over the current best case. Considering how early on in the development of Asm.js is it&#8217;s very likely that there could be even greater performance improvements coming.</p>
<p>It is interesting to see such a large performance chasm appearing between Asm.js and the current engines in Firefox and Chrome. A 4-10x performance difference is substantial (this is in the realm of comparing these browsers to the performance of IE 6). Interestingly even with this performance difference many of these Asm.js demos are still usable on Chrome and Firefox, which is a good indicator for the current state of JavaScript engines. That being said their performance is simply not as good as the performance offered by a browser that is capable of optimizing Asm.js code.</p>
<h2>Use Cases</h2>
<p>It should be noted that almost all of the applications that are targeting Asm.js right now are C/C++ applications compiled to Asm.js using Emscripten. With that in mind the kind of applications that are going to target Asm.js, in the near future, are those that will benefit from the portability of running in a browser but which have a level of complexity in which a direct port to JavaScript would be infeasible.</p>
<p>So far most of the use cases have centered around code bases where performance is of the utmost importance: Such as in running games, graphics, programming language interpreters, and libraries. A quick look through the <a href="https://github.com/kripken/emscripten/wiki">Emscripten project list</a> shows many projects which will be of instant use to many developers.</p>
<ul>
<li>A number of game engines have already been ported. A good demo of what is possible is the <a href="https://developer.mozilla.org/en-US/demos/detail/bananabread">BananaBread FPS Game</a> (<a href="https://github.com/kripken/BananaBread/">Source Code</a>) which is playable directly in the browser and features multiplayer and bots.</li>
<li>A port of LaTeX to JavaScript, <a href="http://manuels.github.com/texlive.js/website/">called texlive.js</a>, using Emscripten, allowing you to compile PDFs completely within your browser.</li>
<li>A port of <a href="https://github.com/kripken/sql.js">SQLite to JavaScript</a> capable of running in Node.js.</li>
<li><a href="https://github.com/tonyg/js-nacl">NaCL: A Networking and Cryptography Library</a></li>
</ul>
<h2>Asm.js Support</h2>
<p>As mentioned before the <a href="https://blog.mozilla.org/luke/2013/03/21/asm-js-in-firefox-nightly/">nightly version of Firefox</a> is currently the only browser that supports optimizing Asm.js code.</p>
<p>However it&#8217;s important to emphasize that Asm.js-formatted JavaScript code is still just JavaScript code, albeit with an important set of restrictions. For this reason Asm.js-compiled code can still run in other browsers as normal JavaScript code, even if that browser doesn&#8217;t support it.</p>
<p>The critical puzzle piece is the performance of that code: If a browser doesn&#8217;t support typed arrays or doesn&#8217;t specially-compile the Asm.js code then the performance is going to be much worse off. Of course this isn&#8217;t special to Asm.js, likely any browser that doesn&#8217;t have those features is also suffering in other ways.</p>
<h2>Asm.js and Web Development</h2>
<p>As you can probably see from the code above Asm.js isn&#8217;t designed to be written by hand. It&#8217;s going to require some sort of tooling to write and it&#8217;s going to require some rather drastic changes from how one would normally write JavaScript, in order to use. The most common use case for Asm.js right now is in applications complied from C/C++ to JavaScript. Almost none of these applications interact with the DOM in a meaningful way, beyond using WebGL and the like.</p>
<p>In order for it to be usable by regular developers there are going to have to be some intermediary languages that are more user-accessible that can compile to Asm.js. The best candidate, at the moment, is <a href="http://mbebenita.github.com/LLJS/">LLJS</a> in which work is starting to get it <a href="http://www.jlongster.com/Compiling-LLJS-to-asm.js,-Now-Available-">compiling to Asm.js</a>. It should be noted that a language like LLJS is still going to be quite different from regular JavaScript and will likely confuse many JavaScript users. Even with a nice more-user-accessible language like LLJS it&#8217;s likely that it&#8217;ll still only be used by hardcore developers who want to optimize extremely complex pieces of code.</p>
<p>Even with LLJS, or some other language, that could allow for more hand-written Asm.js code we still wouldn&#8217;t have an equally-optimized DOM to work with. The ideal environment would be one where we could compile LLJS code and the DOM together to create a single Asm.js blob which could be executed simultaneously. It&#8217;s not clear to me what the performance of that would look like but I would love to find out!</p>
<h2>Q&amp;A with David Herman</h2>
<p>I sent some questions to <a href="http://calculist.org/">David Herman</a> (Senior Researcher at Mozilla Research) to try and get some clarification on how all the pieces of Asm.js fit together and how they expect users to benefit from it. He graciously took the time to answer the questions in-depth and provided some excellent responses. I hope you find them to be as illuminating as I did.</p>
<p><strong>What is the goal of Asm.js? Who do you see as the target audience for the project?</strong></p>
<blockquote><p>
  Our goal is to make the open web a compelling virtual machine, a target for compiling other languages and platforms. In this first release, we&#8217;re focused on compiling low-level code like C and C++. In the longer run we hope to add support for higher-level constructs like structured objects and garbage collection. So eventually we&#8217;d like to support applications from platforms like the JVM and .NET.</p>
<p>Since asm.js is really about expanding the foundations of the web, there&#8217;s a wide range of potential audiences. One of the audiences we feel we can reach now is game programmers who want access to as much raw computational power as they can. But web developers are inventive and they always find ways to use all the tools at their disposal in ways no one predicts, so I have high hopes that asm.js will become an enabling technology for all sorts of innovative applications I can&#8217;t even imagine.
</p></blockquote>
<p><strong>Does it make sense to create a more user-accessible version of Asm.js, like an updated version of LLJS? What about expanding the scope of the project beyond just a compiler target?</strong></p>
<blockquote><p>
  Absolutely. In fact, my colleague <a href="http://www.jlongster.com">James Long</a> recently announced that he&#8217;s done an <a href="http://www.jlongster.com/Compiling-LLJS-to-asm.js,-Now-Available-">initial fork of LLJS that compiles to asm.js</a>. My team at <a href="http://www.mozilla.org/research">Mozilla Research</a> intends to incorporate James&#8217;s work and officially evolve LLJS to support asm.js.</p>
<p>In my opinion, you generally only want to write asm.js by hand in a very narrow set of instances, like any assembly language. More often, you want to use more expressive languages that compile efficiently to it. Of course, when languages get extremely expressive like JavaScript, you lose predictability of performance. (My friend <a href="http://twitter.com/mraleph">Slava Egorov</a> wrote a nice post describing the <a href="http://mrale.ph/blog/2011/11/05/the-trap-of-the-performance-sweet-spot.html">challenges of writing high-performance code in high-level languages</a>.) LLJS aims for a middle ground &#8212; like a C to asm.js&#8217;s assembly &#8212; that&#8217;s easier to write than raw asm.js but has more predictable performance than regular JS. But unlike C, it still has smooth interoperability with regular JS. That way you can write most of your app in dynamic, flexible JS, and focus on only writing the hottest parts of your code in LLJS.
</p></blockquote>
<p><strong>There is talk of a renewed performance divide between browsers that support Asm.js and browsers that don’t, similar to what happened during the last JavaScript performance race in 2008/2009. Even though technically Asm.js code can run everywhere in reality the performance difference will simply be too crippling for many cases. Given this divide, and the highly restricted subset of JavaScript, why did you choose JavaScript as a compilation target? Why JavaScript instead of a custom language or plugin?</strong></p>
<blockquote><p>
  First of all, I don&#8217;t think the divide is as stark as you&#8217;re characterizing it: we&#8217;ve built <a href="https://developer.mozilla.org/en-US/demos/detail/falling-cubes">impressive</a> <a href="https://developer.mozilla.org/en-US/demos/detail/bananabread">demos</a> that work well in existing browsers but will benefit from killer performance with asm.js.</p>
<p>It&#8217;s certainly true that you can create applications that will depend on the increased performance of asm.js to be usable. At the same time, just like any new web platform capability, applications can decide whether to degrade gracefully with some less compute-intensive fallback behavior. There&#8217;s a difference in kind between an application that works with degraded performance and an application that doesn&#8217;t work at all.</p>
<p>More broadly, keep in mind the browser performance race that started in the late 00&#8242;s was great for the web, and applications have evolved along with the browsers. I believe the same thing can and will happen with asm.js.
</p></blockquote>
<p><strong>How would you compare Asm.js with Google’s Native Client? They appear to have similar goals while Asm.js has the advantage of “just working” everywhere that has JavaScript. Have there been any performance comparisons?</strong></p>
<blockquote><p>
  Well, Native Client is a bit different, since it involves shipping platform-specific assembly code; I don&#8217;t believe Google has advocated for that as a web content technology (as opposed to making it available to Chrome Web Store content or Chrome extensions), or at least not recently.</p>
<p>Portable Native Client (PNaCl) has a closer goal, using platform-independent LLVM bitcode instead of raw assembly. As you say, the first advantage of asm.js is compatibility with existing browsers. We also avoid having to create a system interface and repeat the full surface area of the web API&#8217;s as the <a href="https://developers.google.com/native-client/pepperc/">Pepper API</a> does, since asm.js gets access to the existing API&#8217;s by calling directly into JavaScript. Finally, there&#8217;s the benefit of ease of implementability: <a href="https://blog.mozilla.org/luke">Luke Wagner</a> got our first implementation of <a href="https://blog.mozilla.org/luke/2013/03/21/asm-js-in-firefox-nightly/">OdinMonkey</a> implemented and landed in Firefox in just a few months, working primarily by himself. Because asm.js doesn&#8217;t have a big set of syscalls and API&#8217;s, and because it&#8217;s built off of the JavaScript syntax, you can reuse a whole bunch of the machinery of an existing JavaScript engine and web runtime.</p>
<p>We could do performance comparisons to PNaCl but it would take some work, and we&#8217;re more focused on closing the gap to raw native performance. We plan to set up some automated benchmarks so we can chart our progress compared with native C/C++ compilers.
</p></blockquote>
<p><strong>Emscripten, another Mozilla project, appears to be the primary producer of Asm.js-compatible code. How much of Asm.js is being dictated by the needs of the Emscripten project? What benefits has Emscripten received now that improvements are being made at the engine level?</strong></p>
<blockquote><p>
  We used Emscripten as our first test case for asm.js as a way to ensure that it&#8217;s got the right facilities to accommodate the needs of real native applications. And of course benefiting Emscripten benefits everyone who has native applications they want to port &#8212; such as <a href="http://epicgames.com/">Epic Games</a>, who we teamed up with to <a href="https://blog.mozilla.org/blog/2013/03/27/mozilla-is-unlocking-the-power-of-the-web-as-a-platform-for-gaming/">port the Unreal Engine 3 to the web</a> in just a few days using Emscripten and asm.js.</p>
<p>But asm.js can benefit anyone who wants to target a low-level subset of JavaScript. For example, we&#8217;ve spoken with the folks who build the <a href="http://www.mandreel.com/">Mandreel</a> compiler, which works similarly to Emscripten. We believe they could benefit from targeting asm.js just as Emscripten has started doing.</p>
<p><a href="http://twitter.com/kripken">Alon Zakai</a> has been compiling benchmarks that generally run around 2x slower than native, where we were previously seeing results anywhere from 5x to 10x or 20x of native. This is just in our initial release of <a href="https://blog.mozilla.org/luke/2013/03/21/asm-js-in-firefox-nightly/">OdinMonkey</a>, the asm.js backend for Mozilla&#8217;s SpiderMonkey JavaScript engine. I expect to see more improvements in coming months.
</p></blockquote>
<p><strong>How fluid is the Asm.js specification? Are you open to adding in additional features (such as more-advanced data structures) as more compiler authors being to target it?</strong></p>
<blockquote><p>
  You bet. Luke Wagner has written up an <a href="https://wiki.mozilla.org/Javascript:SpiderMonkey:OdinMonkey">asm.js and OdinMonkey roadmap</a> on the Mozilla wiki, which discusses some of our future plans &#8212; I should note that none of these are set in stone but they give you a sense of what we&#8217;re working on. I&#8217;m really excited about adding support for ES6 <a href="http://wiki.ecmascript.org/doku.php?id=harmony:binary_data">structured objects</a>. This would provide garbage-collected but well-typed data structures, which would help compilers like <a href="http://jsil.org">JSIL</a> that compile managed languages like C# and Java to JavaScript. We&#8217;re also hoping to use something like the proposed ES7 <a href="http://wiki.ecmascript.org/doku.php?id=strawman:value_objects">value types</a> to provide support for 32-bit floats, 64-bit integers, and hopefully even fixed-length vectors for <a href="http://en.wikipedia.org/wiki/SIMD">SIMD</a> support.
</p></blockquote>
<p><strong>Is it possible, or even practical, to have a JavaScript-to-Asm.js transpiler?</strong></p>
<blockquote><p>
  Possible, yes, but practical? Unclear. Remember in <a href="http://www.imdb.com/title/tt1375666/">Inception</a> how every time you nested another dream-within-a-dream, time would slow down? The same will almost certainly happen every time you try to run a JS engine within itself. As a back-of-the-envelope calculation, if asm.js runs native code at half native speed, then running a JS engine in asm.js will execute JS code at half that engine&#8217;s normal speed.</p>
<p>Of course, you could always try running one JS engine in a different engine, and who knows? Performance in reality is never as clear-cut as it is in theory. I welcome some enterprising hacker to try it! In fact, Stanford student <a href="http://tatiyants.com/introducing-js-js/">Alex Tatiyants</a> has already <a href="https://github.com/jterrace/js.js/">compiled Mozilla&#8217;s SpiderMonkey engine to JS</a> via Emscripten &#8212; all you&#8217;d have to do is use <a href="https://blog.mozilla.org/luke/2013/03/21/asm-js-in-firefox-nightly/">Emscripten&#8217;s compiler flags</a> to generate asm.js. Someone with more time on their hands than me should give it a try&#8230;
</p></blockquote>
<p><strong>At the moment all DOM/browser-specific code is handled outside of Asm.js-land. What about creating an Emscripten-to-Asm.js-compiled version of the DOM (akin to DOM.js)?</strong></p>
<blockquote><p>
  This is a neat idea. It may be a little tricky with the preliminary version of asm.js, which doesn&#8217;t have any support for objects at all. As we grow asm.js to include support for ES6 <a href="http://wiki.ecmascript.org/doku.php?id=harmony:binary_data">typed objects</a>, something like this could become feasible and quite efficient!</p>
<p>A cool application of this would be to see how much of the web platform could be <a href="http://en.wikipedia.org/wiki/Self-hosting">self-hosted</a> with good performance. One of the motivations behind DOM.js was to see if a pure JS implementation of the DOM could beat the traditional, expensive marshaling/unmarshaling and cross-heap memory management between the JS heap and the reference-counted C++ DOM objects. With asm.js support, DOM.js might get those performance wins <em>plus</em> the benefits of highly optimized data structures. It&#8217;s worth investigating.
</p></blockquote>
<p><strong>Given that it’s fairly difficult to write Asm.js, compared with normal JavaScript, what sorts of tools would you like to have to help both developers and compiler authors?</strong></p>
<blockquote><p>
  First and foremost we&#8217;ll need languages like LLJS, as you mentioned, to compile to asm.js. And we&#8217;ll have some of the usual challenges of compiling to the web, such as mapping generated code back to the original source in the browser developer tools, using technologies like <a href="http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/">source maps</a>. I&#8217;d love to see source maps developed further to be able to incorporate richer debugging information, although there&#8217;s probably a cost/benefit balance to be struck between the pretty minimal source location information of source maps and super-complex debugging metadata formats like <a href="http://en.wikipedia.org/wiki/DWARF">DWARF</a>.</p>
<p>For asm.js, I think we&#8217;ll focus on LLJS in the near term, but I always welcome ideas from developers about how we can improve their experience.
</p></blockquote>
<p><strong>I assume that you are open to working with other browser vendors, what has collaboration or discussion been like thus far?</strong></p>
<blockquote><p>
  Definitely. We&#8217;ve had a few informal discussions and they&#8217;ve been encouraging so far, and I&#8217;m sure we&#8217;ll have more. I&#8217;m optimistic that we can work with multiple vendors to get asm.js somewhere that we all feel we can realistically implement without too much effort or architectural changes. As I say, the fact that Luke was able to implement OdinMonkey in a matter of just a few months is very encouraging. And I&#8217;m happy to see a <a href="http://code.google.com/p/v8/issues/detail?id=2599">bug on file for asm.js support in V8</a>.</p>
<p>More importantly, I hope that developers will check out asm.js and see what they think, and provide their feedback both to us and other browser vendors.
</p></blockquote>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/NpK4hncAn5o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/asmjs-javascript-compile-target/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>WebKit is the jQuery of Browser Engines</title>
		<link>http://ejohn.org/blog/webkit-is-the-jquery-of-browser-engines/</link>
		<comments>http://ejohn.org/blog/webkit-is-the-jquery-of-browser-engines/#comments</comments>
		<pubDate>Wed, 13 Feb 2013 14:38:57 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5896</guid>
		<description><![CDATA[The news has just come out that Opera is switching all of their browsers (both mobile and desktop) to use WebKit (specifically, Chromium). I&#8217;ve seen a lot of gnashing of teeth on Twitter and I feel like I can respond because I use to feel the same way back in 2008-2009. However this is 2013 [...]]]></description>
				<content:encoded><![CDATA[<p>The <a href="http://my.opera.com/ODIN/blog/300-million-users-and-move-to-webkit">news has just come out that Opera</a> is switching all of their browsers (both mobile and desktop) to use WebKit (specifically, Chromium). I&#8217;ve seen a lot of gnashing of teeth on Twitter and I feel like I can respond because I use to feel the same way back in 2008-2009. However this is 2013 and the Chrome/Chromium team has made it obvious that any form of stagnation or lack of innovation does not need to occur when using WebKit. In fact it possibly gives you the ability to accelerate your development, spending less time worrying about implementing common standards. I would argue that WebKit (a common framework for implementing the standards-compatible portion of a web browser) is exactly like jQuery (a common framework for implementing a DOM standards-compatible experience in a web page) at this point.</p>
<p>These are a few arguments against the switch that I&#8217;ve seen so far:</p>
<p><strong>A browser switching to WebKit will result in stagnation</strong></p>
<p>That is demonstrably not true. KDE created KHTML, Apple created WebKit based upon that, Google created WebKit/Chromium based upon that. I don&#8217;t think anyone can successfully argue that Chome/Chromium isn&#8217;t a better browser than Safari which isn&#8217;t a better browser than Konqueror. The Chrome team has proved that stagnation when using WebKit is merely a choice, as a contributor to WebKit you have the complete ability to drive it in a direction you wish (often for the better). I see no reason why the highly-skilled development team at Opera won&#8217;t be able to do the same. They can implement a number of their Opera-specific features into WebKit and it&#8217;s likely that those features will start to trickle back into other WebKit-using browsers as well.</p>
<p><strong>This is helping to making WebKit a de facto standard, bugs-and-all</strong></p>
<p>I don&#8217;t see this argument as being relevant any more, WebKit is already a de facto standard. I mean, everyone remembers when the browsers decided to <a href="http://my.opera.com/ODIN/blog/2012/08/10/css-vendor-prefixes-in-opera-12-50-snapshots">implement <code>-webkit</code> vendor prefixes</a>? It&#8217;s obvious that the &#8220;WebKit is an de facto standard&#8221; horse has already left the gate. As to the bugs: WebKit is a common code base that a number of browsers contribute to, however every browser vendor has the ability to make changes to their own fork of the code base. I see no reason why these &#8220;now-standard&#8221; WebKit bugs wouldn&#8217;t be fixed by any single vendor. Having a bug in the engine does not mean that a single browser vendor is incapable of fixing it &#8212; they would just be willfully not fixing it (as the browser vendors currently willfully clone <code>-webkit</code> prefixes).</p>
<p>In the case of JavaScript libraries virtually everyone has standardized upon jQuery at this point. This didn&#8217;t result in stagnation, which was a major concern, instead it&#8217;s resulted in a number of interesting and hyper-popular second-tier frameworks which build upon jQuery, such as: <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a>, <a href="http://html5boilerplate.com/">HTML5 Boilerplate</a>, and <a href="http://backbonejs.org/">Backbone.js</a>.</p>
<p><strong>This will affect Opera&#8217;s ability to influence standards</strong></p>
<p>I don&#8217;t see the switch to WebKit causing this. I do see <a href="http://annevankesteren.nl/">Anne van Kesteren</a>&#8216;s move to Mozilla as being a massive blow to Opera&#8217;s ability to push standards though. I don&#8217;t know anything about the situation but if his moving was caused by the switch to WebKit then yes, Opera&#8217;s move to WebKit has affected their ability to influence standards.</p>
<p><strong>Opera switching to WebKit is a slippery slope and/or Opera is a small player, Firefox or IE switching to WebKit would be a bigger problem</strong></p>
<p>I think one this is clear already: WebKit has completely and unequivocally won mobile at this point. They are nearly the only rendering engine used on the vast majority of mobile browsers, including the soon-to-switch Opera Mini/Mobile browsers too. There is no reason to worry about a slippery slope, the slope has already been slid down. In order for any other browser to remain relevant in the world of mobile (which, you must admit, is quickly becoming the only world we live in) they must keep feature parity with WebKit. Let&#8217;s follow this to its logical conclusion: In a world in which WebKit is now virtually the only mobile browser vendor Mozilla and Microsoft will feel increased pressure to switch their browser engines over to WebKit in order to keep pace. Google has proved that with Chrome that WebKit stagnation is simply a choice so there&#8217;s no reason why these other companies shouldn&#8217;t be able to build off of WebKit (and possibly create WebKit hybrids, such as WebKit + IonMonkey).</p>
<p>The big question becomes: <strong>Should they switch?</strong></p>
<p>At this point it&#8217;s honestly a business/engineering decision for Mozilla and Microsoft (as it always has been). If some percentage of your developer force is spending all of their time implementing the same standards that everyone else is implementing then switching to a common code base will give you the ability to free up some of your developers to work on something else. You saw what happened in the case of Chrome: They used their extra developer time to completely crush the competition on performance. This resulted in the everyone-wins race to become the fastest browser.</p>
<p>Ultimately it&#8217;s important to remember that WebKit is not a monolithic entity. It&#8217;s a shared codebase that a number of corporations contribute to. (In this respect it&#8217;s different from jQuery: Almost all contributions to jQuery comes back into the main codebase, whereas with WebKit some come back to the main codebase and some stay in a fork.) There is a lot of code sharing going on but it isn&#8217;t the be-all and end-all of browser development. Innovation can clearly still occur when working on a shared codebase and performance will almost certainly continue to improve.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/pU4BxTBqCUg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/webkit-is-the-jquery-of-browser-engines/feed/</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
		<item>
		<title>Fixing Google Analytics for Ghostery</title>
		<link>http://ejohn.org/blog/fixing-google-analytics-for-ghostery/</link>
		<comments>http://ejohn.org/blog/fixing-google-analytics-for-ghostery/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 16:21:13 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5887</guid>
		<description><![CDATA[As an avid user of Ghostery, which blocks all sorts of tracking scripts, pixels, and other web bugs I frequently run across a surprising issue: The case in which the Google Analytics ga.js script has been blocked from loading (which is intended) but then some critical piece of functionality on the site is broken. The [...]]]></description>
				<content:encoded><![CDATA[<p>As an avid user of <a href="http://www.ghostery.com/">Ghostery</a>, which blocks all sorts of tracking scripts, pixels, and other web bugs I frequently run across a surprising issue: The case in which the Google Analytics <code>ga.js</code> script has been blocked from loading (which is intended) but then some critical piece of functionality on the site is broken. The most common place I see this is when a site adds some event tracking to a signup or purchase form. Clicking the submit button will result in a JavaScript error, thus making it impossible to submit the form.</p>
<p>I&#8217;ve found that this occurs when people are doing inline <a href="https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide">event tracking</a> and are assuming that the Google Analytics functionality will always exist. Ghostery-or-not this is generally not a good practice to have: Assuming that some external, 3rd-party, script will always correctly load will result in many a broken web page.</p>
<p>You see cases where people work around this issue, for example in the <a href="https://github.com/h5bp/html5-boilerplate/blob/master/index.html">HTML5 Boilerplate</a> project:</p>
<div id="ig-sh-1" class="syntax_hilite">	<div class="code"><ol class="html4strict" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span>&gt;</span>window.jQuery || document.write('<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/vendor/jquery-1.9.1.min.js&quot;</span>&gt;&lt;\<span style="color: #66cc66;">/</span>script&gt;</span>')<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></li>
</ol>	</div></div>
<p>This attempts to load the jQuery library directly from <a href="https://developers.google.com/speed/libraries/devguide">Google&#8217;s CDN</a> and if it fails (for whatever reason &#8212; Google&#8217;s down, bad Internet connection, or some other weird reason) then it falls back to attempting to load a local version of jQuery. One question that comes of this is: Why not just always load jQuery from your local source rather than rely upon a third party? In this case it makes a lot of sense to pull jQuery from a CDN as you&#8217;ll benefit from the performance and caching benefits that a CDN provides, all while reducing the total bandwidth that you&#8217;ll have to expend on your end.</p>
<p>In the case of Google Analytics you typically don&#8217;t have that luxury: Google recommends that you load the <code>ga.js</code> library directly from their site (which can make sense as then they can push out seamless API changes and bug fixes). However this still causes issues for when Google Analytics simply doesn&#8217;t load, wether due to network conditions or due to Ghostery or some other browser extension.</p>
<p>For this reason, in a site I recently built, I added in the following code as a light wrapper around Google&#8217;s event tracking API:</p>
<div id="ig-sh-2" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// Add in Google Analytics tracking</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var track = function(category, name, value) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; if (window._gaq) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; window._gaq.push([&quot;_trackEvent&quot;, category, name, value]);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">};</div></li>
</ol>	</div></div>
<p>and then when I wanted to track an actual event I would do something like this:</p>
<div id="ig-sh-3" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">track(&quot;Source&quot;, &quot;Visit&quot;, this.href);</div></li>
</ol>	</div></div>
<p>If Google Analytics has failed to load for some reason then the <code>track()</code> call just silently does nothing &#8211; and for users who have Google Analytics installed it tracks the event. I should note that this same technique applies for other event tracking APIs as well, such as <a href="https://mixpanel.com/">Mixpanel</a> or <a href="https://www.kissmetrics.com/">KISSmetrics</a> (they&#8217;re blocked the same as Google Analytics).</p>
<p>Even libraries like <a href="https://segment.io/">Segment.io</a>, which act as a unified wrapper around tracking, are prone to the same issue. Even though they&#8217;ve gone through all the hard work of creating a unified API for event tracking they are still blocked by Ghostery, which will likely still result in errors in your application. In that case you would just write a similar <code>track(...)</code> wrapper around their <code>analytics.track('Name', properties)</code> call.</p>
<p><strong>Update:</strong> The current version of the Google Analytics script always exposes the <code>_gaq</code> object, even if the code isn&#8217;t loaded, so this may be a non-issue for Google Analytics (although the principles here hold true for any third-party-included libraries). I&#8217;ve gotten word from the Ghostery team that Ghostery now handles this case, automatically exposing missing global objects for cases like this (see below in the comments). I&#8217;ve also gotten word from the Segment.io team that, as of now, Ghostery does not block their analytics tracking so you may not need a wrapper there. Additionally Segment.io does check to make sure that the potentially-blocked global objects are actually there before attempting to use them. In general though, and this goes for all third-party script, you&#8217;ll probably want to have a wrapper (or an alternative script) if you&#8217;re loading code from a third-party domain name.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/YU3afHMQBdM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/fixing-google-analytics-for-ghostery/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Secrets of the JavaScript Ninja Released</title>
		<link>http://ejohn.org/blog/secrets-of-the-javascript-ninja-released/</link>
		<comments>http://ejohn.org/blog/secrets-of-the-javascript-ninja-released/#comments</comments>
		<pubDate>Thu, 07 Feb 2013 18:39:30 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5881</guid>
		<description><![CDATA[Happy news! My book, Secrets of the JavaScript Ninja is finally in stock on Amazon! It&#8217;s been available on Manning.com for over a month now but I think Amazon has been struggling to keep the books consistently in stock. You can get an ePub or Kindle version of the book at Manning.com. I&#8217;ve written about [...]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://www.amazon.com/gp/product/193398869X/ref=as_li_ss_tl?ie=UTF8&#038;camp=1789&#038;creative=390957&#038;creativeASIN=193398869X&#038;linkCode=as2&#038;tag=jspro-20"><img src="http://ejohn.org/files/jsninja/jsninja-cover.sm.jpg"/></a></center></p>
<p>Happy news! My book, <a href="http://jsninja.com/">Secrets of the JavaScript Ninja</a> is finally <a href="http://www.amazon.com/gp/product/193398869X/ref=as_li_ss_tl?ie=UTF8&#038;camp=1789&#038;creative=390957&#038;creativeASIN=193398869X&#038;linkCode=as2&#038;tag=jspro-20">in stock on Amazon</a>! It&#8217;s been <a href="http://www.manning.com/resig/">available on Manning.com</a> for over a month now but I think Amazon has been struggling to keep the books consistently in stock.</p>
<p>You can get an ePub or Kindle version of the book <a href="http://www.manning.com/resig/">at Manning.com</a>.</p>
<p>I&#8217;ve written about the <a href="http://ejohn.org/blog/secret-omens/">writing process for this book</a> previously (and why it&#8217;s taken so long to get out). I especially want to thank my co-author Bear Bibeault who worked hard to get this book out the door.</p>
<p>One question that I&#8217;ve been asked recently: &#8220;How relevant is this book to writing JavaScript in 2012?&#8221; I think it&#8217;s still exceedingly relevant. This book has two major focuses:</p>
<ol>
<li>Teaching aspects of the JavaScript language that are under-served or poorly explained. (For example I&#8217;ve been getting a number of messages from people saying how much they appreciated the explanation of closures in the book and that it finally helped them to understand that feature of the language.)</li>
<li>Helping people understand the internal workings of cross-browser DOM-centric JavaScript libraries (such as jQuery). Considering how popular jQuery is (<a href="http://trends.builtwith.com/javascript/jQuery">64% of the top 10,000 web sites use jQuery</a>) and, relatively, how few people truly understand what the library does or is trying to do &#8211; there is still a huge market for people to learn what exactly jQuery is and how it works.</li>
</ol>
<p>I&#8217;m really happy that this book is finally out and to celebrate I&#8217;ve been trying to blog more (as you may have noticed). Are there any particular topics that you&#8217;d like me to write about? Let me know!</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/Hc2GAe0QWW0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/secrets-of-the-javascript-ninja-released/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Keeping Passwords in Source Control</title>
		<link>http://ejohn.org/blog/keeping-passwords-in-source-control/</link>
		<comments>http://ejohn.org/blog/keeping-passwords-in-source-control/#comments</comments>
		<pubDate>Wed, 06 Feb 2013 21:23:32 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5865</guid>
		<description><![CDATA[I learned a neat tip from my co-worker, Craig Silverstein (more on Craig joining Khan Academy), recently and I thought others might find it to be useful. It has to deal with the eternal question: How do you store sensitive configuration options (such as usernames, passwords, etc.) in source control? Typically what I&#8217;ve done is [...]]]></description>
				<content:encoded><![CDATA[<p>I learned a neat tip from my co-worker, <a href="http://www-cs-students.stanford.edu/~csilvers/">Craig Silverstein</a> (<a href="http://allthingsd.com/20120209/googles-very-first-employee-craig-silverstein-technically-no-3-leaving/">more on Craig joining Khan Academy</a>), recently and I thought others might find it to be useful.</p>
<p>It has to deal with the eternal question: How do you store sensitive configuration options (such as usernames, passwords, etc.) in source control? Typically what I&#8217;ve done is to just punt on the problem entirely. I create a dummy configuration file, such as <code>conf/sample-settings.json</code> which has the basic structure but none of the details filled out. For example:</p>
<p><strong><code>conf/sample-settings.json</code></strong></p>
<div id="ig-sh-4" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// Copy to conf/settings.json</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// and fill these in with your login details!</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">{</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &quot;db&quot;: {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &quot;username&quot;: &quot;&quot;,</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &quot;password&quot;: &quot;&quot;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">}</div></li>
</ol>	</div></div>
<p>If someone else needed the details I would just email it to them, or some such (not ideal). Especially when it came time to add additional information to the file or make other changes.</p>
<p>The technique I picked up from Craig was to, instead, keep an encrypted version of the configuration file in source control and then provide a means through which the user can encrypt and decrypt that data.</p>
<p>In this case you can still have the a dummy config file, if you wish.</p>
<p>To start you&#8217;ll want to make sure you have your source control ignore the configuration file &#8212; just to make super-sure that no one ever accidentally commits it. In Git you&#8217;d add a line like this to your <code>.gitignore</code> file:</p>
<p><strong><code>.gitignore</code></strong></p>
<div id="ig-sh-5" class="syntax_hilite">	<div class="code"><ol class="text" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">conf/settings.json</div></li>
</ol>	</div></div>
<p>Next you&#8217;ll want to create your actual config file and populate it with the real values.</p>
<p><strong><code>conf/settings.json</code> (* Do not check this in to source control!!)</strong></p>
<div id="ig-sh-6" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">{</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &quot;db&quot;: {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &quot;username&quot;: &quot;cool_guy&quot;,</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &quot;password&quot;: &quot;A1B2C3!&quot;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">}</div></li>
</ol>	</div></div>
<p>Finally you&#8217;ll want to create a script (I&#8217;m using a <code>Makefile</code>) that the user can run to encrypt and decrypt the file. This script uses OpenSSL, and specifically <a href="http://en.wikipedia.org/wiki/CAST-128">CAST5</a>, to encrypt/decrypt the file. OpenSSL was chosen in particular as it worked out-of-the-box on both Linux and Mac machines.</p>
<p>OpenSSL reads in the appropriate files (depending upon if you&#8217;re encrypting or decrypting) then will prompt you for a password to encrypt/decrypt the file. (You&#8217;re free to use any encryption scheme that OpenSSL supports, of course.)</p>
<p><strong><code>Makefile</code></strong></p>
<div id="ig-sh-7" class="syntax_hilite">	<div class="code"><ol class="bash" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">.PHONY: _pwd_prompt decrypt_conf encrypt_conf</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #007800;">CONF_FILE</span>=conf<span style="color: #000000; font-weight: bold;">/</span>settings.json</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #666666; font-style: italic;"># 'private' task for echoing instructions</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">_pwd_prompt:</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">@</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Contact jeresig@gmail.com for the password.&quot;</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #666666; font-style: italic;"># to create conf/settings.json</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">decrypt_conf: _pwd_prompt</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; openssl cast5-cbc <span style="color: #660033;">-d</span> <span style="color: #660033;">-in</span> <span style="color: #800000;">${CONF_FILE}</span>.cast5 <span style="color: #660033;">-out</span> <span style="color: #800000;">${CONF_FILE}</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">600</span> <span style="color: #800000;">${CONF_FILE}</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #666666; font-style: italic;"># for updating conf/settings.json</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">encrypt_conf: _pwd_prompt</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; openssl cast5-cbc <span style="color: #660033;">-e</span> <span style="color: #660033;">-in</span> <span style="color: #800000;">${CONF_FILE}</span> <span style="color: #660033;">-out</span> <span style="color: #800000;">${CONF_FILE}</span>.cast5</div></li>
</ol>	</div></div>
<p>With all this in place the next step is simple, you&#8217;ll run:</p>
<div id="ig-sh-8" class="syntax_hilite">	<div class="code"><ol class="bash" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #c20cb9; font-weight: bold;">make</span> encrypt_conf</div></li>
</ol>	</div></div>
<p>and you&#8217;ll enter in a password with which to encrypt the config file:</p>
<div id="ig-sh-9" class="syntax_hilite">	<div class="code"><ol class="text" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">Contact jeresig@gmail.com for the password.</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">enter cast5-cbc decryption password:</div></li>
</ol>	</div></div>
<p>Make sure you write this down and don&#8217;t forget it &#8212; it&#8217;ll be very hard (if not impossible) to get your config file back if you forget the password.</p>
<p>At this point you&#8217;ll have a <code>conf/settings.json.cast5</code> file and you can commit all the changes, using something like:</p>
<div id="ig-sh-10" class="syntax_hilite">	<div class="code"><ol class="bash" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #c20cb9; font-weight: bold;">git add</span> .gitignore Makefile conf<span style="color: #000000; font-weight: bold;">/</span>settings.json.cast5</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #c20cb9; font-weight: bold;">git commit</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Adding in an encrypted config file.&quot;</span></div></li>
</ol>	</div></div>
<p>Now whenever someone downloads the code from source control they&#8217;ll need to either fill in their own values into the config file or they&#8217;ll need to get the password from you (the one you entered when you ran <code>make encrypt_conf</code> &#8212; or even better, use a shared <a href="http://en.wikipedia.org/wiki/Password_Safe">password safe</a> to manage this). Once they have the password they just run the following and enter it:</p>
<div id="ig-sh-11" class="syntax_hilite">	<div class="code"><ol class="bash" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #c20cb9; font-weight: bold;">make</span> decrypt_conf</div></li>
</ol>	</div></div>
<p>If you ever need to update the values in the config file, it&#8217;s really straight-forward. Just update the config file, run <code>make encrypt_conf</code> again, and commit the new <code>conf/settings.json.cast5</code> file.</p>
<p>One extra bit that you can add to your application, to make this process more intuitive, is a check for a missing config file and output with instructions for using the <code>Makefile</code>.</p>
<p>For example if you were using Node.js you could do:</p>
<div id="ig-sh-12" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">if (!fs.existsSync(&quot;conf/settings.json&quot;)) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; console.error(&quot;Config file [conf/settings.json] missing!&quot;);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; console.error(&quot;Did you forget to run `make decrypt_conf`?&quot;);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; process.exit(1);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">}</div></li>
</ol>	</div></div>
<p>Also, you may want to consider having a check to see if the decrypted file is out of date (which can happen if some changes were made in the source control, then were checked out, but you didn&#8217;t also run <code>make decrypt_conf</code>). Perhaps something like the following:</p>
<div id="ig-sh-13" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">(function() {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; var conf_time = fs.statSync(&quot;conf/settings.json&quot;).mtime.getTime();</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; var cast5_time = fs.statSync(&quot;conf/settings.json.cast5&quot;).mtime.getTime();</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; if (conf_time &lt; cast5_time) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; console.error(&quot;Your config file is out of date!&quot;);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; console.error(&quot;You need to run `make decrypt_conf` to update it.&quot;);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; process.exit(1);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">})();</div></li>
</ol>	</div></div>
<p>And that&#8217;s it! Simpler than passing around config files manually and you still get all the benefit of using revision control to manage the file and changes.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/WmwL9XjltrU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/keeping-passwords-in-source-control/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
		<item>
		<title>i18n Module for Node and Express.js</title>
		<link>http://ejohn.org/blog/i18n-module-for-node-and-express-js/</link>
		<comments>http://ejohn.org/blog/i18n-module-for-node-and-express-js/#comments</comments>
		<pubDate>Tue, 15 Jan 2013 16:25:10 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5856</guid>
		<description><![CDATA[As a follow-up to my post from last week on a strategy for i18n and Node.js I&#8217;ve published my module for handling internationalization in Node and, specifically, Express.js. The module is now available on NPM and can be installed by running: npm install i18n-2 The code and documentation for the module is available on Github [...]]]></description>
				<content:encoded><![CDATA[<p>As a follow-up to my post from last week on <a href="http://ejohn.org/blog/a-strategy-for-i18n-and-node/">a strategy for i18n and Node.js</a> I&#8217;ve published my module for handling internationalization in Node and, specifically, Express.js.</p>
<p>The module is now <a href="https://npmjs.org/package/i18n-2">available on NPM</a> and can be installed by running:</p>
<blockquote><p><code>npm install <a href="https://npmjs.org/package/i18n-2">i18n-2</a></code></p></blockquote>
<p>The code and documentation for the module is available on Github here:</p>
<blockquote><p><a href="https://github.com/jeresig/i18n-node-2">https://github.com/jeresig/i18n-node-2</a></p></blockquote>
<p>I&#8217;ve designed the API to work as simply as possible with Express.js &#8211; while still supporting a simple Node.js usage or usage with another web framework.</p>
<p>The module includes a number of features built-in:</p>
<ul>
<li>Automatic integration with Express as middleware and integration with templating solutions.</li>
<li>Support for handling the setting of locale based upon query strings and/or subdomain.</li>
<li>Dynamic reading and updating of translation files during development mode.</li>
<li>Automatic caching of translation files in production mode.</li>
</ul>
<p>Usage is simple, in your Express app.js:</p>
<div id="ig-sh-14" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// load modules</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var express = require('express'),</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; I18n = require('i18n-2');</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// Express Configuration</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">app.configure(function() {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // ...</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // Attach the i18n property to the express request object</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // And attach helper methods for use in templates</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; I18n.expressBind(app, {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; // setup some locales - other locales default to en silently</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; locales: ['en', 'de']</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; }));</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // Set up the rest of the Express middleware</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; app.use(app.router);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; app.use(express.static(__dirname + '/public'));</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">});</div></li>
</ol>	</div></div>
<p>Inside your Express view:</p>
<div id="ig-sh-15" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">module.exports = {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; index: function(req, res) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; req.render(&quot;index&quot;, {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title: req.i18n.__(&quot;My Site Title&quot;),</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; desc: req.i18n.__(&quot;My Site Description&quot;)</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; });</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">};</div></li>
</ol>	</div></div>
<p>Inside your templates (this example uses the <a href="http://paularmstrong.github.com/swig/">Swig templating system</a>).</p>
<pre>{% extends "page.swig" %}
{% block content %}
&lt;h1>{{ __("Welcome to: %s", title) }}&lt;/h1>
&lt;p>{{ desc }}&lt;/p>
{% endblock %}</pre>
<p>My module is based off of <a href="https://github.com/mashpie/i18n-node">the i18n-node module by Marcus Spiegel</a>.</p>
<p>I used the <a href="https://github.com/mashpie/i18n-node">original i18n-node module</a> as a basis for further work as it provided the closest solution to full Express.js integration that I needed. After some initial usage though I saw that it was very much lacking. As I described in <a href="http://ejohn.org/blog/a-strategy-for-i18n-and-node/">my previous post</a> there is potential for severe problems to occur in an asynchronous environment like Node.js.</p>
<p>The problem that I was having was rather severe and, unfortunately, required a complete rewrite of the module. The original i18n-node module stored the locale information in a closure. Calling <code>setLocale</code> changed the locale but did so for every instance that was currently active, resulting in templates being rendered in the wrong language.</p>
<p><center><img src="http://ejohn.org/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-4.08.10-PM-271x300.png" alt="" title="Lang Shared State" width="271" height="300" class="alignnone size-medium wp-image-5843" /></center></p>
<p>Here is the issue that is especially surprising (but not so much once you know how modules work in Node.js): Since the state was stored in a closure repeated calls to <code>require('i18n')</code> resulted in the current locale state being held the entire time, not reset. This meant that when a new request came in, the locale was set, changing the locale for all other active requests.</p>
<p>The only way to fix this particular problem is to simply encapsulate all state into a single object &#8212; I did this by making an object that you instantiate: <code>new I18n(options)</code>.</p>
<p>I looked at other JavaScript translation solutions, including the excellent <a href="https://github.com/SlexAxton/jed">Jed</a> and <a href="https://github.com/SlexAxton/messageformat.js">messageformat</a> and while their translation capabilities are top-notch what they provided was overkill for my particular application and did not provide the Express.js integration that I needed.</p>
<p>I hope others will find this module to be useful, especially when used in conjunction with my <a href="http://ejohn.org/blog/a-strategy-for-i18n-and-node/">strategy for i18n and Node.js</a>.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/ni1WgbWIu3E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/i18n-module-for-node-and-express-js/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A Strategy for i18n and Node.js</title>
		<link>http://ejohn.org/blog/a-strategy-for-i18n-and-node/</link>
		<comments>http://ejohn.org/blog/a-strategy-for-i18n-and-node/#comments</comments>
		<pubDate>Fri, 11 Jan 2013 22:03:51 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5840</guid>
		<description><![CDATA[Recently I internationalized a Node/Express web application that I&#8217;ve been working on and it seems to have gone fairly well (users in multiple languages are using it happily and I&#8217;m seeing a marked increase in traffic because of it!). Not much of what I&#8217;m writing up here is particular to Node, per se, just a [...]]]></description>
				<content:encoded><![CDATA[<p>Recently I internationalized a <a href="http://expressjs.com/">Node/Express</a> web application that I&#8217;ve been working on and it seems to have gone fairly well (users in multiple languages are using it happily and I&#8217;m seeing a marked increase in traffic because of it!). Not much of what I&#8217;m writing up here is particular to Node, per se, just a general strategy for internationalizing a web application.</p>
<p>I&#8217;ve used enough internationalized web sites, and travelled to enough foreign countries and attempted to use English language sites back in the US, that I knew what kind of features I wanted:</p>
<ul>
<li><strong>Full parity between languages.</strong> Wherever possible the same content should be available to everyone.</li>
<li><strong>Use sub-domains to contain different language versions.</strong> It&#8217;s overkill/expensive to use different TLDs and it&#8217;s annoying to have to twiddle query strings or paths to match a language.</li>
<li><strong>No automatic translations of content to the user&#8217;s native language.</strong> There is nothing worse than arriving at a site and being forced into a version that you can&#8217;t read either because it&#8217;s poorly translated, or you&#8217;re being GeoIP detected, or you&#8217;re on a computer whose language settings don&#8217;t match your own. If you visit a URL it should always be in the same language</li>
<li><strong>No automatic redirects to a site with the user&#8217;s native language.</strong> Same as the last one. If I visit &#8220;foo.com&#8221; I should not be automatically routed to &#8220;es.foo.com&#8221; because it thinks that I speak Spanish. Instead, give the user a notification in their native language and allow them to visit the page themselves.</li>
</ul>
<p>The end result would be a simple URL system that works like so:</p>
<ul>
<li><code>domain.com</code> &#8211; Main site (English)</li>
<li><code>ja.domain.com</code> &#8211; Japanese Site</li>
<li><code>XX.domain.com</code> &#8211; Other languages</li>
</ul>
<p>and due to the full translation parity and the lack of URL modification it meant that for every page that you visited you could visit the same page in another language just by changing the sub-domain.</p>
<p>For example:</p>
<pre>   domain.com/search?q=mountain
ja.domain.com/search?q=mountain</pre>
<p>Both work identically, just the second one is presented in Japanese.</p>
<p>This has the benefit that in the header of the page I can link the user to the same exact page but in their native language.</p>
<p><center><img src="http://ejohn.org/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-1.58.17-PM.png" alt="" title="JP Header" width="85" height="52" class="alignnone size-full wp-image-5846" /> <img src="http://ejohn.org/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-1.58.43-PM.png" alt="" title="En Header" width="83" height="42" class="alignnone size-full wp-image-5845" style="position: relative; top: -4px;" /></center></p>
<p>Additionally I can use the <a href="http://support.google.com/webmasters/bin/answer.py?hl=en&#038;answer=189077">rel=&#8221;alternate&#8221; hreflang=&#8221;x&#8221;</a> technique to help Google understand the structure of my site better. I can put this in the header of my page and Google will show the language-preferred version of the site in the Google results.</p>
<pre>&lt;link rel="alternate" hreflang="ja"
    href="http://ja.domain.com/" /&gt;</pre>
<h2>Server</h2>
<p>Encouraging users to find the correct content is a key implementation detail, considering that the content is not translated automatically nor is the user redirected to content in their native language. While the links in the header are a good start I also wanted to show a message at the top of the page encouraging the user to view the content (with the message being written in their native language).</p>
<p><center><img src="http://ejohn.org/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-1.59.30-PM.png" alt="" title="Lang Redirect User" width="526" height="206" class="alignnone size-full wp-image-5844" /></center></p>
<p>As it turns out this can be particularly tricky to implement. The easiest way to do it is to simply check the user&#8217;s request headers and look at what&#8217;s listed in their &#8220;<a href="http://www.w3.org/International/questions/qa-accept-lang-locales">Accept Language</a>&#8221; and then display the message based upon that. This really only works if your content is always dynamic and is never being cached.</p>
<p>If that&#8217;s not the case for your application, how and where you do your caching matters.</p>
<p>In my particular application I&#8217;m using <a href="http://nginx.org/">nginx</a> in front of a proxied collection of <a href="http://expressjs.com/">Node/Express</a> servers. This means that everything coming from the Node server is cached (including any messages to the user telling them to visit another page).</p>
<p>As a result, in order to display this message to the user we&#8217;re going to need to manage the logic for this on the client. Unfortunately this is where we hit another stumbling block: It&#8217;s not possible to reliably determine the desired language of the user using just JavaScript/the DOM.</p>
<p>Thus we&#8217;ll need to get the server to pass us some extra information on what the user&#8217;s desired language is.</p>
<p>To do this I used the nginx <a href="http://wiki.nginx.org/AcceptLanguageModule">AcceptLanguage Module</a> and then set a cookie with the desired language and passed it to the client. This is the relevant nginx configuration to make that happen.</p>
<pre>set_from_accept_language $lang en ja;
add_header Set-Cookie lang=$lang;</pre>
<p>And now on the client-side all the needs to happen is reading the cookie for the desired language and displaying the redirect message if the current language and the desired language don&#8217;t match.</p>
<p>This gives the best of all worlds: nginx continues to aggressively cache the results from my Node servers and the client displays a message in the user&#8217;s native language encouraging them to visit the appropriate sub-domain.</p>
<h2>i18n Logic</h2>
<p>I&#8217;ve written <a href="http://ejohn.org/blog/i18n-module-for-node-and-express-js/">a new Node i18n module</a> which follows the makes the following strategy possible.</p>
<p>None of the i18n logic is particularly out of the ordinary but there are a few strategies I took that helped to simplify things.</p>
<ul>
<li>All translations are stored in named JSON files.</li>
<li>Those files are loaded and used for in-place translation in the application.</li>
<li>Translations are done using the typical <code>__("Some string.")</code> technique (wherein &#8220;Some string.&#8221; is replaced with the translated string, if it exists, otherwise &#8220;Some string.&#8221; is returned instead).</li>
</ul>
<p>Since all requests to the server are handled by a single set of servers this means that translation logic cannot be shared &#8211; it must be initialized and used on a request-by-request basis. I&#8217;ve seen other i18n solutions, like <a href="https://github.com/mashpie/i18n-node">i18n-node</a> that assume that the server will only ever be serving up pages in a single language, and this tends to fail in practice &#8211; especially in the shared-state, asynchronous, realm of Node. For example:</p>
<p><center><img src="http://ejohn.org/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-4.08.10-PM-271x300.png" alt="" title="Lang Shared State" width="271" height="300" class="alignnone size-medium wp-image-5843" /></center></p>
<p>Since whenever a request comes in and set the current language, it sets the current language for the shared i18n object &#8211; and given the asynchronous nature of Node it&#8217;s possible that other requests may be happening at the same time, and thus changing the displayed language of another request as a result.</p>
<p>You&#8217;ll want to make sure that, at minimum, your current language state is stored relative to the current request to avoid this problem. (My <a href="http://ejohn.org/blog/i18n-module-for-node-and-express-js/">new i18n node module</a> fixes this, for example.)</p>
<p>In practice it means that you&#8217;ll be adding a <code>i18n</code> property to the <code>request</code> object, likely as a piece of Express middleware, like so:</p>
<pre>app.use(function(req, res, next) {
	req.i18n = new i18n(/* options... */);
	next();
});</pre>
<h2>Workflow</h2>
<p>I have it so that the i18n logic behaves differently depending upon if the server is in development mode or in production mode.</p>
<p>When in development mode:</p>
<ul>
<li>Translation JSON files are read on every request.</li>
<li>Translation files are updated automatically any time a new string is detected.</li>
<li>Warnings and debug messages are shown.</li>
</ul>
<p>In production mode:</p>
<ul>
<li>All JSON translation files are cached the first time they&#8217;re read.</li>
<li>Translation files are never updated dynamically.</li>
<li>No warnings or debug messages are shown.</li>
</ul>
<p>The two major differences here are the caching and the auto-updating of the JSON files. When in development it&#8217;s quite useful to have the translation files reload on every request, in case a change has been made to their contents. Whereas in production they really should be considered static files.</p>
<p>Additionally, the workflow of having the translation files update every time a new string is found is actually quite useful: It helps you to catch strings that you may have forgotten to translate. Naturally doing this in production (frequently hitting the disk) is not a good idea.</p>
<h2>Marking Up Strings</h2>
<p>Strings that need to be translated can be found in a number of locations: Inside your application source, inside templates, inside JavaScript files, and even (god forbid) inside CSS files.</p>
<p>In the case of my application I had no strings inside my JavaScript or CSS files. This worked out nicely because I had already written my application in such a way that content is never being dynamically constructed from strings inside my client-side JavaScript. If I were to do that I would use a template and put the template directly into the HTML of my page, using something like my <a href="http://ejohn.org/blog/javascript-micro-templating/">JavaScript Micro-Templating</a> solution.</p>
<p>I consider it to be especially important that you try to avoid having any translatable strings in your JavaScript or CSS files as those files you&#8217;ll want to heavily cache and likely put onto a CDN. Naturally, you could dynamically replace those strings as part of your build process and just generate a number of script/css files, one for each language you support, but that is likely up to you and how much extra work you want to introduce into your build.</p>
<p>Inside my application I made sure that the only time I ever attempted to translate a string it was inside of a Express view handler (meaning that I had access to the request object, which is where I bound my i18n object).</p>
<p>An example of using the i18n object inside a view:</p>
<div id="ig-sh-15" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">module.exports = {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; index: function(req, res) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; req.render(&quot;index&quot;, {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title: req.i18n.__(&quot;My Site Title&quot;),</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; desc: req.i18n.__(&quot;My Site Description&quot;)</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; });</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">};</div></li>
</ol>	</div></div>
<p>For my templates I use the confusingly-named <a href="http://paularmstrong.github.com/swig/">swig</a>, but the technique for actually using the i18n methods will be roughly the same for most templating systems:</p>
<div id="ig-sh-16" class="syntax_hilite">	<div class="code"><ol class="html4strict" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">{% extends &quot;page.swig&quot; %}</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">{% block content %}</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>{{ __(&quot;Welcome to:&quot;) }} {{ title }}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;</span>{{ desc }}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span></div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">{% endblock %}</div></li>
</ol>	</div></div>
<p>A string is wrapped with a <code>__(...)</code> call and the string is replace with the translated string, as it is called.</p>
<h2>Translation</h2>
<p>So far the actual translation process has been relatively simple. It&#8217;s just me doing the translation and I&#8217;m not out-sourcing anything (at least not yet). Additionally my site is relatively simple, only a couple dozen strings at the moment.</p>
<p>I&#8217;ve been able to temporarily &#8220;cheat&#8221; in a few ways (at least until I hire a real translator):</p>
<ul>
<li><strong>Use Open Source Translations.</strong> There are already massive Open Source projects out there that have done a lot of hard work in translating their UIs. For example <a href="http://localize.drupal.org/translate/languages">Drupal</a> has all of their translations online in easy-to-download formats. I was able to find a number of strings that I needed by going through their files.</li>
<li><strong>Look at already-localized sites.</strong> This is another cheat but look for other sites that have some of the same features of your site and have already gone through the hard work of localizing into multiple languages, like Google. (In my case I was working on a search engine so a number of Google&#8217;s strings directly matched strings on my site.)</li>
<li><strong>Google Translate.</strong> I know, I know &#8211; but I was really surprised at how much better Google Translate has gotten as of late, especially for translating single words or concepts. It&#8217;s able to tell you the exact meanings for different possible translations, which is really impressive.</li>
</ul>
<p><center><a href="http://translate.google.com/"><img src="http://ejohn.org/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-4.39.30-PM-282x300.png" alt="" title="Google Translate" width="282" height="300" class="alignnone size-medium wp-image-5842" /></a></center></p>
<h2>Conclusion</h2>
<p>I&#8217;m only a couple weeks in to having implemented this process on my site, so I&#8217;m sure some things are likely to change as I start to scale up more. I&#8217;ve already substantially increased traffic to my site, especially as Google has started to index the newly-translated site. As I mentioned before I have <a href="http://ejohn.org/blog/i18n-module-for-node-and-express-js/">a new Node i18n module</a> that complements the above process and hopefully make it easier for others to follow, as well.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/UjONK3iVMRg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/a-strategy-for-i18n-and-node/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Talk: Khan Academy Computer Science</title>
		<link>http://ejohn.org/blog/talk-khan-academy-computer-science/</link>
		<comments>http://ejohn.org/blog/talk-khan-academy-computer-science/#comments</comments>
		<pubDate>Fri, 26 Oct 2012 15:04:26 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5833</guid>
		<description><![CDATA[This past weekend I gave a talk at EmpireJS on the Computer Science platform that I&#8217;ve been developing at Khan Academy. The talk explores that platform and then goes into deeper technical details about how the real-time execution on the site was achieved. I recorded the talk on my laptop (so please excuse the echo [...]]]></description>
				<content:encoded><![CDATA[<p>This past weekend I gave <a href="https://www.youtube.com/watch?v=2sEvlJKAuos">a talk</a> at <a href="http://empirejs.org/">EmpireJS</a> on the <a href="http://khanacademy.org/cs">Computer Science platform</a> that I&#8217;ve been developing at Khan Academy. The talk explores that platform and then goes into deeper technical details about how the real-time execution on the site was achieved.</p>
<p>I recorded the talk on my laptop (so please excuse the echo as it wasn&#8217;t properly mic&#8217;ed up) and you can <a href="https://www.youtube.com/watch?v=2sEvlJKAuos">watch it here</a>:</p>
<p><iframe width="480" height="360" src="http://www.youtube.com/embed/2sEvlJKAuos?rel=0" frameborder="0" allowfullscreen></iframe></p>
<p>A <a href="http://www.slideshare.net/jeresig/khan-academy-computer-science">slightly older</a> (stats are slightly out of date) version of the slides can be found here:</p>
<p><iframe src="http://www.slideshare.net/slideshow/embed_code/14376708" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe></p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/XW5c0bj_y2w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/talk-khan-academy-computer-science/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Redefining the Introduction to Computer Science</title>
		<link>http://ejohn.org/blog/introducing-khan-cs/</link>
		<comments>http://ejohn.org/blog/introducing-khan-cs/#comments</comments>
		<pubDate>Tue, 14 Aug 2012 17:35:19 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5816</guid>
		<description><![CDATA[I&#8217;m incredibly excited to take this opportunity to announce a new project that I&#8217;ve been leading here at Khan Academy: Khan Academy Computer Science. We&#8217;re releasing a completely new platform that targets people with no programming knowledge and gives them an engaging and fun environment to learn in. Over everything else we wanted to emphasize [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m incredibly excited to take this opportunity to announce a new project that I&#8217;ve been leading here at Khan Academy: <a href="http://www.khanacademy.org/cs">Khan Academy Computer Science</a>.</p>
<p><center><a href="http://www.khanacademy.org/cs"><img src="http://ejohn.org/files/cs-flock-screenshot.sm.png"/></a></center></p>
<p>We&#8217;re releasing a completely new platform that targets people with no programming knowledge and gives them an engaging and fun environment to learn in.</p>
<p>Over everything else we wanted to emphasize creativity and exploration and make it approachable for people of all ages, including young kids.</p>
<p><a href="http://en.wikipedia.org/wiki/Salman_Khan_(educator)">Sal Khan</a> and I recorded a video giving a good introduction to what we&#8217;re releasing:</p>
<p><center><iframe width="560" height="315" src="http://www.youtube.com/embed/tygZ2A8rytQ" frameborder="0" allowfullscreen></iframe></center></p>
<p>To get started feel free to visit the Khan Academy Computer Science site:</p>
<blockquote><p><a href="http://www.khanacademy.org/cs">http://www.khanacademy.org/cs</a></p></blockquote>
<p>Explore, play around, and build something!</p>
<blockquote><p>Jamie Wong, who worked on the CS platform this summer, has also <a href="http://jamie-wong.com/2012/08/14/khan-academy-computer-science/">written up a blog post</a> on his experience developing the platform.</p></blockquote>
<h3>Methodology</h3>
<p>Earlier this year I was working on an iteration of the CS platform which was heavily focused on structured curriculum leading towards exploratory projects.</p>
<p>Until I saw <a href="http://worrydream.com/">Bret Victor</a>&#8216;s <a href="http://vimeo.com/36579366">mind-blowing talk on using a responsive programming environment</a>.</p>
<p>After watching that video I couldn&#8217;t shake the feeling that what he presented was a fundamentally different way of approaching how to interact with, and learn how to, code.</p>
<p>In an environment that is truly responsive you can completely change the model of how a student learns: rather than following the typical write -> compile -> guess it works -> run tests to see if it worked model you can now immediately see the result and intuit how underlying systems inherently work without ever following an explicit explanation.</p>
<p>When code is so interactive, and the actual process of interacting with code is in-and-of-itself a learning process, it becomes very important to put code front-and-center to the learning experience.</p>
<p>Rather than starting Computer Science education off by explicitly teaching how a computer works or fundamental programming concepts (like variables, logic, control structures, etc.) you put the student into code of graduated complexity and encourage them to manipulate, explore, and write their own programs.</p>
<p>Once they start to explore and figure out things for themselves then they can begin to dig into all the explanatory tutorials and documentation that are provided to clarify how things work.</p>
<p>The desire to learn and understand can be a powerful accelerant for students and it&#8217;s something that <em>is completely missing from almost all Computer Science education</em>.</p>
<p>When I look back at how I became interested in programming, or ask other programmers about how they started to program, the answer is very frequently: &#8220;I was given a [Basic/QBasic/Python] compiler and a bunch of programs and I wanted to understand how it all worked so I could write my own!&#8221; It was only after digging in to the code that the student wanted to understand how to tackle certain programmatic challenges &#8211; but they then did so with great gusto!</p>
<p>The Khan Academy Computer Science program is a distillation of this process into it&#8217;s purest form: <strong>Directly encouraging experimentation, exploration, and creativity as a direct gateway to deeper learning.</strong></p>
<h3>How do we teach?</h3>
<p>On the site we provide dozens of programs, at a variety of skill levels, across a number of disciplines (including art, mathematics, and science). We wanted students to find the niche programs that could capture their excitement while also being able to provide a direct line from normally theoretical concepts (such as algebra, geometry, or physics) towards direct evidence of their utility in a tangible medium that the student can control.</p>
<p>We provide a number of tutorials that cover concepts that come up frequently in the programs that we&#8217;ve developed (from programming concepts like variables and conditionals to other concepts inherent to the medium such as drawing and animation). These tutorials should cover most of the questions that students have when they&#8217;re just beginning to program and can be accessed at a student&#8217;s leisure.</p>
<p>I&#8217;ve <a href="http://ejohn.org/blog/javascript-as-a-first-language/">talked before</a> about how I think that JavaScript, and specifically learning how to code in-browser, is inherently a better way of learning. Reducing the complexity of getting started down to zero will result in more people learning. Additionally the ubiquity of JavaScript only serves to educate people in a language that will be generally useful.</p>
<p>I also feel that learning how to code in an environment where the output is visual and highly enticing can better excite the student towards wanting to produce, and thus learn, more. I feel that purely textual coding environments (or coding environments that favor textual output over visual output) serve as a highly uninteresting introduction to programming.</p>
<p><center><a href="http://www.khanacademy.org/cs/browse/all-programs"><img src="http://ejohn.org/files/cs-projects.sm.png"/></a></center></p>
<p>At a fundamental level we want the students using the platform to be self-directed learners, choosing to drive the direction of their education in a way that best suits their interests.</p>
<p>We&#8217;ve taken some steps to provides students with some level of possible direction which they could follow, if interested. For example when viewing an introductory program that only does basic drawing we encourage the student to explore variables or animation &#8212; ways of bringing their program &#8220;to life&#8221; which simultaneously getting them excited about attempting to learn those, comparatively, complex subjects.</p>
<p>We already have a number of programs for students to explore, and we will be adding many more (highlighting some of the best from the community as well). With that being said we don&#8217;t want to be the sole arbiter of programs that a student might find to be interesting. For this reason we&#8217;re working to put community, sharing, and collaboration as pillars of the platform.</p>
<p>We want students to work up to the point at which they feel comfortable writing their own projects. We&#8217;ve already seen some pretty phenomenal output from both people here at Khan Academy  and from middle-school-aged students who&#8217;ve never programmed before.</p>
<p>Over this past summer we held a number of &#8220;<a href="http://www.khanacademy.org/about/discovery-lab">Discovery Lab</a>&#8221; sessions at Khan Academy in which kids of roughly middle school age did a number of learning activities. We had the opportunity to watch them interact with the Computer Science content and were blown away with what they created. In the first hour they were designing and drawing their own characters, in the second they had added in variables and were starting animations, by the end of the third hour they had functional draw loops and were adding in logic to control the animations.</p>
<p>We&#8217;ve never seen students of that age progress so quickly through such challenging concepts. It was noted that they were moving faster than most college age students taking a normal intro Computer Science course.</p>
<p><img src="http://ejohn.org/files/cs-creeper.sm.png" style="float:right; margin: 0 0 0 10px;"/></p>
<p>One project that I particularly enjoyed was made by a student who really loved Minecraft. He designed some characters from the game (drawing them using a number of points and rectangles) and then added in some user interaction. He made it so that you could control the the position of a creeper by moving your mouse, as it came closer to &#8220;Steve&#8221; he would start to hiss and blink, upon hitting Steve he would explode into a firey cloud. This was done over the course of maybe four hours and two days.</p>
<p>To say that I&#8217;m excited to see how people are going to use this platform is an understatement.</p>
<h3>Coding Environment</h3>
<p>The environment is built around a two-panel view: The left being an <a href="http://ace.ajax.org/">Ace editor</a> and the right being a canvas.</p>
<p>All of the user&#8217;s code is written using JavaScript and uses <a href="http://processingjs.org/">Processing.js</a> to generate all the graphics.</p>
<p><center><img src="http://ejohn.org/files/cs-random-screenshot.sm.png"/></center></p>
<p>All code is executed in real-time. Not only is the code re-run (which is relatively easy to do, just re-evaling the code) but the code that you change is live dynamically injected into the runtime &#8212; this gives you the ability to change variables, colors, or even functions on the fly without the program ever restarting.</p>
<p>We did a lot to try and take advantage of the real-time nature of the environment, giving the user all sorts of tools to adjust the code, and thus the state of the program as well.</p>
<p>We have a number picker:<br />
<img src="http://ejohn.org/files/cs-number-picker-full.png"/></p>
<p>We have a color picker:<br />
<img src="http://ejohn.org/files/cs-color-picker-full.png"/></p>
<p>and we even have an image picker (using images from the always-excellent <a href="http://www.lostgarden.com">Lostgarden.com</a>):<br />
<img src="http://ejohn.org/files/cs-image-picker-full.png"/></p>
<p>We&#8217;ve also put a lot of work into the error correction. We build off of the existing linting that we do to try and provide extra levels of hinting. We do spelling correction, provide argument suggestions, and try to make suggestions for common beginner mistakes.</p>
<p><center><img src="http://ejohn.org/files/cs-error.png"/></center></p>
<p>In our experience students who&#8217;ve never programmed before can be left unattended using this environment and be able to resolve almost all of their issues via the error hints or the tutorials.</p>
<p>As it turns out it&#8217;s really, <em>really</em>, hard to build the real-time execution environment that Bret Victor proposed, in practice &#8212; even harder in a browser. I plan on writing many posts about the nuts-and-bolts of the implementation when we release the code-and-editor as Open Source (which should be soon).</p>
<p>To make the environment we have to use a lot of features that only the latest browsers support. For this reason we are only actively supporting Chrome, Firefox, Safari, and IE 9+. Chrome, Firefox, and Safari will have the best experience as they also have Web Worker support (which we make extensive use of).</p>
<p>Thankfully we&#8217;re able to make this hard call as less than 6% of our user base fails to match the above criteria &#8212; and that number is quickly shrinking.</p>
<blockquote><p>Side note: One area of the implementation that would benefit from an Open Source library is some form of in-browser, pure-JavaScript, ECMAScript 5 linter. We use <a href="http://www.jshint.com/">JSHint</a> right now and we&#8217;d really appreciate being able to enforce true strict mode (JSHint&#8217;s strict mode support is rather limited in nature).</p></blockquote>
<h3>Collaboration and Community</h3>
<p>With the Khan CS platform we wanted to provide an environment that effectively mimicked the best aspects of great programming communities like <a href="https://github.com/">Github</a>.</p>
<p>Students can always see the code associated with a project and it&#8217;s always displayed next to the output. Students can change any code they see and and save it to their own personal account (aka &#8220;forking&#8221; in the Github parlance).</p>
<p><center><img src="http://ejohn.org/files/cs-sharing.sm.png"/></center></p>
<p>(Note the authorship details and the &#8220;Based on&#8221; link with screenshot that shows up below a project that has been &#8220;forked&#8221; from another project.)</p>
<p>Community feedback and discussion is also large part of the benefit that we hope students will be able to derive from the platform. Students will be able to solicit feedback from others and have discussions within the context of their code. We&#8217;re not to the point of having line-level comments yet but we hope the initial discussion functionality will be very useful to everyone using the site.</p>
<p>To a large degree the Khan Computer Science platform is influenced by the Open Source communities that I&#8217;ve participated in: All the code is open, experimentation is encouraged, and feedback is easily provided. I feel that this particular environment is highly conducive to learning as you can easily see many ways of tackling a problem. You can also get feedback on your personal attempts, creating a tight feedback loop.</p>
<p>(I should note that we do have versioning baked in to the system as well but we haven&#8217;t exposed it yet, though probably will at some point.)</p>
<p>We also really wanted students to feel excited about sharing their work with others. We provide the ability to share it through traditional social media (Facebook, Twitter, and email) but also on the site and through their profile.</p>
<p><center><img src="http://ejohn.org/files/cs-profile.sm.png"/></center></p>
<p>On a student&#8217;s profile they have the ability to choose some explorations that they wish to explicitly share with others. We want students to take pride in their best work and feel open to sharing it with the world.</p>
<h3>Tutorials and Next Steps</h3>
<p>While students exploring the content of the platform will certainly learn some things simply by exploring and manipulating code, we wanted to go a step further and provide tutorials and a clear narrative to help students better understand some of the complex subject matter that they&#8217;re seeing.</p>
<p>The primary vehicle for learning is through the <a href="http://www.khanacademy.org/cs/tutorials/all-tutorials">tutorials</a> on the site. These are unique in that they both behave like a normal code editor but also as a &#8220;video&#8221; player. All of the tutorials include audio walkthroughs (playing live from <a href="http://developers.soundcloud.com">Soundcloud using their API</a>), combined with live playback from the presenter, right in the code editor itself.</p>
<p><center><a href="http://www.khanacademy.org/cs/tutorials/all-tutorials"><img src="http://ejohn.org/files/cs-video-screenshot.png"/></a></center></p>
<p>We wanted to have the playback take place directly in the editor to try and provide an experience for the student that was more immediate and tangible. Producing hard-coded video explanations or forcing the student to walk through step-by-step written instructions is both tedious and lacks interactivity. With this playback mechanism the student will be able to see the results live, exactly as they would always run in the editor, while also being able to pause the playback and manipulate, or copy, the code that they see. This ability to dig into the meat of a tutorial should serve to deepen, and reinforce, a student&#8217;s understanding of the subject matter.</p>
<p>In addition to the tutorials we have a large amount of <a href="http://www.khanacademy.org/cs/docs">documentation</a> on Processing.js and JavaScript, all of which is written up and available in a code editor (again, for further exploration). All documentation is available on a dedicated page and beneath every code editor, making it an easy reference for students.</p>
<p><center><a href="http://www.khanacademy.org/cs/docs"><img src="http://ejohn.org/files/cs-docs.png"/></a></center></p>
<p>Next to many of the projects that are on the site we also provide some suggested &#8220;Next Steps&#8221; that the students can follow for some deeper engagement and learning.</p>
<p><center><img src="http://ejohn.org/files/cs-next-steps.png"/></center></p>
<p>We don&#8217;t explicitly evaluate the student&#8217;s work here and instead we encourage them to share their work with others, providing an external motivator to try and write the best possible code they can. With the active and excited Khan Academy community that already exists students will be able to receive constructive feedback on their work and make a number of improvements thereon.</p>
<p>One question is obviously: How much &#8220;Computer Science&#8221; do we actually teach? Obviously, right now we&#8217;re not teaching very much in the way of traditional Computer Science content, we&#8217;ve placed far more focus onto the platform and feel that a lot can be gained from just what we&#8217;ve already built. We&#8217;re still very early on in the production of content and will be producing much more, of increasing complexity, over the upcoming weeks and months.</p>
<p>We decided that it was much more fruitful for us to tackle the most challenging problem that exists with Computer Science education first: Getting people excited about programming. If we can get people excited about programming, and build (or point them to) the resources they need to learn more then we will have been successful.</p>
<p>Eventually I think we&#8217;ll work to effectively replicate the materials one typically finds in a &#8220;Computer Science 101&#8243; but in a way that is far more engaging and self-paced than what you would find at a traditional university.</p>
<p>So what&#8217;s next? We want to work on providing even more direction and tooling around students writing larger projects. We want to provide easy APIs around storage, network connectivity, and dependencies that will allow for some fascinating projects. Additionally we want to improve peer-to-peer and mentor-student collaboration, finding ways of pairing struggling students with skilled developers. Finally we want to produce a lot more content of a wide range of difficulties and topics.</p>
<p>We&#8217;re only just getting started and how the community responds to this release will largely help to drive the direction of the platform as a whole. Feedback is most welcome!</p>
<h3>Thank Yous</h3>
<p>This is the culmination of a bunch of work by a number of people and I want to take this opportunity to thank them &#8212; without them this project would not have happened and would not have come out as well as it did.</p>
<p>Most importantly I want to thank <a href="http://jamie-wong.com/">Jamie Wong</a> and <a href="http://cakefordinner.com/">Jessica Liu</a> &#8212; both of whom worked this summer on the Computer Science platform and have both made tremendous contributions in ways that I couldn&#8217;t have even hoped for.</p>
<p><center><img src="http://www.khanacademy.org/images/headshots/interns/jamiew.png"/> <img src="http://www.khanacademy.org/images/headshots/interns/jessica.png"/></center></p>
<p>Jamie primarily worked on the Khan CS platform, providing a superb level of quality and scalability that we&#8217;ll be enjoying for a long time. He provided contributions above-and-beyond what was needed and even helped to improve some of our development processes at Khan Academy. His expertise has been a massive boon to the project, quickly escalating it to encompass functionality that we didn&#8217;t even hope we&#8217;d be able to provide. In the short time he&#8217;s been with the company he&#8217;s already made a tremendous impact upon the organization.</p>
<p>Jessica worked on creating Computer Science tutorials, meticulously researching methodologies and iterating after gathering user feedback. The structure and content of the Computer Science curriculum is largely of her design (if you view some of the CS tutorials you&#8217;re sure to enjoy much of her expertise and wit). She also worked on improving the usability of the editor and the curriculum, making it far easier for newbies to get up to speed. Her innate understanding of a new programmer&#8217;s mind, combined with her ability to execute on a solution that will aide them has made the platform an incredibly effective tool for self-paced learning.</p>
<p>I strongly hope to have the opportunity to work with both of them in the future.</p>
<p>I also want to thank everyone at Khan Academy for their input into the design process and their help in creating the awesome projects you see on the site. I especially want to thank Sal Khan, Shantanu Sinha, Ben Kamens, Jason Rosoff, Ben Komalo, Ben Alpert, Tom Yedwab, and Mathias Hiron for their help and advice in making the platform what it is today.</p>
<p>I also want to thank the teachers and students at the Khan Academy Discovery Lab for being such willing, and excited, participants in experimenting with the Computer Science platform. Your feedback was instrumental in identifying many issues that we were able to make much better as a result.</p>
<p>And so, on that note, I hope you will all enjoy the new <a href="http://www.khanacademy.org/cs">Khan Academy Computer Science</a> platform!</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/mq_cdZf25VY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/introducing-khan-cs/feed/</wfw:commentRss>
		<slash:comments>56</slash:comments>
		</item>
		<item>
		<title>Secret Omens: Book Update</title>
		<link>http://ejohn.org/blog/secret-omens/</link>
		<comments>http://ejohn.org/blog/secret-omens/#comments</comments>
		<pubDate>Wed, 11 Jul 2012 19:05:46 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5809</guid>
		<description><![CDATA[Jeff Atwood wrote up a post today on the merits of writing a technical book in this day-and-age and specifically called out my past post on programming book profits and my work-in-progress Secrets of the JavaScript Ninja. I wanted to give a brief status update on the book and how it&#8217;s going. I started the [...]]]></description>
				<content:encoded><![CDATA[<p>Jeff Atwood <a href="http://www.codinghorror.com/blog/2012/07/coding-horror-the-book.html">wrote up a post today</a> on the merits of writing a technical book in this day-and-age and specifically called out my past post on <a href="http://ejohn.org/blog/programming-book-profits/">programming book profits</a> and my work-in-progress <a href="http://jsninja.com/">Secrets of the JavaScript Ninja</a>.</p>
<p><img src="http://ejohn.org/files/ninja.74.jpg" style="float:right;margin-left: 10px;"/></p>
<p>I wanted to give a brief status update on the book and how it&#8217;s going. I started the book in early 2008 and was actually quite productive, finishing nearly the entire book that year (with some missing gaps that I fixed up in 2009). There was some work left to do to make it a better book but, honestly, I got caught up in coding and stopped focusing on writing. I had to prioritize my time and I chose to prioritize doing more development and focusing on my personal life. Some time last year Manning brought on a co-author, Bear Bibeault, to finish the book and get it out the door. He&#8217;s done a bunch of revision bringing it up-to-date and just the other week I finally wrote the preface. It&#8217;s in final revisions now and should be out-the-door <em>very soon</em>. This is a huge relief for me and it&#8217;s great that there&#8217;s one less thing to worry about.</p>
<p>To the point of Jeff&#8217;s post, I would absolutely not write a technical book again. It&#8217;s a tedious process and unless you LOVE writing and are really good at it (like <a href="http://www.nczonline.net/">Nicholas Zakas</a> or <a href="http://www.oreillynet.com/pub/au/156">Dave Flanagan</a>) then I suggest that you stick with the medium that is truly successful: Writing long-form articles/blog posts and possibly spinning them off into purchasable ebooks. (As an example, I&#8217;d point to <a href="http://perfectionkills.com/">Juriy Zaytsev</a> and <a href="http://www.quirksmode.org/">Peter-Paul Koch</a> both of whom could get any JavaScript position in the world purely based upon the quality of their articles and sites, without ever having written a book.)</p>
<p>I realized at some point in late 2008 that that&#8217;s really what I should&#8217;ve done with Secrets of the JavaScript Ninja but I was already neck-deep in the book with most of it complete. Ironically working on the book (or not working on it, however you look at it) actually compelled me to NOT blog more as every time I wanted to write a technical blog post I was forcing myself to make the decision &#8220;I&#8217;m writing about 1000 words on a technical matter, shouldn&#8217;t this just be going towards my uncompleted book?&#8221; and would just end up writing nothing as a result.</p>
<p>I do feel bad for, and apologize to, the people that pre-ordered hard copy version of my book over the years only to have to wait on a time scale comparable to George R. R. Martin&#8217;s writing schedule. Amusingly the book has been extremely successful as a <a href="http://www.manning.com/resig/">pre-order e-book at Manning.com</a> &#8211; it&#8217;s the best-selling MEAP book of all time. I&#8217;ve gotten numerous emails from readers who&#8217;ve gotten enormous benefit from the book, even in it&#8217;s rough form, and this has pleased me greatly.</p>
<p>I&#8217;m excited to finally have this book be out in the &#8220;wild&#8221;, as it were. It&#8217;s no longer (as Jeff put it) &#8220;permanently unfinished&#8221;.</p>
<p>I&#8217;ve included the preface from my book below, to give some more detail:</p>
<blockquote><p>When I started writing Secrets of the JavaScript Ninja four years ago, in early 2008, I saw a real need: There were no books providing in-depth coverage of the most important parts of the JavaScript language (functions, closures, and prototypes) nor were there any books that even attempted to cover writing truly cross-browser code. Unfortunately it appears as if the situation has not improved very well, which is truly surprising.</p>
<p>More and more development energy is being put into new technologies (such as the ones coming out of HTML 5 or the new versions of ECMAScript). There isn’t a point to diving into new technologies, or using the hottest libraries, if you don’t have a proper understanding of the fundamental characteristics of the JavaScript language. While the future for browser development is very bright the reality is that most development needs to make sure that code continues to work in the majority of browsers and for the majority of potential users.</p>
<p>Even though this book has been under development for a long time, thankfully it is not out of date. The book has been given a solid set of revisions by my co-author Bear Bibeault. He’s gone through and made sure that the material will continue to be relevant for a long time to come.</p>
<p>A major reason why this book has taken so long is largely due to the experience that I was drawing upon to write the material for the later chapters on cross-browser code. Much of my understanding of how cross-browser development happens in-the-wild has come from my work on the jQuery JavaScript library. As I was writing the later chapters on cross-browser development I realized that so much of jQuery’s core could be written differently, optimized, and made capable of handling a wider range of browsers.</p>
<p>Perhaps the largest change that came to jQuery, as a result of writing this book, was a complete overhaul from using browser-specific sniffing to using feature detection at the core of the library. This change made it so that jQuery could be used almost indefinitely, without assuming that browsers would always have specific bugs or be missing specific features.</p>
<p>As a result of these changes jQuery directly anticipated many of the improvements to browsers that have come during the past couple years: Google released the Chrome browser, the number of useragents have exploded as mobile computing has increased in popularity, Mozilla, Google, and Apple have gotten into a browser performance war, and Microsoft has finally started making substantial improvements to Internet Explorer. It can no longer be assumed that a single rendering engine (such as WebKit or Trident, in Internet Explorer) will always behave the same way. Substantial changes are occurring rapidly and are spread out to an ever-increasing number of users.</p>
<p>Using the techniques outlined in this book, jQuery’s cross-browser capabilities provide a fairly solid guarantee that code that you write with jQuery will work in a maximal number of browser environments. This guarantee has led to explosive growth in jQuery over the past four years, with it now being used in over 57% of the top 10,000 websites on the Internet, according to Builtwith.com.</p>
<p>The portions of this book that cover features that are relatively un-changing, such as code evaluation, with statements, and timers are continually being used in interesting ways. There are now a number of active programming languages that are built on top of, or compiled to, JavaScript: Such as CoffeeScript or Processing.js. These languages require complex language parsing, code evaluation, and scope manipulation in order to work effectively. While dynamic code evaluation has been maligned due to its complexity and potential for security issues, without it we would not have had the CoffeeScript programming language &#8211; which has gone on to influence the upcoming ECMAScript specification itself.</p>
<p>I’m personally making use of all of these features, even today, in my work at Khan Academy. Dynamic code evaluation in the browser is such a powerful feature: You can build in-browser programming environments and do crazy things like inject code into a live runtime. This can result in an extremely compelling way to learn computer programming and provide all sorts of capabilities that wouldn’t be possible in a traditional learning environment.</p>
<p>The future for browser development continues to be very strong and it’s largely due to the features encapsulated in JavaScript and in the browser APIs. Having a solid grasp of the most crucial parts of the JavaScript language, combined with a desire for writing code that’ll work in many browsers, will result in your code being elegant, fast, and ubiquitous.</p></blockquote>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/E40l_KTI-HQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/secret-omens/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>Image Similarity Search Wanted</title>
		<link>http://ejohn.org/blog/image-similarity-search-wanted/</link>
		<comments>http://ejohn.org/blog/image-similarity-search-wanted/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 21:44:31 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5804</guid>
		<description><![CDATA[I&#8217;ve been working on a few projects in my spare time and one service, in particular, would greatly benefit from a high quality image similarity search. I&#8217;ve been trying a number of the Open (and non-Open) Source tools (a great list of which is on Wikipedia here). Thus far none of the tools that I&#8217;ve [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been working on a few projects in my spare time and one service, in particular, would greatly benefit from a high quality image similarity search.</p>
<p>I&#8217;ve been trying a number of the Open (and non-Open) Source tools (a <a href="http://en.wikipedia.org/wiki/List_of_CBIR_engines">great list of which is on Wikipedia here</a>). Thus far none of the tools that I&#8217;ve found are of high-enough quality to warrant further pursuit. They either do simple color comparison, basic wavelet/outline comparison, or some form of hashing &#8211; none of which appears to work very well beyond basic images. Some of the best algorithms are either caught up in University research programs (generally unreleased) or are available as corporate search engines.</p>
<p>In an ideal world I&#8217;d like something with the quality of TinEye (I&#8217;d even be open to using TinEye&#8217;s commercial services but they haven&#8217;t gotten back to me as of yet &#8211; I suspect that they&#8217;re mostly interested in dealing with large corporate clients).</p>
<p>In short: Does anyone have a lead on a high quality image similarity search tool (using <a href="http://en.wikipedia.org/wiki/Content-based_image_retrieval">Content-Based Image Retrieval</a>)? I&#8217;m open to Open Source, closed source, or even paid API service &#8211; as long as it works well.</p>
<p><strong>Note:</strong> I&#8217;m looking to use this on a private collection of images, so a service like Google Image Search (or TinEye&#8217;s normal commercial API) are not suitable alternatives &#8211; they both search images on the open web.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/sbXFHhvUJK4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/image-similarity-search-wanted/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>JavaScript as a First Language</title>
		<link>http://ejohn.org/blog/javascript-as-a-first-language/</link>
		<comments>http://ejohn.org/blog/javascript-as-a-first-language/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 19:04:28 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5792</guid>
		<description><![CDATA[At Khan Academy we&#8217;ve been investigating teaching Computer Science to students in some new and interesting ways. The most interesting aspect of which is that we&#8217;re likely going to be teaching them JavaScript as their first language. We&#8217;re in a very unique position as we&#8217;re primarily aiming to teach students who&#8217;ve been through our previous [...]]]></description>
				<content:encoded><![CDATA[<p>At <a href="http://www.khanacademy.org/">Khan Academy</a> we&#8217;ve been investigating teaching Computer Science to students in some new and interesting ways. The most interesting aspect of which is that we&#8217;re likely going to be teaching them JavaScript as their first language.</p>
<p>We&#8217;re in a very unique position as we&#8217;re primarily aiming to teach students who&#8217;ve been through our previous <a href="http://www.khanacademy.org/exercisedashboard?k">math and science-centric curriculum</a>. Because of this we can create some rather compelling exercises and projects that never would&#8217;ve been feasible otherwise.</p>
<p>The prospect of teaching the JavaScript language as a first language is actually really exciting. Teaching prototypal inheritance to experienced classical-inheritance-using developers is normally rather frustrating (and results in many libraries springing up attempting to replicate the classical style of inheritance in JavaScript, which is a whole realm of weirdness in-and-of itself). Teaching prototypal inheritance to someone who has never seen any form of inheritance before will decidedly be an easier task. The same goes for learning functional programming. JavaScript is a great language for experiencing functional programming and can be a major focus of our curriculum as a result.</p>
<p>As we&#8217;ve begun to look at the prospect of JavaScript-as-a-first-language a number of obvious warts stick out (as is obvious to anyone who has worked with JavaScript for any duration). To make sure that general warts don&#8217;t crop up we will be using some form of linting (either JSLint or JSHint or similar) in the code editor to give the users contextual information on what&#8217;s happening with their code and why they should be writing their code in a certain way.</p>
<p>We want to go beyond basic syntax tweaks though and find ways of using the language that&#8217;ll result in an easier learning experience. In particular there are two changes which will likely result in a much simpler on-ramp to learning.</p>
<p><strong>Note:</strong> These particular recommendations really only make sense if you&#8217;re teaching JavaScript to someone who has never seen the language before and is really only programming with a set of specific, well-coded, libraries. Obviously more will have to be taught in order bring the students up to the level of &#8220;see any random piece of cross-browser JavaScript code and understand what it does.&#8221;</p>
<h3>Type Coercion</h3>
<p>Type coercion is just a complete mess, as many many others have pointed out and as what Douglas Crockford typically teaches, as in <a href="http://www.amazon.com/gp/product/0596517742/ref=as_li_ss_tl?ie=UTF8&#038;tag=jspro-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0596517742">JavaScript: The Good Parts</a>.</p>
<p>It might make sense to discuss it far later in the education cycle&#8230; like after learning about prototypes, functional programming, and closures. Basically after everything that&#8217;s actually important.</p>
<div id="ig-sh-17" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">name === &quot;John&quot;</div></li>
</ol>	</div></div>
<p>The first change that I&#8217;m recommending is that the students will only ever see, and use, <code>===</code> (and <code>!==</code>). While using &#8216;<code>==</code>&#8216; does have the advantage of being syntactically shorter there is so much type coercion baggage attached to it as to make it an exercise in futility to try and teach early on in the learning of programming.</p>
<p>The one exception that might be worthwhile to teach later on is the case in which you wish to see if a variable contains a null or undefined value. This can be done easily with a simple <code>someVar == null</code> check and is likely the one useful case of <code>==</code>. (Another noted exception is the browser bug in IE where <code>===</code> checks against Window objects will always return false, but it&#8217;s unlikely that we&#8217;ll cover such specific browser issues in our curriculum.)</p>
<p><strong>Falsy Values</strong></p>
<p>For the same reasons that <code>==</code> can be messy, so can falsy values. Enforcing strict boolean checks would result in less edge cases but would certainly result in longer code. Perhaps education of falsy values can be limited to booleans, null, and undefined with number and string falsy values left for a later exercise. </p>
<h3>Function Declarations</h3>
<p>Perhaps the most interesting change that we can make is a rather subtle one, but it&#8217;s eschewing normal function declarations for creating anonymous functions and assigning them to a variable.</p>
<div id="ig-sh-18" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// Don't do this:</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">function getData() { }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// Do this instead:</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var getData = function() { };</div></li>
</ol>	</div></div>
<p>There are a number of good habits that are instilled when you use this particular technique.</p>
<ul>
<li>Makes it easier to understand &#8220;functions as an object&#8221;. I&#8217;ve found that when you show new developers a function being assigned to a variable it suddenly becomes much more obvious that a function is actually an object and can be manipulated as such (and that a function can be passed as an argument to another function). Thus students are advanced along the path towards a better understanding of functional programming.</li>
<li>It enforces good semicolon habits. Traditional function declaration is the only situation in which semicolons aren&#8217;t needed (save for conditional statements and loops, naturally) and it makes it much more obvious when they&#8217;re required all the time.</li>
<li>Doesn&#8217;t have much of the baggage <a href="https://developer.mozilla.org/en/JavaScript/Reference/Scope_Cheatsheet">traditionally associated with functions and scope</a>.</li>
</ul>
<h3>Block Scope</h3>
<p>This is the remaining area that&#8217;ll certainly be a challenge for any introductory student to understand and yet I don&#8217;t see a particularly good solution here. The issue of variables declared within for loops hoisting up is more than enough to make most developers heads spin. I&#8217;ll have to see if we can&#8217;t come up with some intuitive ways of explaining how variable declaration works (and combining it with vigilant lint enforcement) rather than having a purely technical solution.</p>
<p>(While <code>(function(){ ... })();</code> is a solution I&#8217;m skeptical that we&#8217;ll be able to teach that early-enough on as to make it worthwhile.)</p>
<h2>JavaScript as a  First Language</h2>
<p>It should be noted that while we&#8217;re starting with JavaScript as a first language &#8211; largely due to its ubiquity, desirability in the larger workforce, lack of prior installation requirements, and ability to create something that&#8217;s easy to share with friends &#8211; we&#8217;re not going to be myopic and only focus on JavaScript. There are so many things that can be learned from other languages, not to mention entire skillsets that aren&#8217;t terribly relevant to in-browser JavaScript, that it behooves us to try and bring as much of them into our curriculum as possible.</p>
<p>I talk a little bit more about our choice to use JavaScript and some of the browsers that we&#8217;ll want to support in our development in the <a href="http://www.youtube.com/watch?v=k0Fi8EnSInE">following video</a>:</p>
<p><iframe width="640" height="360" src="http://www.youtube.com/embed/k0Fi8EnSInE" frameborder="0" allowfullscreen></iframe></p>
<p>By all accounts I want to try and avoid any features that would cause cross-browser weirdness to spring up. As a result we&#8217;ll be making extensive use of libraries (for drawing to a canvas or manipulating the DOM) and using only JavaScript language features that work consistently in the browsers that we end up supporting.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/Y4CgYR4Z4bc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/javascript-as-a-first-language/feed/</wfw:commentRss>
		<slash:comments>82</slash:comments>
		</item>
		<item>
		<title>Khan Exercise Rewrite</title>
		<link>http://ejohn.org/blog/khan-exercise-rewrite/</link>
		<comments>http://ejohn.org/blog/khan-exercise-rewrite/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 19:33:22 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5786</guid>
		<description><![CDATA[Today we&#8217;re pushing live a complete rewrite of the Khan Academy Exercise framework (live demo). A big push at Khan Academy has been to write more-and-more exercises for students to practice with. Naturally, to increase the number of exercises that we have, we needed to make it easier for team members, and casual committers, to [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/jeresig/5984905975/" title="Khan Exercise Framework Deployed by John Resig, on Flickr"><img src="http://farm7.static.flickr.com/6144/5984905975_1f9b68ff98_m.jpg" width="240" height="150" alt="Khan Exercise Framework Deployed" style="float:right;margin:0 0 10px 10px;"></a></p>
<p>Today we&#8217;re pushing live a complete rewrite of the <a href="https://github.com/Khan/khan-exercises">Khan Academy Exercise framework</a> (<a href="http://khanacademy.org/exercisedashboard">live demo</a>).</p>
<p>A big push at <a href="http://khanacademy.org/">Khan Academy</a> has been to write more-and-more exercises for students to practice with. Naturally, to increase the number of exercises that we have, we needed to make it easier for team members, and casual committers, to write them.</p>
<p>When I was first looking in to Khan Academy I did a bunch of digging through their code base (<a href="https://khanacademy.kilnhg.com/Repo/Website/Group/stable/Files">which is Open Source</a>) and noticed that a lot of effort was going in to writing exercises. Interestingly all the exercises were being written in pure JavaScript and were dependent upon the server component in order to run properly. To me this seemed like a massive barrier to entry.</p>
<h2>Brand New Framework</h2>
<p>When I started just over two months ago I immediately went about rewriting the framework to use semantic HTML and not rely upon any server-side components whatsoever. To provide an example of the change that was made here is one particular exercise, Significant Figures 1, <a href="https://khanacademy.kilnhg.com/Repo/Website/Group/stable/File/javascript/exercises/significant_figures_1.js?rev=tip">written for the old framework</a> and <a href="https://github.com/Khan/khan-exercises/blob/master/exercises/significant_figures_1.html">written for the new framework</a>. You can view <a href="http://khanacademy.org/exercises?exid=significant_figures_1">the live version</a> of the exercise, as well.</p>
<p><center><a href="http://www.flickr.com/photos/jeresig/5985482092/" title="Khan Exercise Code Comparison by John Resig, on Flickr"><img src="http://farm7.static.flickr.com/6012/5985482092_58971521ca.jpg" width="206" height="500" alt="Khan Exercise Code Comparison"></a><br/>Significant Figures 1 went from 191 lines of code down to 58.</center></p>
<p>Note the dramatic lack of &#8220;code&#8221; &#8211; most logic is encapsulated and reduced to a series of variable declarations (some with minimal logic). Additionally utility functions were made significantly more useful, and generic, shared across exercises (some of this was done in the old framework but a complete rewrite allowed us to find areas of obvious overlap).</p>
<p>The result of the new framework is an interesting mix of semantic markup and logic &#8211; wrapped in a form of highly specialized templating. Tons of details regarding the specifics of the framework can be found in the <a href="https://github.com/Khan/khan-exercises/wiki/Writing-Exercises:-Home">Writing Exercises tutorial</a>.</p>
<p>In short, some of the cool new features of this framework include:</p>
<ul>
<li>A full module system for dynamically loading specific utilities (such as graphing).</li>
<li>A <a href="https://github.com/Khan/khan-exercises/blob/master/utils/tmpl.js">brand new templating framework</a>, including templating inheritance, that makes it easy to reduce repeated code in exercises (<a href="https://github.com/Khan/khan-exercises/wiki/Writing-Exercises:-Formatting">some examples</a>).</li>
<li>A <a href="https://github.com/Khan/khan-exercises/blob/master/utils/graphie.js">brand new graphing framework</a> (written by Ben Alpert, named &#8216;Graphie&#8217;) that&#8217;s built on top of Raphael. This framework provides a simple API for creating all sorts of graphs and charts, it&#8217;s used extensively throughout the exercises.</li>
<li>An extensible plugin system for creating new <a href="https://github.com/Khan/khan-exercises/wiki/Writing-Exercises:-Answer-Types">answer types</a> (to expand beyond basic multiple choice or fill in the blank).</li>
</ul>
<p>Of course, that&#8217;s saying nothing of the actual user interaction as well. Most of the new framework&#8217;s logic is contained on the client-side and is generated directly off of <a href="https://github.com/Khan/khan-api">Khan Academy&#8217;s REST API</a>.</p>
<p>By moving logic to the client-side we&#8217;re able to have a much more interactive experience (doing all problem generation on the client-side, doing Ajax-y background submissions, things of that sort).</p>
<h2>Testing</h2>
<p>A big concern for us, with this rewrite, was to ensure that the quality and integrity of exercises was maintained well into the future. We wanted to make sure that the content of the exercises were correct and that regressions do not occur over time.</p>
<p>In fact we have three levels of testing:</p>
<ol>
<li>We have <a href="https://github.com/Khan/khan-exercises/tree/master/utils/test">unit tests for our modules and utility functions</a> (ensures that stuff like the templating will continue to work correctly).</li>
<li>We have an interactive interface for generating <a href="https://github.com/Khan/khan-exercises/tree/master/test/exercises">unit tests</a> for any given exercise (details below).</li>
<li>We have a &#8220;Report a Problem&#8221; interface for sending post-deployment issues directly to our bug tracker.</li>
</ol>
<p>The second stage is particularly interesting. On a fundamental level it&#8217;s hard to unit test something as complex as an exercise. While we can ensure that they still work at a functional level we can&#8217;t verify if the problems make sense, or if graphs look correct, or if it&#8217;s even possible to pick the right answer.</p>
<p>For these reasons we&#8217;ve introduced a new testing interface in which we use human developers as unit testers. When in test mode an additional panel is displayed asking the user to provide additional details regarding wether the problem is working correctly, or not. <a href="https://github.com/Khan/khan-exercises/wiki/Testing-Exercises">We ask them</a> to really dig into the exercises and make sure that they&#8217;re working correctly, hints are being displayed properly, and other things of that nature.</p>
<p><center><a href="http://www.flickr.com/photos/jeresig/5985481938/" title="Khan Exercise Testing by John Resig, on Flickr"><img src="http://farm7.static.flickr.com/6003/5985481938_ab834e3c42.jpg" width="500" height="351" alt="Khan Exercise Testing"></a></center></p>
<p>All of this information is collected and distilled into a piece of JavaScript code that is dropped into our <a href="https://github.com/Khan/khan-exercises/tree/master/test/exercises">test suite</a>, all pushed into QUnit. At the moment we have around 2414 unit test collections with over 10,000 assertions.</p>
<p><center><a href="http://www.flickr.com/photos/jeresig/5984923703/" title="Khan Exercise Test Dump by John Resig, on Flickr"><img src="http://farm7.static.flickr.com/6017/5984923703_2496715189_m.jpg" width="240" height="215" alt="Khan Exercise Test Dump"></a></center></p>
<p>At the moment we&#8217;re working on ways of having better reporting and integration with our development process, for all those unit tests.</p>
<h2>Development Process</h2>
<p>I&#8217;m rather pleased with how the overall development process worked out. We actively kept both the code open (it&#8217;s up on Github and it&#8217;s MIT licensed) and the process open as well. We&#8217;ve had contributions from over twice as many outside contributors than members of the Khan Academy team (although the vast majority of the development was done by members of the team).</p>
<p>We have a <a href="https://github.com/Khan/khan-exercises/wiki/Getting-Involved">detailed Getting Involved guide</a> that explains how exactly anyone can participate in the development of the framework (or in the authoring of new exercises).</p>
<p>Predominantly we&#8217;ve been coordinating through <a href="http://www.hipchat.com/g2m3UVDtY">a public HipChat room</a>, using the <a href="https://github.com/Khan/khan-exercises/issues">Github Issue Tracker</a>, and managing all the exercise work through a series of Google Spreadsheets.</p>
<p>We&#8217;re going to be transitioning now into creating a ton more exercises and we&#8217;d love to have even more help from the community. There is a ton of information on <a href="https://github.com/Khan/khan-exercises/wiki/Getting-Involved">how to get involved</a> in the <a href="https://github.com/Khan/khan-exercises/wiki">wiki</a>.</p>
<h2>Next Steps and Thanks</h2>
<p>There are a few things that we&#8217;re looking to do in the near future: Bring offline support to the exercises (for those with spotty internet connections or those using the upcoming iPad/Android application), client-side translation of content into other languages, and exercise answer checking using Node.js and JSDOM.</p>
<p>I also want to take this opportunity to thank everyone at Khan Academy, and all the community contributors, for helping to make this project happen. I especially want to thank Marcia Lee, Ben Alpert, Jeff Ruberg, Igor Terzic, Omar Rizwan, and Ben Kamens for their help in getting this out the door.</p>
<p>I should also mention that <a href="http://hire.jobvite.com/CompanyJobs/Careers.aspx?k=JobListing&#038;c=qd69Vfw7">Khan Academy is hiring devs</a>. We&#8217;re looking for both server/client devs (Python/JavaScript) and also mobile devs (iOS and Android).</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/ogLAcLijUBw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/khan-exercise-rewrite/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Random Khan Exercises</title>
		<link>http://ejohn.org/blog/random-khan-exercises/</link>
		<comments>http://ejohn.org/blog/random-khan-exercises/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 19:06:34 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5771</guid>
		<description><![CDATA[We&#8217;re taking an innovative new approach to providing students with exercises in the new Khan Academy exercise framework (which will be released for beta testing soon). In the old framework a problem would be randomly generated and provided to the user. This would result in a near-infinite number of randomly generated problems. This ends up [...]]]></description>
				<content:encoded><![CDATA[<p>We&#8217;re taking an innovative new approach to providing students with exercises in the <a href="http://github.com/khan/khan-exercises">new Khan Academy exercise framework</a> (which will be released for beta testing soon). In the old framework a problem would be randomly generated and provided to the user. This would result in a near-infinite number of randomly generated problems.</p>
<p>This ends up being a double-edged sword. While it&#8217;s great to provide a ton of problem variety to the students it&#8217;s fundamentally tricky as we want to have a manageable sample size of problems so that we can analyze student behavior and responses. For this reason we want to reduce the pool of possible problems to a more-manageable size (like about 200 or so &#8211; we&#8217;ll experiment with exact figures as time goes by). Most students will only do about 10-20 problems before moving on (since we define a &#8216;streak&#8217; as having completed 10 problems in a row correctly) &#8211; although we want to provide enough of a pool to allow adventurous users to explore more.</p>
<p>Having a smaller pool size creates another issue though: Potential for student overlap. If there&#8217;s one thing that we&#8217;ve learned so far it&#8217;s that students are quite resourceful and identify patterns very quickly. They will realize if they start on the same problem together and if the problems go in the same order.</p>
<p>On top of this we need to make it so that every time the student hits the exercise they are presented with the same exact series of exercises. The first problem will always be the same &#8211; and the 50th problem will always be the same for that user. (This will allow us to reproduce the problems at a later date, showing them their problems/answers or analyzing the results.)</p>
<p>Thus we need two pieces of information to determine which problem should be presented to a user: The user&#8217;s ID and the problem # that they&#8217;re currently tackling.</p>
<p>We start by placing the user into a simple &#8220;bin&#8221;: We take the <a href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC32</a> of the student&#8217;s ID and mod 200 to start the user at one of the 200 possible exercises. (We picked CRC32 as it&#8217;s a simple function and we only need a basic level of granularity in the results.) Next we use the CRC32 to figure out how the user should jump through the exercises.</p>
<p>We can&#8217;t jump through the exercises 1 by 1, since the students will instantly recognize that pattern, so we have to take a random approach &#8211; one developed by Khan Academy intern <a href="https://plus.google.com/101013822660106280579/posts">Ben Alpert</a>.</p>
<p>We start with a pool of prime numbers (the first 23 primes, to be exact) and use the user&#8217;s CRC32 to determine which of those primes will become the &#8220;jump distance&#8221; for that user.</p>
<p>For example:</p>
<div id="ig-sh-19" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var primes = [3, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97];</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var num = crc32(&quot;jeresig&quot;);</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// num = 1411847358</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var problemNum = num % 200;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// problemNum = 158</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var jumpNum = primes[ num % primes.length ];</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">// jumpNum = 71</div></li>
</ol>	</div></div>
<p>Thus when I visit a particular problem I will start at problem # 158, then go to problem 29, then problem 100, then problem 171, etc. On the other hand, if user &#8220;jeresig2&#8243; visits the same problem they start at problem 171 then visit problem 182, 193, 4, etc.</p>
<p>(Note that we leave out 2 and 5 to avoid creating a circular loop of exercises &#8211; 2 will result in 100 repeating exercises, 5 will result in 40 repeating exercises. Of course we could just make the number of exercises prime to achieve a similar result &#8211; we&#8217;ll see!)</p>
<p>Even though we&#8217;re not using any built-in random number generator in this process, the distribution of chosen problems appears to be similar to a random distribution (since we&#8217;ve effectively implemented one ourselves):</p>
<p><a href="http://www.flickr.com/photos/jeresig/5954863467/" title="Khan Problem Probability Distribution by John Resig, on Flickr"><img src="http://farm7.static.flickr.com/6017/5954863467_4b415bd2fc_b.jpg" width="674" height="264" alt="Khan Problem Probability Distribution"></a></p>
<p>To re-emphasize: We&#8217;re not trying to stop problem overlap &#8211; in fact we want overlap to occur, to give us data to study &#8211; but a lack of repeatable patterns has definitely been arrived at here.</p>
<p>We chose a collection of 23 primes because it is sufficiently large &#8211; but it also doesn&#8217;t divide into 200 cleanly (giving users that might have an identical starting position a different jump amount).</p>
<p>Also note that in the final solution we&#8217;re going to be combining the user&#8217;s ID with the name of the current problem &#8211; so that even if, somehow, two students end up with identical start positions and jump rates on one exercise they will have a different start position and jump rate on other exercises.</p>
<p>If all goes well we&#8217;ll be opening up the new exercise rewrite for beta testing within the next week or two.</p>
<blockquote><p><strong>Note:</strong> I&#8217;ve been posting interesting dev updates over <a href="https://plus.google.com/115675748062237570841/posts">on Google Plus</a>. Feel free to follow me there if you wish to find out more about what I&#8217;m working on with Khan Academy or jQuery.</p></blockquote>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/h6wWpeK7Q1Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/random-khan-exercises/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>jQuery 1.6 and .attr()</title>
		<link>http://ejohn.org/blog/jquery-16-and-attr/</link>
		<comments>http://ejohn.org/blog/jquery-16-and-attr/#comments</comments>
		<pubDate>Fri, 13 May 2011 14:04:47 +0000</pubDate>
		<dc:creator>John Resig</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5766</guid>
		<description><![CDATA[jQuery 1.6 and 1.6.1 are out the door. Congrats to the team and everyone that was involved with the release! A relatively controversial change in 1.6 was regarding how attributes and DOM object properties were handled. In 1.6 we wanted to take the major step of completely separating the two, allowing us to create an [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://blog.jquery.com/2011/05/03/jquery-16-released/">jQuery 1.6</a> and <a href="http://blog.jquery.com/2011/05/12/jquery-1-6-1-released/">1.6.1</a> are out the door. Congrats to the team and everyone that was involved with the release!</p>
<p>A relatively controversial change in 1.6 was regarding how attributes and DOM object properties were handled. In 1.6 we wanted to take the major step of completely separating the two, allowing us to create an <code>.attr()</code> method that wasn&#8217;t quite so mealy-mouthed with regards to how attributes were handled. We did this in 1.6 because we felt that it was a substantial change (we only do major changes in the 1.x major releases of jQuery) and had the possibility of affecting people.</p>
<p>We did a considerable amount of testing on the code and we were quite confident that the amount of problems that people would encounter, while upgrading, would be quite minimal. The biggest pain points, we surmised, would be regarding how boolean attributes were handled (attributes like &#8220;disabled&#8221; or &#8220;selected&#8221;). However most of this would be mitigated and would likely have worked fine for users that consistently used <code>.attr()</code> to access and update their attributes.</p>
<p>After making the changes, and publishing 1.6, there were enough complaints that we had changed the API to cause us to reconsider and return <code>.attr()</code> to its sometimes-attribute, sometimes-property, state.</p>
<p>jQuery is in an incredibly tricky position now (and has been for some time). We very rarely add features to the library, for fear of bloat and added API maintenance overhead, and are rarely able to make any sort of API change, for fear of preventing people from upgrading.</p>
<p>Thankfully even though we&#8217;ve reverted some of the changes in 1.6, we&#8217;ve done it in a way that still maintains the performance gains that we achieved with the 1.6 release.</p>
<p>I wanted to try and <a href="https://github.com/jquery/jquery/blob/master/src/attributes.js#L293">summarize the <code>.attr()</code> method</a>, to explain how it currently works in 1.6.1, but ended up writing up a sample function instead (note that this is a bit of an over-simplification, please <a href="https://github.com/jquery/jquery/blob/master/src/attributes.js#L293">read the code</a> for more details):</p>
<div id="ig-sh-20" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">function attr( elem, name, value ) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // Are we setting a value?</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; if ( value !== undefined ) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; // Make sure the element has the ability to set an attribute</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; if ( typeof elem.setAttribute !== &quot;undefined&quot; ) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If the user is setting the value to false</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( value === false ) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Completely remove the attribute</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elem.removeAttribute( name );</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Otherwise set the attribute value</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If the user is setting the value to true,</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Set it equal to the name of the attribute</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // (handles boolean attributes nicely)</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elem.setAttribute( name, value === true ? name : value );</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; </div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; // If it doesn't, then we're likely dealing with window or document</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; // (or some other object entirely)</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; } else {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elem[ name ] = value;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; </div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // Otherwise we're getting an attribute value</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // Check to see if the appropriate method exists</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // Also don't use getAttribute if a boolean property exists</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; } else if ( typeof elem.getAttribute !== &quot;undefined&quot; &amp;&amp;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typeof elem[ name ] !== &quot;boolean&quot; ) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; return elem.getAttribute( name );</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; </div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // If no getAttribute method is present, or if we</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // wish to access the boolean property instead of the</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; // attribute, then we fallback to the DOM object property</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; } else {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; &nbsp; &nbsp; return elem[ name ];</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; }</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">}</div></li>
</ol>	</div></div>
<p>Ironically this isn&#8217;t much shorter than the <a href="https://github.com/jquery/jquery/blob/master/src/attributes.js#L293">actual <code>.attr()</code> implementation</a>, I recommend that you check it out.</p>
<p>There&#8217;s a very good chance that your code, written targeting 1.5.2, will continue to work just fine in 1.6.1 using this particular technique.</p>
<p>However this point now begs the question: <strong>Why does .prop() exist?</strong></p>
<p>In short, for two reasons:</p>
<ol>
<li>There are legitimate use cases for interacting with some DOM properties (such as <code>nodeName</code>, <code>selectedIndex</code>, or <code>defaultValue</code>) and we want to provide a simple solution for accessing, and mutating, them.</li>
<li>Accessing properties through the <code>.attr()</code> method will be slightly slower than accessing them directly through <code>.prop()</code> (as <code>.attr()</code> calls <code>.prop()</code> internally in order to handle all property-related mutation).</li>
</ol>
<p>In jQuery 1.5.2, and older, in order to access a DOM property you would have to do something like this:</p>
<div id="ig-sh-21" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">var elem = $(&quot;#foo&quot;)[0];</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">if ( elem ) {</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp; &nbsp; index = elem.selectedIndex;</div></li>
<li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">}</div></li>
</ol>	</div></div>
<p>In 1.6+ you can just do:</p>
<div id="ig-sh-22" class="syntax_hilite">	<div class="code"><ol class="javascript" style="font-family:monospace;"><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">index = $(&quot;#foo&quot;).prop(&quot;selectedIndex&quot;);</div></li>
</ol>	</div></div>
<p>Summary: There&#8217;s a good chance that your code won&#8217;t be affected at all with the changes that&#8217;ve happened, especially so with the changes in 1.6.1, and jQuery now has a convenience method for handling DOM properties in a simpler, and slightly faster, manner.</p>
<p>Tangentially this reminds me of a common question that I hear: <strong>What will be in jQuery 2.0?</strong> I have no idea what will be in that release, should it ever arrive, but I do know what <em>won&#8217;t</em> be in it: A massive API change of any sort. Even when we make, relatively minor, API changes like in the 1.6 release the amount of negative feedback that we get is monumental. If we&#8217;ve learned anything after doing <a href="http://docs.jquery.com/Downloading_jQuery">31 releases</a> of jQuery it&#8217;s that people like having stability in their API and will cherish that over everything else.</p>
<p>I do want to thank the community though for being so vocal and working to communicate with the team so actively. Without the community&#8217;s communication and support it&#8217;s doubtful that the team would be able to continue operating.</p>
<p>I would like to take this opportunity to encourage everyone to <a href="http://docs.jquery.com/Getting_Involved">get involved</a> with the development of jQuery. We hold active discussions every day in IRC and hold public meetings once a week. We also post <a href="http://jquery.org/updates/category/core/">weekly status updates</a> if you wish to follow along. Right now we&#8217;re working on the 1.7 release of the library and are actively encouraging contributions and feedback. If you want to help ensure the quality and stability of the next release of jQuery, the best way to do so is to get involved. Hope to see you around the bug tracker.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/9ATQ-8y6Lyo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ejohn.org/blog/jquery-16-and-attr/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
	</channel>
</rss><!-- Dynamic page generated in 0.358 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-06-18 23:17:13 -->
