<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>tag:blog.danieljanus.pl,2019:category:javascript</id>
  <title>Daniel Janus – JavaScript</title>
  <link href="http://blog.danieljanus.pl/category/javascript/"/>
  <updated>2014-04-02T00:00:00Z</updated>
  <author>
    <name>Daniel Janus</name>
    <uri>http://danieljanus.pl</uri>
    <email>dj@danieljanus.pl</email>
  </author>
  <entry>
    <id>tag:blog.danieljanus.pl,2014-04-02:post:2048</id>
    <title>2048: A close look at the source</title>
    <link href="http://blog.danieljanus.pl/2048/"/>
    <updated>2014-04-02T00:00:00Z</updated>
    <content type="html">&lt;div&gt;&lt;p&gt;Dust has now mostly settled down on &lt;a href="https://gabrielecirulli.github.io/2048/"&gt;2048&lt;/a&gt;. Yet, in all the deluge of variants and clones that has swept through &lt;a href="https://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt;, little has been written about the experience of modifying the game. As I too have jumped on the 2048-modding bandwagon, it’s time to fill that gap, because, as we shall see, the code more than deserves a close look.&lt;/p&gt;&lt;p&gt;I’ll start with briefly describing my variant. It’s called &lt;a href="http://danieljanus.pl/wosg"&gt;“words oh so great”&lt;/a&gt; (a rather miserable attempt at a pun on “two-oh-four-eight”) and is a consequence of a thought I had, being an avid Scrabble player, after seeing the &lt;a href="http://joppi.github.io/2048-3D/"&gt;3D&lt;/a&gt; and &lt;a href="http://huonw.github.io/2048-4D/"&gt;4D&lt;/a&gt; versions: “what if we mashed 2048 and Scrabble together?” The answer just lended itself automatically.&lt;/p&gt;&lt;p&gt;Letters instead of number tiles, that was obvious. And you use them to form words. It is unclear how merging tiles should work: merging two identical tiles, as in the original, just wouldn’t make sense here, so drop the concept of merging and make the tiles disappear instead when you form a word. In Scrabble, the minimum length of a word is two, but allowing two-letter words here would mean too many words formed accidentally, so make it at least three. And 16 squares sounds like too tight a space, so increase it to 5x5. And there you have the modified rules.&lt;/p&gt;&lt;p&gt;I &lt;a href="https://github.com/nathell/wosg"&gt;cloned&lt;/a&gt; the Git repo, downloaded an English word list (&lt;a href="http://dreamsteep.com/projects/the-english-open-word-list.html"&gt;EOWL&lt;/a&gt;), and set out to work. It took me just over three hours from the initial idea to putting the modified version online and submitting a link to HN. I think three hours is not bad, considering that I’ve significantly changed the game mechanics. And, in my opinion, this is a testimony to the quality of Gabriele Cirulli’s code.&lt;/p&gt;&lt;p&gt;The code follows the MVC pattern, despite not relying on any frameworks or libraries. The model is comprised of the &lt;code&gt;Tile&lt;/code&gt; and &lt;code&gt;Grid&lt;/code&gt; classes, laying out the universe for the game as well as some basic rules governing it, and the &lt;code&gt;GameManager&lt;/code&gt; that implements the game mechanics: how tiles move around, when they can merge together, when the game ends, and so on. It also uses a helper class called &lt;code&gt;LocalStorageManager&lt;/code&gt; to keep the score and save it in the browser’s local storage.&lt;/p&gt;&lt;p&gt;The view part is called an “actuator” in 2048 parlance. The &lt;code&gt;HTMLActuator&lt;/code&gt; takes the game state and updates the DOM tree accordingly. It also uses a micro-framework for animations. The controller takes the form of a &lt;code&gt;KeyboardInputManager&lt;/code&gt;, whose job is to receive keyboard events and translate them to changes of the model.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;GameManager&lt;/code&gt; also contains some code to tie it all together — not really a part of the model as in MVC. Despite this slight inconsistency, the separation of concerns is very neatly executed in 2048’s code; I would even go so far as to say that it could be used as a demonstration in teaching MVC to people.&lt;/p&gt;&lt;p&gt;The only gripe I had with the code is that it violates the DRY principle in several places. Specifically, to change the board size to 5x5, I had to modify as many as three places: the HTML (it contains the initial definition for the DOM, including 16 empty divs making up the grid, which is unfortunate — I’d change it to set up the DOM at runtime during initialization); the model (instantiation of &lt;code&gt;GameManager&lt;/code&gt;); and the &lt;code&gt;.scss&lt;/code&gt; file from which the CSS is generated.&lt;/p&gt;&lt;p&gt;While on this topic, let me add that 2048’s usage of SASS is a prime example of its capabilities. It is very instructive to see how the sizing and positioning of the grid, and also styling for the tiles down to the glow, is done programmatically. I was aware of the existence of SASS before, but never got around to explore it. Now, I’m sold on it.&lt;/p&gt;&lt;p&gt;To sum up: 2048 rocks. And it’s fun to modify. Go try it.&lt;/p&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>tag:blog.danieljanus.pl,2011-07-08:post:meet-my-little-friend-createtree</id>
    <title>Meet my little friend createTree</title>
    <link href="http://blog.danieljanus.pl/meet-my-little-friend-createtree/"/>
    <updated>2011-07-08T00:00:00Z</updated>
    <content type="html">&lt;div&gt;&lt;p&gt;I’ve recently been developing an iPhone application in my spare time. I’m not going to tell you what it is just yet (I will post a separate entry once I manage to get it into the App Store); for now, let me just say that I’m writing it in JavaScript and HTML5, using [PhoneGap][1] and [jQTouch][2] to give it a native touch.&lt;/p&gt;&lt;p&gt;After having written some of code, I began testing it on a real device and encountered a nasty issue. It turned out that some of the screens of my app, containing a dynamically-generated content, sometimes would not show up. I tried to chase the problem down, but it seemed totally random. Finally, I googled up [this blog post][3] that gave me a clue.&lt;/p&gt;&lt;p&gt;My code was using jQuery’s &lt;code&gt;.html()&lt;/code&gt; method (and hence &lt;code&gt;innerHTML&lt;/code&gt; under the hood) to display the dynamic content. It turns out that, on Mobile Safari, using &lt;code&gt;innerHTML&lt;/code&gt; is highly unreliable (at least on iOS 4.3, but this seems to be a long-standing bug). Sometimes, the change just does not happen. I changed one of my screens, to build and insert DOM objects explicitly, and sure enough, it started to work predictably well.&lt;/p&gt;&lt;p&gt;So I had to remove all usages of &lt;code&gt;.html()&lt;/code&gt; from my app. The downside to it was that explicit DOM-building code is much more verbose than the version that constructs HTML and then sets it up. It’s tedious to write and contains much boilerplate.&lt;/p&gt;&lt;p&gt;To not be forced to change code, the above-quoted article advocates using a pure-JavaScript HTML parser outputting DOM to replace jQuery’s &lt;code&gt;.html()&lt;/code&gt; method. I considered this for a while, but finally decided against it — I didn’t want to include another big, complex dependency that potentially could misbehave at times (writing HTML parsers is &lt;em&gt;hard&lt;/em&gt;).&lt;/p&gt;&lt;p&gt;Instead, I came up with this:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;function&lt;/span&gt; &lt;span class="hljs-title function_"&gt;createTree&lt;/span&gt;(&lt;span class="hljs-params"&gt;tree&lt;/span&gt;) {
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;typeof&lt;/span&gt; tree === &lt;span class="hljs-string"&gt;&amp;#x27;string&amp;#x27;&lt;/span&gt; || &lt;span class="hljs-keyword"&gt;typeof&lt;/span&gt; tree === &lt;span class="hljs-string"&gt;&amp;#x27;number&amp;#x27;&lt;/span&gt;)
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createTextNode&lt;/span&gt;(tree);
    &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; tag = tree[&lt;span class="hljs-number"&gt;0&lt;/span&gt;], attrs = tree[&lt;span class="hljs-number"&gt;1&lt;/span&gt;], res = &lt;span class="hljs-variable language_"&gt;document&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;createElement&lt;/span&gt;(tag);
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; attr &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; attrs) {
        val = attrs[attr];
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; (attr === &lt;span class="hljs-string"&gt;&amp;#x27;class&amp;#x27;&lt;/span&gt;)
            res.&lt;span class="hljs-property"&gt;className&lt;/span&gt; = val;
        &lt;span class="hljs-keyword"&gt;else&lt;/span&gt;
            $(res).&lt;span class="hljs-title function_"&gt;attr&lt;/span&gt;(attr, val);
    }
     &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; i = &lt;span class="hljs-number"&gt;2&lt;/span&gt;; i &amp;lt; tree.&lt;span class="hljs-property"&gt;length&lt;/span&gt;; i++)
        res.&lt;span class="hljs-title function_"&gt;appendChild&lt;/span&gt;(&lt;span class="hljs-title function_"&gt;createTree&lt;/span&gt;(tree[i]));
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; res;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is very similar in spirit to &lt;code&gt;.html()&lt;/code&gt;, except that instead of passing HTML, you give it a data structure representing the DOM tree to construct. It can either be a string (which yields a text node), or a list consisting of the HTML tag name, an object mapping attributes to their values, and zero or more subtrees of the same form. Compare:&lt;/p&gt;&lt;p&gt;Using &lt;code&gt;.html()&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; html = &lt;span class="hljs-string"&gt;&amp;#x27;&amp;lt;p&amp;gt;This is an &amp;lt;span class=&amp;quot;red&amp;quot;&amp;gt;example.&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&amp;#x27;&lt;/span&gt;;
$(&lt;span class="hljs-string"&gt;&amp;#x27;#myDiv&amp;#x27;&lt;/span&gt;).&lt;span class="hljs-title function_"&gt;html&lt;/span&gt;(html);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using &lt;code&gt;createTree&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; tree = [&lt;span class="hljs-string"&gt;&amp;#x27;p&amp;#x27;&lt;/span&gt;, {},
            &lt;span class="hljs-string"&gt;&amp;#x27;This is an &amp;#x27;&lt;/span&gt;,
            [&lt;span class="hljs-string"&gt;&amp;#x27;span&amp;#x27;&lt;/span&gt;, {&lt;span class="hljs-string"&gt;&amp;#x27;class&amp;#x27;&lt;/span&gt;: &lt;span class="hljs-string"&gt;&amp;#x27;red&amp;#x27;&lt;/span&gt;}, &lt;span class="hljs-string"&gt;&amp;#x27;example.&amp;#x27;&lt;/span&gt;]];
$(&lt;span class="hljs-string"&gt;&amp;#x27;#myDiv&amp;#x27;&lt;/span&gt;).&lt;span class="hljs-title function_"&gt;empty&lt;/span&gt;().&lt;span class="hljs-title function_"&gt;append&lt;/span&gt;(&lt;span class="hljs-title function_"&gt;createTree&lt;/span&gt;(tree));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A side benefit is that it is just as easy to build up a tree dynamically as it is to create HTML, and the code often gets clearer. Note how the &lt;code&gt;createTree&lt;/code&gt; version above does not mix single and double quotes which is easy to mess up in the &lt;code&gt;.html()&lt;/code&gt; version.&lt;/p&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>tag:blog.danieljanus.pl,2011-05-15:post:a-quirk-with-javascript-closures</id>
    <title>A quirk with JavaScript closures</title>
    <link href="http://blog.danieljanus.pl/a-quirk-with-javascript-closures/"/>
    <updated>2011-05-15T00:00:00Z</updated>
    <content type="html">&lt;div&gt;&lt;p&gt;I keep running into this obstacle every now and then. Consider this example:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&amp;gt; q = []
[]
&amp;gt; &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; i = &lt;span class="hljs-number"&gt;0&lt;/span&gt;; i &amp;lt; &lt;span class="hljs-number"&gt;3&lt;/span&gt;; i++)
    q.&lt;span class="hljs-title function_"&gt;push&lt;/span&gt;(&lt;span class="hljs-keyword"&gt;function&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) { &lt;span class="hljs-variable language_"&gt;console&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;log&lt;/span&gt;(i); });
&amp;gt; q[&lt;span class="hljs-number"&gt;0&lt;/span&gt;]()
&lt;span class="hljs-number"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I wanted an array of three closures, each printing a different number to the console when called. Instead, each prints 3 (or, rather, whatever the value of the variable &lt;code&gt;i&lt;/code&gt; happens to be).&lt;/p&gt;&lt;p&gt;I am not exactly sure about the reason, but presumably this happens because the &lt;code&gt;i&lt;/code&gt; in each lambda refers to the &lt;em&gt;variable&lt;/em&gt; &lt;code&gt;i&lt;/code&gt; itself, not to its binding from the creation time of the function.&lt;/p&gt;&lt;p&gt;One solution is to enforce the bindings explicitly on each iteration, like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; (&lt;span class="hljs-keyword"&gt;var&lt;/span&gt; i = &lt;span class="hljs-number"&gt;0&lt;/span&gt;; i &amp;lt; &lt;span class="hljs-number"&gt;3&lt;/span&gt;; i++)
  (&lt;span class="hljs-keyword"&gt;function&lt;/span&gt;(&lt;span class="hljs-params"&gt;v&lt;/span&gt;) {
    q.&lt;span class="hljs-title function_"&gt;push&lt;/span&gt;(&lt;span class="hljs-keyword"&gt;function&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) { &lt;span class="hljs-variable language_"&gt;console&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;log&lt;/span&gt;(v); });
  })(i);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or use &lt;a href="http://documentcloud.github.com/underscore/"&gt;Underscore.js&lt;/a&gt;, which is what I actually do:&lt;/p&gt;&lt;pre&gt;&lt;code class="hljs javascript"&gt;&lt;span class="hljs-title function_"&gt;_&lt;/span&gt;([&lt;span class="hljs-number"&gt;1&lt;/span&gt;,&lt;span class="hljs-number"&gt;2&lt;/span&gt;,&lt;span class="hljs-number"&gt;3&lt;/span&gt;]).&lt;span class="hljs-title function_"&gt;each&lt;/span&gt;(&lt;span class="hljs-keyword"&gt;function&lt;/span&gt;(&lt;span class="hljs-params"&gt;i&lt;/span&gt;) {
  q.&lt;span class="hljs-title function_"&gt;push&lt;/span&gt;(&lt;span class="hljs-keyword"&gt;function&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;) { &lt;span class="hljs-variable language_"&gt;console&lt;/span&gt;.&lt;span class="hljs-title function_"&gt;log&lt;/span&gt;(i); });
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
</feed>
