<?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>https://johnresig.com</link>
	<description>JavaScript Programming</description>
	<lastBuildDate>Tue, 27 Aug 2019 13:15:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.0.8</generator>

<image><link>http://ejohn.org/</link><url>http://ejohn.org/files/jeresig-wordpress-sm.jpg</url><title>John Resig (ejohn.org)</title></image> 
	<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><feedburner:emailServiceId>JohnResig</feedburner:emailServiceId><feedburner:feedburnerHostname>https://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>10th Anniversary of jQuery</title>
		<link>https://johnresig.com/blog/10th-anniversary-of-jquery/</link>
		<comments>https://johnresig.com/blog/10th-anniversary-of-jquery/#comments</comments>
		<pubDate>Thu, 14 Jan 2016 17:17:07 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6271</guid>
		<description><![CDATA[Today marks the 10th anniversary of the release of jQuery. I announced it back at BarCamp NYC 2006 when I was still in college. It&#8217;s incredible to think of how far it&#8217;s come and just how many people have contributed to its success. To them I am forever grateful, thank you. Last year I wrote [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Today marks the 10th anniversary of the release of jQuery. I announced it back at <a href="https://johnresig.com/blog/barcampnyc-wrap-up/">BarCamp NYC 2006</a> when I was still in college. It&#8217;s incredible to think of how far it&#8217;s come and just how many people have contributed to its success. To them I am forever grateful, thank you.</p>
<p>Last year I wrote up an <a href="https://johnresig.com/blog/annotated-version-of-the-original-jquery-release/">annotated version of the original jQuery release</a> in which I dumped many of my thoughts regarding the work and influences that went into that very first release.</p>
<p>It&#8217;s fascinating to see what place jQuery continues to hold in the world of web development. When I originally created the library I wanted to scratch two personal itches: 1) To provide a simple interface for interacting with the DOM and 2) Reduce the number of cross-browser issues that exist during development. Thankfully we now live in a world which is much rosier than back in 2005, when I was writing jQuery. Most users are on evergreen browsers and most have access to the recent standards-specified technology. It pleases me that there is apparently still a place for simple API design in the world, as jQuery&#8217;s continued success attests. <a href="https://trends.builtwith.com/javascript/jQuery">jQuery is more popular than ever</a>, surprisingly enough! 77.8% of the top million web site on the web use it, which is astounding.</p>
<p>When I stepped down from the project in 2011, to focus on my transition to working at <a href="https://www.khanacademy.org/">Khan Academy</a>, a fantastic team stepped up to ensure that the project would continue to run smoothly. Reading <a href="https://medium.com/@sebmck/2015-in-review-51ac7035e272">Sebastian McKenzie&#8217;s recent blog post</a> about the struggles he&#8217;s faced in running the popular <a href="https://babeljs.io/">Babel</a> project struck close to home for me. It made me glad that I had put time and effort into building a team of amazing people who were happy to take over the project once I stepped down. jQuery would not be in the place it is today without them.</p>
<p>I&#8217;m thankful that jQuery gave me the opportunity to meet so many new people and work on the things that I&#8217;m most passionate about. However I&#8217;m most happy that it&#8217;s empowered so many people to build things on the web, I&#8217;m so glad to have been a part of it all. I can&#8217;t wait to see where we&#8217;ll be another 10 years from now!</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/AIxwk_fDf1s" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/10th-anniversary-of-jquery/feed/</wfw:commentRss>
		<slash:comments>78</slash:comments>
		</item>
		<item>
		<title>Building an Art History Database Using Computer Vision</title>
		<link>https://johnresig.com/blog/building-art-history-database-computer-vision/</link>
		<comments>https://johnresig.com/blog/building-art-history-database-computer-vision/#comments</comments>
		<pubDate>Thu, 28 May 2015 15:02:28 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6247</guid>
		<description><![CDATA[Since the fall of 2013 I&#8217;ve had the opportunity to collaborate with the Frick Art Reference Library Photoarchive, a venerable art history research institution here in New York City. We&#8217;ve been especially interested in finding ways of applying computer vision technology to improve art history research. Art history photo archives are an interesting tool used [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Since the fall of 2013 I&#8217;ve had the opportunity to collaborate with the <a href="http://www.frick.org/research/photoarchive">Frick Art Reference Library Photoarchive</a>, a venerable art history research institution here in New York City. We&#8217;ve been especially interested in finding ways of applying computer vision technology to improve art history research.</p>
<p>Art history photo archives are an interesting tool used by scholars: they&#8217;re a collection of thousands, if not millions, of photos of art. These are not the artworks themselves but photos of the artworks &#8211; oftentimes from all over the world &#8211; taken by individuals or institutions and aggregated into this single archive. This is an invaluable resource for researchers as oftentimes you can find more information about the history of an artwork (before/after conservation) or even find artworks that are lost (stolen, destroyed, or moved into unknown private collections).</p>
<p>The Frick Photoarchive has 1.2 million photos of art which they are in the process of digitizing and bringing online. They&#8217;re part of a larger photo archive consortium, called PHAROS, which has many other photo archives from all over the world. In total they&#8217;re likely going to have over 10 million photos of art once all of their collections are pooled.</p>
<p>This poses an interesting problem however as combining this much data from all of these institutions is especially challenging. In the world of digital humanities the most-common tool to utilize is that of <a href="https://en.wikipedia.org/wiki/Linked_open_data">Linked Open Data</a>. Making sure all the records have consistent attributes being used, along with consistent data, then it&#8217;ll become easy to match up data from multiple institutions. In practice, however, this is quite difficult. Moving massive databases over to another schema can be very challenging, in fact very few institutions have done it. The <a href="http://www.britishmuseum.org/about_us/news_and_press/press_releases/2011/semantic_web_endpoint.aspx">British Museum</a> is an especially notable example that has made the switch to this format and has served as an example to other institutions around the world.</p>
<table style="border: 0px; width: 100%;">
<tr>
<td width="50%" align="center"><img src="https://johnresig.com/files/frick-image-analysis/10383.jpg" style="max-width: 335px;"/></td>
<td width="50%" align="center"><img src="https://johnresig.com/files/frick-image-analysis/10382.jpg" style="max-width: 335px;"/></td>
</tr>
<tr>
<td colspan="2" align="center"><small>Madonna and Child, 13th century, La Chiesa di S. Eufrasia, Pisa.</small></td>
</tr>
</table>
<p>I&#8217;ve been proposing an alternative means of merging archives, namely using computer vision techniques to find the missing connections between images of artworks, to avoid the process of having to manually identify images and making sure that their data is pre-aligned. I <a href="https://johnresig.com/research/computer-vision-photo-archives/">published a paper on my research</a> looking in to this topic (which has since been re-published in the <a href="http://journalofdigitalhumanities.org/3-2/using-computer-vision-to-increase-the-research-potential-of-photo-archives-by-john-resig/">Journal of Digital Humanities</a>). The results are extremely promising. I&#8217;ve been using the <a href="https://services.tineye.com/MatchEngine">MatchEngine</a> service graciously provided by <a href="http://ideeinc.com/">Idee Inc.</a> to great effect. The algorithm they use is able to match duplicate images of the same artwork, even if there are differences in the photo (e.g. color vs. black-and-white, skewed photo angles, etc.). I highly recommend reading <a href="https://johnresig.com/research/computer-vision-photo-archives/">my paper</a> for more information on the algorithm&#8217;s capabilities.</p>
<p>Building off of that work last year the Frick Art Reference Library and I received a <a href="http://www.kressfoundation.org/grants/default.aspx?id=150">digital resources grant from the Kress Foundation</a> to continue exploring these computer vision techniques. Specifically I looked in to using the technology to merge multiple art history photo archives together. I attempted to merge the Frick Photoarchive&#8217;s Anonymous Italian Art collection and the <a href="http://www.fondazionezeri.unibo.it/home/00000003_Home.html">Zeri Foundation&#8217;s</a> 15th and 16th century Italian art collections using only the images and no additional metadata.</p>
<p>As it turns out this technique proved to be very successful &#8211; so successful that we&#8217;re now looking to use this technology as a primary means of merging records between all the archives in the PHAROS consortium. You can learn more about the results of this process in <a href="https://www.youtube.com/watch?v=PL6J8MtTsPo">a talk that I gave</a> at last year&#8217;s PHAROS (then IDPAC) annual meeting:</p>
<p><center><iframe width="480" height="360" src="https://www.youtube.com/embed/PL6J8MtTsPo?rel=0" frameborder="0" allowfullscreen></iframe></center></p>
<p>Now that we&#8217;ve proven that inter-institutional merging of photo archives is possible the next step becomes obvious: building a new database, in many ways like the <a href="http://ukiyo-e.org/">Japanese print database</a> I built previously, but focused on the digital photo collections of these archives.</p>
<p>I&#8217;m happy to announced that the Frick Art Reference Library and I have just received another grant from the Kress foundation to fund the development of this new database. At the start it&#8217;ll primarily focus on Italian art, as that&#8217;s the majority what has already been digitized by PHAROS archives. However even just focusing on Italian art it&#8217;ll immediately become one of the largest and most-important online collections for studying Italian art in the world.</p>
<p>A few key features of this new database:</p>
<ul>
<li>The database, images, and data contained within it will all be publicly accessible. This was an extremely important point for me as I wanted to ensure that we were providing a resource for everyone to learn from.</li>
<li>Computer vision techniques will be used to merge the records from the archives together and will also be provided as a tool for research: you&#8217;ll be able to upload an image of an artwork and find other copies of it in the archive. This feature alone will save researchers so much time and energy when attempting to learn about an artwork.</li>
<li>Metadata about the images will be provided by the institutions and will be made searchable. In the first version of this database we will not be doing any work to rectify the metadata between the institutions (many of them will be in different languages) but that should serve as a good &#8220;next step&#8221; for the project after launch.</li>
<li>The interface for the database will be provided in multiple languages. Initially in English, German, and Italian.</li>
</ul>
<p>More information about this project can be found on the <a href="https://johnresig.com/research/italian-art-database-proposal/">project proposal</a> page. I will be working on this project, outside of my work at Khan Academy, over the next year. I&#8217;m extremely excited to have this opportunity to work on this project. Being able to improve art history scholarship is a passion of mine and being able to provide these tools for others is a fantastic opportunity. I&#8217;ll be sure to write more about my work as it progresses, especially the interesting technical innovations that come in to play.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/-hHDB5NmcfE" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/building-art-history-database-computer-vision/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Using Waifu2x to Upscale Japanese Prints</title>
		<link>https://johnresig.com/blog/using-waifu2x-to-upscale-japanese-prints/</link>
		<comments>https://johnresig.com/blog/using-waifu2x-to-upscale-japanese-prints/#comments</comments>
		<pubDate>Wed, 20 May 2015 22:42:42 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6233</guid>
		<description><![CDATA[In my spare time I&#8217;ve been working on a database of Japanese prints for a little over 3.5 years now. I&#8217;m fully aware that I&#8217;ve never actually written about this, personally very important, project on my blog &#8212; until now. Unfortunately this isn&#8217;t a post explaining that project. I do still hope to write more [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In my spare time I&#8217;ve been working on a <a href="http://ukiyo-e.org/">database of Japanese prints</a> for a little over 3.5 years now. I&#8217;m fully aware that I&#8217;ve never actually written about this, personally very important, project on my blog &#8212; until now. Unfortunately this isn&#8217;t a post explaining that project. I do still hope to write more about the intricacies of it, some day, but until that time you can watch <a href="https://www.youtube.com/watch?v=u2pZ_OVRzVc">this talk I gave at OpenVisConf 2014</a> about the site and the tech behind it.</p>
<p>I&#8217;ve been doing a lot of work exploring different computer vision, and machine learning, algorithms to see how they might apply to the world of art history study. I&#8217;m especially interested in finding novel uses of technology that could greatly benefit art historians in their work and also help individuals better appreciate art.</p>
<p>One tool that I came across yesterday is called <a href="https://github.com/nagadomi/waifu2x">Waifu2x</a>. It&#8217;s a convolutional neural network (CNN) that is designed to optimally &#8220;upscale&#8221; images (taking small images and generating a larger image). The creator of this tool built it to better upscale poorly-sized Anime images and video. This is an effort that I can massively cheer on &#8211; while I&#8217;m not a purveyor of Anime, I love applying algorithmic overkill to non-tech hobbies.</p>
<p>Waifu2x also provides a <a href="http://waifu2x.udp.jp/">live demo site</a> that you can use to test it on other images. When I saw this I became immediately intrigued. Anime <a href="http://www.cool-jp.com/articles/anime/anime_fs_techniques_04.php?article_id=140">has direct stylistic influences</a> drawn from the &#8220;old&#8221; world of Japanese woodblock printing, which was popular from the late 1600s to the late 1800s. Maybe the pre-trained upscaler could also work well for photos of Japanese prints? (Naturally I could train a new CNN to do this, but it may not even be necessary!)</p>
<p>Now the first questions that should come up, before even attempting upscale Japanese prints, are simply: Are there enough tiny images of prints that need to be made bigger? Who will benefit from this?</p>
<p>To answer those questions: Unfortunately there are <em>tons</em> of tiny pictures of Japanese prints in the world. To provide one very real example: The <a href="http://www.tnm.jp/?lang=en">Tokyo National Museum</a> has one of the greatest collections of Japanese prints in the world&#8230; none of which are (publicly) digitized. If a researcher wants to see if a the TNM has a particular copy of a print they&#8217;ll need to use the following 3 volume set of books (which I own):</p>
<p><center><img src="https://i.imgur.com/KbbVN91l.jpg" alt="TNM Books"/></center></p>
<p>Inside the book is 3,926 small, black-and-white, scans of every print in their collection:</p>
<p><center><img src="https://i.imgur.com/vdfWjvXl.jpg" alt="Inside of TNM Book"/></center></p>
<p>I plan on digitizing these books and bringing these (not-ideal) prints online as they will be of the utmost use to scholars. However given their tiny size it will be very hard for most researchers to be able to make out what exactly the print is depicting. Thus any technology that is able to upscale the images to make them a bit easier to view would be greatly appreciated.</p>
<p>I began by experimenting with a few different, existing, print images and was really intrigued by the results.</p>
<p>I started with a <a href="http://ukiyo-e.org/image/mfa/sc165440" target="_blank">primitive Ukiyo-e print by Hishikawa Moronobu</a>:</p>
<p><center><a href="http://ukiyo-e.org/image/jaodb/Moronobu_Hishikawa-No_Series-Behind_the_Standing_Screen-00028803-020218-F12" target="_blank"><img src="http://data.ukiyo-e.org/jaodb/scaled/Moronobu_Hishikawa-No_Series-Behind_the_Standing_Screen-00028803-020218-F12.jpg"/></a><br />
(Source Image)</center></p>
<p>And here is the image scaled 2x (OSX Preview) and then using Waifu2x using high noise reduction (be sure to click the images to see them full size):</p>
<p><center><a href="http://i.imgur.com/WJqqUHV.png" target="_blank"><img src="https://i.imgur.com/WJqqUHVl.png" style="width:49%;"/></a> <a href="http://i.imgur.com/AHDu0cq.png" target="_blank"><img src="https://i.imgur.com/AHDu0cql.png" style="width:49%;"/></a></center></p>
<p>And here is another <a href="http://ukiyo-e.org/image/mfa/sc165440" target="_blank">early actor print by Utagawa Kunisada</a>:</p>
<p><center><a href="http://ukiyo-e.org/image/mfa/sc165440" target="_blank"><img src="http://data.ukiyo-e.org/mfa/scaled/sc165440.jpg"/></a><br />
(Source Image)</center></p>
<p>And here is the image scaled 2x (OSX Preview) and then using Waifu2x with low noise reduction and high noise reduction (be sure to click the images to see them full size):</p>
<p><center><a href="http://i.imgur.com/GS4HLxw.png" target="_blank"><img src="https://i.imgur.com/GS4HLxwl.png" style="width:32%;"/></a> <a href="http://i.imgur.com/pDmgNZS.png" target="_blank"><img src="https://i.imgur.com/pDmgNZSl.png" style="width:32%;"/></a> <a href="http://i.imgur.com/541uG5t.png" target="_blank"><img src="https://i.imgur.com/541uG5tl.png" style="width:32%;"/></a></center></p>
<p>I also have a few blown-up details comparing the results between these three (OSX Preview 2x, Waifu2x with low noise reduction, Waifu2x with high noise reduction):</p>
<p><center><img src="https://i.imgur.com/9mV9zFTl.png" alt="Head Detail 2x" style="width:32%;"/> <img src="http://i.imgur.com/713JUPZ.png" alt="Head Detail Waifu2x Low" style="width:32%;"/> <img src="https://i.imgur.com/CjI6DMJl.png" alt="Head Detail Waifu2x" style="width:32%;"/></center></p>
<p><center><img src="http://i.imgur.com/6QdDdX5.png" alt="Arm Detail 2x" style="width:32%;"/> <img src="http://i.imgur.com/144mHSf.png" alt="Arm Detail Waifu2x Low" style="width:32%;"/> <img src="http://i.imgur.com/YYXFMfH.png" alt="Arm Detail Waifu2x" style="width:32%;"/></center></p>
<p><center><img src="http://i.imgur.com/wuIbd6x.png" alt="Cartouche Detail 2x"/> <img src="http://i.imgur.com/LRz8prA.png" alt="Cartouche Detail Waifu2x Low"/> <img src="http://i.imgur.com/91j35la.png" alt="Cartouche Detail Waifu2x"/></center></p>
<p>It&#8217;s immediately apparent that the lines are still quite &#8220;crisp&#8221; in both of the Waifu2x versions. This is extremely compelling as being able to see those details can be quite important. In fact seeing these upscaled images like this is seriously quite impressive. It definitely reinforces the fact that the algorithms Anime training data has suited this subject matter well!</p>
<p>To my eye it almost looks like they entire image has also become more &#8220;smooth&#8221;, it seems much more mottled, almost as if someone spilled water on it (Japanese prints are printed with watercolors and thus are quite susceptible to water damage that actually creates similar results as to what&#8217;s seen here). This is especially true when using Waifu2x&#8217;s high noise reduction. It&#8217;s not clear that this would become any better with better training data as the original source image really only has so much data to begin with.</p>
<p>Waifu2x&#8217;s high noise reduction also causes the background to become much more tumultuous, as if it was crumpled wrapping paper. And the details in the signature, that make it readable, tend to be lost with that much processing. I suspect that using just the low noise reduction may be a better sweet spot.</p>
<p>Helping researchers be able to better see the lines of a print from a tiny image can be a double-edged sword. They will certainly appreciate being able to have a larger and semi-crisp image. However the lack of precision is a massive problem (not that the original image at 2x would&#8217;ve been any better). Researchers rely upon being able to spot minute differences between print impressions in order to be able to understand when a print could&#8217;ve been created. I suspect that using this technique will need to be reserved to only extremely-small images and come with a massive caveat warning the viewer as to the nature of the image and its appearance.</p>
<p>Regardless, this technology is quite exciting and it&#8217;s extremely serendipitous that the subject matter that was used just so happens to correlate nicely with one of my areas of study. I&#8217;ll be very curious to see where else people have success with this particular utility and in what context. </p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/8DX7LRJZCqo" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/using-waifu2x-to-upscale-japanese-prints/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Annotated Version of the Original jQuery Release</title>
		<link>https://johnresig.com/blog/annotated-version-of-the-original-jquery-release/</link>
		<comments>https://johnresig.com/blog/annotated-version-of-the-original-jquery-release/#comments</comments>
		<pubDate>Tue, 07 Apr 2015 19:40:09 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6226</guid>
		<description><![CDATA[Recently I was prompted by Daniel Lamb to try and find old versions of jQuery for his jQuery Archive project. Thankfully I was able to find one in the Internet Archive from just a couple weeks after its release, in January 2006. I then took that opportunity to put that code online and I used [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Recently I was prompted by Daniel Lamb to try and find old versions of jQuery for his <a href="https://github.com/daniellmb/jquery-archive">jQuery Archive</a> project. Thankfully I was able to find one in the Internet Archive from just a couple weeks after its release, in January 2006.</p>
<p>I then took that opportunity to put that code online and I used the new <a href="http://genius.com/">Genius</a> annotation beta to mark it up with a bunch of thoughts and memories around the release of the code.</p>
<blockquote><p><a href="https://johnresig.com/files/Genius%20-%20jQuery%20Annotation.htm">Annotated jQuery Release</a></p></blockquote>
<p>The comments are kind of sprawling, they cover the code itself to the circumstances of the release. I&#8217;ll certainly add more as I think of them. Please feel free to ask questions if there are certain things that you want to learn about!</p>
<p>One of the things I was most touched about was just how obviously inspired I was by many great developers who came before me. I&#8217;m glad I went out of my way to credit them on the <a href="https://web.archive.org/web/20060203025710/http://jquery.com/">original version of the jQuery site</a>. jQuery would not have existed if it wasn&#8217;t for Sam Stephenson creating Prototype, Simon Willison creating getElementsBySelector, Valerio Proietti creating moo.fx, and especially Dean Edwards creating so much: event binding, CSS selector libraries, DOM ready techniques and more. I cover a lot of these influences in the annotations but I want to especially thank them now as without their work I never would&#8217;ve made jQuery.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/GV-pMGOTtb0" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/annotated-version-of-the-original-jquery-release/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Low-cost .com Domains with Whois Privacy</title>
		<link>https://johnresig.com/blog/low-cost-com-domains-with-whois-privacy/</link>
		<comments>https://johnresig.com/blog/low-cost-com-domains-with-whois-privacy/#comments</comments>
		<pubDate>Sun, 23 Nov 2014 01:00:11 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6183</guid>
		<description><![CDATA[In an effort to be more privacy conscious I&#8217;ve been looking to transition to having Domain Privacy enabled on all the domains that I own. As it turns out many domain registrars, including my current one, charge an additional fee for this service. In an effort to save some money I did a price comparison [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In an effort to be more privacy conscious I&#8217;ve been looking to transition to having <a href="https://en.wikipedia.org/wiki/Domain_privacy">Domain Privacy</a> enabled on all the domains that I own. As it turns out many domain registrars, including my current one, charge an additional fee for this service. In an effort to save some money I did a price comparison at some of the most popular domain registrars and came up with the <a href="https://docs.google.com/spreadsheets/d/1cc0mhqT32vBGtzJ-QkODRHX2xX-AVh_9-OGuQNEmH_0/edit?usp=sharing">following list</a> (as of November 22, 2014).</p>
<p><iframe src="https://docs.google.com/spreadsheets/d/1cc0mhqT32vBGtzJ-QkODRHX2xX-AVh_9-OGuQNEmH_0/pubhtml?gid=0&amp;single=true&amp;widget=true&amp;headers=false" style="width:100%; height:525px; border: none;"></iframe></p>
<p>I can&#8217;t vouch for the quality of the particular services, only that this is their stated price for renewing a .com domain through their service. I opted to only focus on the cost of renewing the domain as often-times registrars will have a much-lower cost during the first year of registration and then later increase the price (as with any privacy services). Hope this can be useful to others who are researching the price of private domain registration!</p>
<p><strong>Update:</strong> After compiling this list I found <a href="http://www.registrarowl.com/report_registrar_price_comparison.php">this master list</a> on <a href="http://www.registrarowl.com/">Registrarowl.com</a>, which includes many more registrars (along with privacy price information).</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/4MWqKijIbMg" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/low-cost-com-domains-with-whois-privacy/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Write Code Every Day</title>
		<link>https://johnresig.com/blog/write-code-every-day/</link>
		<comments>https://johnresig.com/blog/write-code-every-day/#comments</comments>
		<pubDate>Thu, 10 Apr 2014 18:28:19 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6144</guid>
		<description><![CDATA[Last fall, work on my coding side projects came to a head: I wasn&#8217;t making adequate progress and I couldn&#8217;t find a way to get more done without sacrificing my ability to do effective work at Khan Academy. There were a few major problems with how I was working on my side projects. I was [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Last fall, work on my <a href="https://github.com/jeresig">coding side projects</a> came to a head: I wasn&#8217;t making adequate progress and I couldn&#8217;t find a way to get more done without sacrificing my ability to do effective work at <a href="https://www.khanacademy.org/">Khan Academy</a>.</p>
<p>There were a few major problems with how I was working on my side projects. I was primarily working on them during the weekends and sometimes in the evenings during the week. This is a strategy that does not work well for me, as it turns out. I was burdened with an incredible amount of stress to try and complete as much high quality work as possible during the weekend (and if I was unable to it felt like a failure). This was a problem as there&#8217;s no guarantee that every weekend will be free &#8211; nor that I&#8217;ll want to program all day for two days (removing any chance of relaxation or doing anything fun).</p>
<p>There&#8217;s also the issue that a week between working on some code is a long time, it&#8217;s very easy to forget what you were working on or what you left off on (even if you keep notes). Not to mention if you miss a weekend you end up with a two week gap as a result. That massive multi-week context switch can be deadly (I&#8217;ve had many side projects die due to attention starvation like that).</p>
<p>Inspired by the incredible work that <a href="http://jenniferdewalt.com/">Jennifer Dewalt</a> completed last year, in which she taught herself programming by building 180 web sites in 180 days, I felt compelled to try a similar tactic: working on my side projects every single day.</p>
<p><img src="http://i.imgur.com/SsevWYY.jpg" class="header-img"/></p>
<div class="header-caption">Illustration by <a href="http://www.stevenchasestudios.com/">Steven Resig</a></div>
<p>I decided to set a couple rules for myself:</p>
<ol>
<li>I must write code every day. I can write docs, or blog posts, or other things but it must be in addition to the code that I write.</li>
<li>It must be useful code. No tweaking indentation, no code re-formatting, and if at all possible no refactoring. (All these things are permitted, but not as the exclusive work of the day.)</li>
<li>All code must be written before midnight.</li>
<li>The code must be Open Source and up on Github.</li>
</ol>
<p>Some of these rules were arbitrary. The code doesn&#8217;t technically need to be written before midnight of the day of but I wanted to avoid staying up too late writing sloppy code. Neither does the code have to be Open Source or up on Github. This just forced me to be more mindful of the code that I was writing (thinking about reusability and deciding to create modules earlier in the process).</p>
<p>Thus far I&#8217;ve been very successful, I&#8217;m nearing 20 weeks of consecutive work. I wanted to write about it as it&#8217;s completely changed how I code and has had a substantial impact upon my life and psyche.</p>
<p><center><a href="https://github.com/jeresig"><img src="http://i.imgur.com/5zjbxsz.jpg" style="border:0px;max-width:100%;"/></a></center></p>
<p>With this in mind a number of interesting things happened as a result of this change in habit:</p>
<p><b>Minimum viable code.</b> I was forced to write code for no less than 30 minutes a day. (It&#8217;s really hard to write meaningful code in less time, especially after remembering where you left off the day before.) Some week days I work a little bit more (usually no more than an hour) and on weekends I&#8217;m sometimes able to work a full day.</p>
<p><b>Code as habit.</b> It&#8217;s important to note that that I don&#8217;t particularly care about the outward perception of the above Github chart. I think that&#8217;s the most important take away from this experiment: this is about a change that you&#8217;re making in your life for yourself not a change that you&#8217;re making to satisfy someone else&#8217;s perception of your work. The same goes for any form of dieting or exercise: if you don&#8217;t care about improving yourself then you&#8217;ll never actually succeed.</p>
<p><b>Battling anxiety.</b> Prior to starting this experiment I would frequently feel a high level of anxiety over not having completed &#8220;enough&#8221; work or made &#8220;enough&#8221; progress (both of which are relatively unquantifiable as my side projects had no specific deadlines). I realized that <b>the <em>feeling</em> of making progress is just as important as making actual progress</b>. This was an eye-opener. Once I started to make consistent progress every day the anxiety started to melt away. I felt at peace with the amount of work that I was getting done and I no longer had the over-bearing desire to frantically get any work done.</p>
<p><b>Weekends.</b> Getting work done on weekends use to be absolutely critical towards making forward momentum (as they were, typically, the only time in which I got significant side project coding done). That&#8217;s not so much the case now &#8211; and that&#8217;s a good thing. Building up a weeks-worth of expectations about what I should accomplish during the weekend only ended up leaving me disappointed. I was rarely able to complete all the work that I wanted and it forced me to reject other weekend activities that I enjoyed (eating dim sum, visiting museums, going to the park, spending time with my partner, etc.) in favor of getting more work done. I strongly feel that while side projects are really important they should not be to the exclusion of life in general.</p>
<p><b>Background processing.</b> An interesting side effect of writing side project code every day is that your current task is frequently running in the back of your mind. Thus when I go for a walk, or take a shower, or any of the other non-brain-using activities I participate in, I&#8217;m thinking about what I&#8217;m going to be coding later and finding a good way to solve that problem. This did not happen when I was working on the code once a week, or every other week. Instead that time was consumed thinking about some other task or, usually, replaced with anxiety over not getting any side project work done.</p>
<p><b>Context switch.</b> There&#8217;s always going to be a context switch cost when resuming work on a side project. Unfortunately it&#8217;s extremely hard to resume thinking about a project after an entire week of working on another task. Daily work has been quite helpful in this regard as the time period between work is much shorter, making it easier to remember what I was working on.</p>
<p><b>Work balance.</b> One of the most important aspects of this change was in simply learning how to better balance work/life/side project. Knowing that I was going to <em>have to</em> work on the project every single day I had to get better at balancing my time. If I was scheduled to go out in the evening, and not get back until late, then I would need to work on my side project early in the day, before starting my main Khan Academy work. Additionally if I hadn&#8217;t finished my work yet, and I was out late, then I&#8217;d hurry back home to finish it up (instead of missing a day). I should note that I&#8217;ve been finding that I have less time to spend on hobbies (such as woodblock printing) but that&#8217;s a reasonable tradeoff that I&#8217;ll need to live with.</p>
<p><b>Outward perception.</b> This has all had the added benefit of communicating this new habit externally. My partner understands that I have to finish this work every day, and thus activities sometimes have to be scheduled around it. It&#8217;s of considerable comfort to be able to say &#8220;Yes, we can go out/watch a movie/etc. but I have to get my coding in later&#8221; and have that be understood and taken into consideration.</p>
<p><b>How much code was written?</b> I have a hard time believing how much code I&#8217;ve written over the past few months. I created a couple new web sites, re-wrote some frameworks, and created a ton of new node modules. I&#8217;ve written so much I sometimes forget the things I&#8217;ve made &#8211; work from even a few weeks prior seem like a distant memory. I&#8217;m extremely pleased with the amount of work that I&#8217;ve gotten done.</p>
<p>I consider this change in habit to be a massive success and hope to continue it for as long as I can. In the meantime I&#8217;ll do all that I can to recommend this tactic to others who wish to get substantial side project work done. <a href="https://johnresig.com/about/">Let me know</a> if this technique does, or doesn&#8217;t, work for you &#8211; I&#8217;m very interested in hearing additional anecdotes!</p>
<p><small><a href="https://news.ycombinator.com/item?id=7568675">Discuss this post on Hacker News.</a></small></p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/dl5z0PpAP_s" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/write-code-every-day/feed/</wfw:commentRss>
		<slash:comments>73</slash:comments>
		</item>
		<item>
		<title>Use Project-based Interviews Instead of “GitHub”</title>
		<link>https://johnresig.com/blog/project-based-interviews/</link>
		<comments>https://johnresig.com/blog/project-based-interviews/#comments</comments>
		<pubDate>Thu, 21 Nov 2013 18:22:55 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=6054</guid>
		<description><![CDATA[First, some background: I highly recommend that you read the following two blog posts: by Ashe Dryden: The Ethics of Unpaid Labor and the OSS Community and by James Coglan: Why Github is not your CV. They make some fantastic points and communicate the issues surrounding &#8220;Using Github as your CV&#8221;. Both of these were [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>First, some background: I highly recommend that you read the following two blog posts: by Ashe Dryden: <a href="http://ashedryden.com/blog/the-ethics-of-unpaid-labor-and-the-oss-community">The Ethics of Unpaid Labor and the OSS Community</a> and by James Coglan: <a href="https://blog.jcoglan.com/2013/11/15/why-github-is-not-your-cv/">Why Github is not your CV</a>. They make some fantastic points and communicate the issues surrounding &#8220;Using Github as your CV&#8221;.</p>
<p>Both of these were largely provoked by this tweet by Chris Anderson:</p>
<blockquote class="twitter-tweet" lang="en">
<p>Advice received on hiring software devs: reject anyone who doesn&#39;t have a <a href="https://twitter.com/github">@GitHub</a> profile (the more active the better). Agree?</p>
<p>&mdash; Chris Anderson (@chr1sa) <a href="https://twitter.com/chr1sa/statuses/395388032976556032">October 30, 2013</a></p></blockquote>
<p>I had a similar, extremely popular, tweet from 2011:</p>
<blockquote class="twitter-tweet" lang="en">
<p>When it comes to hiring, I&#39;ll take a Github commit log over a resume any day.</p>
<p>&mdash; John Resig (@jeresig) <a href="https://twitter.com/jeresig/statuses/33968704983138304">February 5, 2011</a></p></blockquote>
<p><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<p>I wanted to take this chance to clarify my position on using Github during the interview process a bit.</p>
<p>To start, the position being posited by Chris is absolutely wrong. No one should ever require a Github profile in favor of a resume (unless you&#8217;re applying for a job at Github, perhaps?). Nor should anyone prefer candidates who provide a Github profile over those who don&#8217;t.</p>
<p>(And to clarify, some people seem to be getting caught up in the terminology &#8211; I see many people using &#8216;Github&#8217; as a placeholder for &#8216;any OSS activity&#8217;, I hope no one is being that literal.)</p>
<p>When you&#8217;re applying for a job it&#8217;s generally advised that the more high-quality information that you provide, the better. Anything that emphasizes your work habits, the quality of work that you will perform, and your interests is ideal. Thus the more targeted information you&#8217;re able to provide, the better. Github can provide this for some but almost certainly can&#8217;t be the final arbiter of this information for all.</p>
<p>We&#8217;ve had dev applicants at <a href="https://www.khanacademy.org/">Khan Academy</a> who&#8217;ve applied with traditional resumes, resume + Github profile, resume + personal web site, resume + links to projects they&#8217;ve worked on, resume + a custom project made special for the interview.</p>
<p>Out of all of these submissions the ones that&#8217;ve had the most impact are the ones where the candidates have gone above-and-beyond and done some custom coding, made a custom web site, or contributed to <a href="https://github.com/Khan">one of our Open Source projects</a> as part of the application process. A popular project is one where candidates make a custom exercise using our <a href="https://github.com/khan/khan-exercises">exercise framework</a>.</p>
<p>There are a few reasons why this particular approach is so effective:</p>
<ol>
<li>It communicates just how interested the candidate is in the job: That they&#8217;re willing to go above-and-beyond to demonstrate their interest.</li>
<li>They show that the sort of things they&#8217;re interested in working on are largely aligned with what we&#8217;re trying to do (especially if they make an exercise with our exercise framework).</li>
<li>If it&#8217;s a coding project you can get a sense for what their code quality is like and how they wish to portray themselves.</li>
</ol>
<p>Naturally this isn&#8217;t completely ideal as it requires a candidate to put in considerably more time into their application than just generating a single-sheet resume. That being said the level of information that is conveyed is so much higher that it almost isn&#8217;t comparable.</p>
<p>The traditional interview process is broken. It&#8217;s high-stress and a poor representation of what you&#8217;ll actually experience working for the employer, or working with the candidate.</p>
<p>Over this past summer I developed a new &#8220;take-home&#8221; project-based interview for JavaScript-centric candidates to Khan Academy. I wanted a way to try to better-quantify a person&#8217;s development ability without having to necessarily suss out their best code from Github, or elsewhere.</p>
<p>I extracted a tangible, contained, project that I had assigned to one of my interns and turned it into a project. Thus far it&#8217;s worked extremely well as, as can be <a href="http://blog.pamelafox.org/2013/09/technical-interviews-make-me-cry.html">attested to by Pamela Fox</a> (who completed the project with flying colors). I&#8217;m very pleased with this approach as it gets all the benefit of the candidate creating a custom project on their own but it has the added benefit of communicating to the candidate the exact type of projects that they&#8217;ll be working on here at Khan Academy.</p>
<p>I&#8217;d love to open up the project at some point to show how it&#8217;s done but it&#8217;s still an effective tool in our interviewing toolbox and I&#8217;m not sure I want to lose that just yet!</p>
<p>However, you can be privy to the project-based interview process if you wish to <a href="http://hire.jobvite.com/j/?cj=o0HMVfw8&#038;s=ejohn.org">apply to Khan Academy</a>! Specifically if you&#8217;re interested in working with <a href="http://www.pamelafox.org/">Pamela Fox</a> and me to build <a href="https://www.khanacademy.org/cs">Khan Academy&#8217;s Computer Science</a> platform (<a href="https://johnresig.com/blog/introducing-khan-cs/">more details on the launch</a>, a <a href="https://johnresig.com/blog/talk-khan-academy-computer-science/">technical talk</a> I gave on it after launch).</p>
<p>If this really excites you then <a href="http://hire.jobvite.com/j/?cj=o0HMVfw8&#038;s=ejohn.org">you should apply</a> for a Software Developer position at Khan Academy and specifically request to go through the JavaScript project interview with myself. I&#8217;ll give you the project to work on and we&#8217;ll discuss the results extensively.</p>
<p>The biggest drawback to this approach is that we&#8217;re demanding some of your free time to gather this information. We&#8217;re not sure what the best way is to offset this, as of yet. However by doing the project you&#8217;ll likely be able to skip a number of stages in our interview process and hopefully get started on changing the world with us at Khan Academy all the sooner.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/4yJAuH83hxY" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/project-based-interviews/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Node.js Stream Playground</title>
		<link>https://johnresig.com/blog/node-js-stream-playground/</link>
		<comments>https://johnresig.com/blog/node-js-stream-playground/#comments</comments>
		<pubDate>Fri, 15 Nov 2013 17:37:43 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5976</guid>
		<description><![CDATA[This summer I had the opportunity to attend NodeConf and it was a fantastic experience. I really appreciated how every session was a hands-on coding session: I felt like I walked away knowing how to put a bunch of advice directly into practice. One of my favorite sessions was the one run by James Halliday [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>This summer I had the opportunity to attend <a href="http://www.nodeconf.com/">NodeConf</a> and it was a fantastic experience. I really appreciated how every session was a hands-on coding session: I felt like I walked away knowing how to put a bunch of advice directly into practice.</p>
<p>One of my favorite sessions was the one run by <a href="https://github.com/substack/">James Halliday</a> and <a href="https://github.com/maxogden/">Max Ogden</a> exploring <a href="http://nodejs.org/api/stream.html">Node streams</a>. Specifically they sat us down and had us run through the amazing <a href="https://github.com/substack/stream-adventure">Stream Adventure</a> program. It&#8217;s an interactive series of exercises that are designed to help you understand streams better. Seeing interesting ways of using streams in practice was quite eye opening for me. (I also recommend checking out the awesome <a href="https://github.com/substack/stream-handbook">Stream Handbook</a> if streams are totally foreign to you)</p>
<p>I had made limited use of streams before (namely with the <a href="https://github.com/mikeal/request">request</a> and <a href="http://nodejs.org/api/fs.html">fs</a> modules) but I was still early on. Over the past few months I&#8217;ve spent more time researching Node modules that make good use of streams and have tried to apply them in my various side projects. In theory I absolutely love streams: they are the chainable piping amazingness that exists with UNIX and I aspired to achieve with jQuery. In practice many Node stream modules are poorly written, poorly documented, out of date, or just obscure. So while theoretically using Node streams should be really easy in practice it becomes quite challenging.</p>
<p>In my explorations I was starting to build up a pile of streaming Node modules that I *knew* worked correctly (or, at least, as I expected them to). Namely: They supported streams in Node 0.10+ and they supported being <code>.pipe()</code>&#8216;d to and from (where applicable). I realized that in a perfect world Node streams truly are like Lego bricks &#8211; it becomes quite easy to snap a few of them together to build a chained flow for your data to pass through.</p>
<p>With that in mind I built an exploration that I hope will help others to understand the simplicity and power of Node streams: The <a href="http://nodestreams.com/">Node.js Stream Playground</a>.</p>
<p><center><a href="http://nodestreams.com/"><img src="https://johnresig.com/files/node-stream-playground.500.jpg"/></a></center></p>
<p><strong>More information:</strong></p>
<ul>
<li><a href="http://nodestreams.com/">http://nodestreams.com/</a></li>
<li><a href="https://github.com/jeresig/node-stream-playground">https://github.com/jeresig/node-stream-playground</a></li>
<li><a href="https://npmjs.org/package/stream-playground">https://npmjs.org/package/stream-playground</a></li>
</ul>
<p>The Node.js Stream Playground was created to help Node.js developers better understand how streams work by showing a number of use cases that are easily plug-and-play-able. Additionally detailed logging is provided at every step to help users better understand what events the streams are emitting and exactly what their contents are.</p>
<h3>How to Use the Playground</h3>
<p>I hope you&#8217;ll get the most out of the playground by exploring concepts for yourself &#8211; looking at what happens when you pipe different streams to each other, looking at the data being logged, and attempting to understand (for yourself) what exactly is happening and why. Note that all of the code being generated is valid Node code and can be copy-and-pasted and run on your own computer (assuming you have the appropriate NPM modules installed).</p>
<p>I should note that this isn&#8217;t the end-all-and-be-al of Node stream education: There is still a lot to learn with regard to error handling, back pressure, and all the intricate stream concepts that exist. I hope to write some more on these concepts some day.</p>
<p>With that being said here are some good examples of some of the actions that you can do:</p>
<p><strong>Copying a File</strong></p>
<ol>
<li>Select <strong>Read File</strong> and <code>input/people.json</code>.</li>
<li>Select <strong>Write File</strong> and <code>output/people.json</code>.</li>
</ol>
<p>The resulting code:</p>
<pre class="brush: cpp; title: ; notranslate">var fs = require(&quot;fs&quot;);

// Read File
fs.createReadStream(&quot;input/people.json&quot;)
    // Write File
    .pipe(fs.createWriteStream(&quot;output/people.json&quot;));</pre>
<p>This will copy the JSON file from one location to another. This is actually the preferred way of copying files in Node &#8211; there actually is no built-in utility method for doing this.</p>
<p><strong>Downloading a File</strong></p>
<p>This will download the JSON file from the specified URL and save it to the local file.</p>
<ol>
<li>Select <strong>HTTP Get Request</strong> and <code>http://nodestreams.com/input/people.json</code>.</li>
<li>Select <strong>Write File</strong> and <code>output/people.json</code>.</li>
</ol>
<p>The resulting code:</p>
<pre class="brush: cpp; title: ; notranslate">var request = require(&quot;request&quot;);
var fs = require(&quot;fs&quot;);

// HTTP GET Request
request(&quot;http://nodestreams.com/input/people.json&quot;)
    // Write File
    .pipe(fs.createWriteStream(&quot;output/people.json&quot;));</pre>
<p><strong>Un-Gzipping a File</strong></p>
<ol>
<li>Select <strong>Read File</strong> and <code>input/people.csv.gz</code>.</li>
<li>Select <strong>Un-Gzip</strong>.</li>
<li>Select <strong>Write File</strong> and <code>output/people.csv</code>.</li>
</ol>
<p>The resulting code:</p>
<pre class="brush: cpp; title: ; notranslate">var fs = require(&quot;fs&quot;);
var zlib = require(&quot;zlib&quot;);

// Read File
fs.createReadStream(&quot;input/people.csv.gz&quot;)
    // Un-Gzip
    .pipe(zlib.createGunzip())
    // Write File
    .pipe(fs.createWriteStream(&quot;output/people.csv&quot;));</pre>
<p>Note that the initial data that is coming out of the Read File is just an array of numbers &#8211; this is to be expected. In reality it&#8217;s a <a href="http://nodejs.org/api/buffer.html">Node Buffer</a> holding all of the raw binary data. It&#8217;s not until after we Un-Gzip the file that we start to have data that&#8217;s in a more usable form.</p>
<p><strong>Converting a TSV to HTML</strong></p>
<p>In this case we&#8217;re going to manually parse the TSV (without headers) just to show you some of the string operations provided by <a href="https://github.com/dominictarr/event-stream">event-stream</a>.</p>
<ol>
<li>Select <strong>Read File</strong> and <code>input/people.tsv</code>.</li>
<li>Select <strong>Split Strings</strong>.</li>
<li>Select <strong>Split Strings into Array</strong>.</li>
<li>Select <strong>Convert Array w/ Sprintf</strong> (with the default table row HTML).</li>
<li>Select <strong>Join Strings</strong> (this will insert an endline between all the individual table rows).</li>
<li>Select <strong>Concat Strings</strong> (this will combine all the individual table rows and endlines into a single string).</li>
<li>Select <strong>Wrap Strings</strong> (with the default table HTML).</li>
<li>Select <strong>Write File</strong> and <code>output/people.html</code>.</li>
</ol>
<p>The resulting code:</p>
<pre class="brush: cpp; title: ; notranslate">var fs = require(&quot;fs&quot;);
var es = require(&quot;event-stream&quot;);
var vsprintf = require(&quot;sprintf&quot;).vsprintf;

// Read File
fs.createReadStream(&quot;input/people.tsv&quot;)
    // Split Strings
    .pipe(es.split(&quot;\n&quot;))
    // Split Strings into Array
    .pipe(es.mapSync(function(data) {
        return data.split(&quot;\t&quot;);
    }))
    // Convert Array w/ Sprintf
    .pipe(es.mapSync(function(data) {
        return vsprintf(&quot;&lt;tr&gt;&lt;td&gt;&lt;a href='%2$s'&gt;%1$s&lt;/a&gt;&lt;/td&gt;&lt;td&gt;%3$s&lt;/td&gt;&lt;/tr&gt;&quot;, data);
    }))
    // Join Strings
    .pipe(es.join(&quot;\n&quot;))
    // Concat Strings
    .pipe(es.wait())
    // Wrap Strings
    .pipe(es.mapSync(function(data) {
        return &quot;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;City&lt;/th&gt;&lt;/tr&gt;\n&quot; + data + &quot;\n&lt;/table&gt;&quot;;
    }));</pre>
<p>This should give you some HTML that looks something like this:</p>
<pre class="brush: xml; title: ; notranslate">&lt;table&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;City&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://vinceallen.com/'&gt;Vince Allen&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Brooklyn, NY&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://twitter.com/jandet'&gt;Janessa Det&lt;/a&gt;&lt;/td&gt;&lt;td&gt;New York, NY&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://patnakajima.com/'&gt;Pat Nakajima&lt;/a&gt;&lt;/td&gt;&lt;td&gt;San Francisco, CA&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://sarajchipps.com/'&gt;Sara Chipps&lt;/a&gt;&lt;/td&gt;&lt;td&gt;New York, NY&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://johnresig.com/'&gt;John Resig&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Brooklyn, NY&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</pre>
<p><strong>Download Encoded, Gzipped, CSV and Convert to HTML</strong></p>
<p>This is the big one:</p>
<ol>
<li>Select <strong>HTTP Get Request</strong> and <code>http://nodestreams.com/input/people.csv.gz</code>.</li>
<li>Select <strong>Un-Gzip</strong> (note that some of the characters are encoded incorrectly, we need to fix this!).</li>
<li>Select <strong>Change Encoding</strong> (even though it comes out as a buffer, this is correct, as we&#8217;ll see in a moment).</li>
<li>Select <strong>Parse CSV as Object</strong>.</li>
<li>Select <strong>Convert Object w/ Handlebars</strong> (with the default table row HTML).</li>
<li>Select <strong>Join Strings</strong> (this will insert an endline between all the individual table rows).</li>
<li>Select <strong>Concat Strings</strong> (this will combine all the individual table rows and endlines into a single string).</li>
<li>Select <strong>Wrap Strings</strong> (with the default table HTML).</li>
<li>Select <strong>HTTP PUT Request</strong> and <code>http://nodestreams.com/output/people.html</code>.</li>
</ol>
<p>The resulting code:</p>
<pre class="brush: cpp; title: ; notranslate">var request = require(&quot;request&quot;);
var zlib = require(&quot;zlib&quot;);
var Iconv = require(&quot;iconv&quot;).Iconv;
var csv = require(&quot;csv-streamify&quot;);
var Handlebars = require(&quot;handlebars&quot;);
var es = require(&quot;event-stream&quot;);

var tmpl = Handlebars.compile(&quot;&lt;tr&gt;&lt;td&gt;&lt;a href='{{URL}}'&gt;{{Name}}&lt;/a&gt;&lt;/td&gt;&lt;td&gt;{{City}}&lt;/td&gt;&lt;/tr&gt;&quot;);

// HTTP GET Request
request(&quot;http://nodestreams.com/input/people_euc-jp.csv.gz&quot;)
    // Un-Gzip
    .pipe(zlib.createGunzip())
    // Change Encoding
    .pipe(new Iconv(&quot;EUC-JP&quot;, &quot;UTF-8&quot;))
    // Parse CSV as Object
    .pipe(csv({objectMode: true, columns: true}))
    // Convert Object w/ Handlebars
    .pipe(es.mapSync(tmpl))
    // Join Strings
    .pipe(es.join(&quot;\n&quot;))
    // Concat Strings
    .pipe(es.wait())
    // Wrap Strings
    .pipe(es.mapSync(function(data) {
        return &quot;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;City&lt;/th&gt;&lt;/tr&gt;\n&quot; + data + &quot;\n&lt;/table&gt;&quot;;
    }))
    // HTTP PUT Request
    .pipe(request.put(&quot;http://nodestreams.com/output/people.html&quot;));</pre>
<p>You should have the same output as the last run. A lot is happening here but even will all of these steps Node streams still makes it relatively easy to complete it all. It&#8217;s at this point that you can truly start to see the power and expressiveness of streams.</p>
<h3>Adding in New Streams</h3>
<p>If you&#8217;re interested in extending the playground and adding in new pluggable stream &#8220;blocks&#8221; you can simply edit <code><a href="https://github.com/jeresig/node-stream-playground/blob/master/blocks.js">blocks.js</a></code> and add in the stream functions. A common stream block would look something like this:</p>
<pre class="brush: cpp; title: ; notranslate">&quot;Change Encoding&quot;: function(from /* EUC-JP */, to /* UTF-8 */) {
   var Iconv = require(&quot;iconv&quot;).Iconv;
   return new Iconv(from, to);
},</pre>
<p>The property name is the full title/description of the stream. The arguments to the function are variables that you wish the user to populate. The comments immediately following the argument names are the default values (you can provide multiple values by separating them with a <code>|</code>).</p>
<p>The streams are split into 3 types: &#8220;Readable&#8221;, &#8220;Writable&#8221;, &#8220;Transform&#8221; (in that they read content, modify it, and pass it through). Typically it is assumed that &#8220;Readable&#8221; streams will be the first ones that you can choose in the playground, &#8220;Writeable&#8221; streams will end the playground, and everything else is just &#8220;.pipe()able&#8221;.</p>
<p>If you&#8217;ve added a new stream please <a href="https://github.com/jeresig/node-stream-playground/pulls">send a pull request</a> and I&#8217;ll be happy to add it!</p>
<h3>Running Your Own Server</h3>
<p>After downloading the code (either from <a href="https://github.com/jeresig/node-stream-playground">Github</a> or <a href="http://npmjs.org/package/stream-playground">NPM</a>). Be sure to run <code>npm install</code> to install all the dependencies. You can then use just <code>node app.js</code> to run a server &#8211; or if you wish to run something more robust you can install <code><a href="https://npmjs.org/package/naught">naught</a></code> and then run <code>npm start</code>.</p>
<p><strong>WARNING</strong> I have no idea how robust the application&#8217;s security is. This application is generating and executing code on the user&#8217;s behalf (although it is not allowing arbitrary code to be executed). Feel free to run it on a local server or, if you feel confident in the code, run it on your own server. At the moment I&#8217;m running it on a standalone server with nothing else on it, just in case.</p>
<h3>Feedback Welcome!</h3>
<p>I&#8217;d love to hear about how people are using streams and if this tool has been helpful for your understanding how streams work. Let me know if there are particular stream modules that you really like and &#8211; if possible &#8211; try and add them to the stream playground so that others can experience them as well!</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/McHQe_lJiZ8" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/node-js-stream-playground/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Gittip at Khan Academy</title>
		<link>https://johnresig.com/blog/gittip-at-khan-academy/</link>
		<comments>https://johnresig.com/blog/gittip-at-khan-academy/#comments</comments>
		<pubDate>Tue, 16 Jul 2013 21:23:11 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://ejohn.org/?p=5954</guid>
		<description><![CDATA[For a while now I&#8217;ve been a huge fan of Gittip. I think they&#8217;ve created one of the most interesting models for funding Open Source development. One of the missing pieces, for most Open Source developers, is having consistent, reliable, income backing your development. Some developers are sponsored by their work place, others have a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>For a while now I&#8217;ve been a huge fan of <a href="https://www.gittip.com/">Gittip</a>. I think they&#8217;ve created one of the most interesting models for funding Open Source development.</p>
<p>One of the missing pieces, for most Open Source developers, is having consistent, reliable, income backing your development. Some developers are sponsored by their work place, others have a job but do Open Source work on the side. Even others may not have reliable incomes and still want to create software that isn&#8217;t tied to a specific revenue-generator. I <a href="https://www.gittip.com/jeresig/">personally use Gittip</a> to fund hosting costs for some of my side projects.</p>
<p>Gittip is capable of freeing Open Source developers by allowing people to give them money on a week-by-week basis. This is intriguing as the money that comes in will come slowly &#8211; people will be less likely to give and they&#8217;ll likely give smaller amounts &#8211; but it&#8217;ll also be relatively stable (once someone is giving there will be not much reason to decrease that amount or stop giving).</p>
<p>I&#8217;ve been providing feedback to <a href="http://whit537.org/">Chad Whitacre</a> and the rest of the Gittip team wherever I can because this is something that I really want to succeed.</p>
<p>Taking a further step I looked to see what were the major pain points to growth. Right now they&#8217;re:</p>
<ol>
<li>Getting more developers signed up and asking for donations.</li>
<li>Getting more people giving money to those developers.</li>
</ol>
<p>I&#8217;m attempting to work with the Gittip team to help make #1 more feasible, and while I&#8217;m giving money personally, I wanted to try and get more money into the system.</p>
<p>I saw a great opportunity for the development team at <a href="https://www.khanacademy.org/">Khan Academy</a> to give back to the Open Source community in ways that were not just code-related.</p>
<p>Talking with <a href="http://bjk5.com/">Ben Kamens</a> we came upon a good solution: <strong>Every developer at Khan Academy (interns included) has $5/week to give to the Open Source developers of their choice.</strong> (You&#8217;re restricted from giving that money to employees of Khan Academy though, heh.) That money would then be rolled up into a single contribution coming from the <a href="https://www.gittip.com/khanacademy/">Khan Academy Gittip account</a>.</p>
<p>This seemed like the ideal scenario: Developers gets full control of how their money should be allocated and Khan Academy gets the benefit of their financial contributions coming from a unified source. (Which helps to communicate to developers that we care about Open Source and that, hopefully, we&#8217;re a cool place to work, which we are.)</p>
<p>In the spirit of <a href="https://sites.google.com/a/khanacademy.org/forge/for-developers">shipping beats perfection</a> I hacked together a <a href="https://docs.google.com/spreadsheet/pub?key=0ApubWHv0aMirdE9LODNJY0s4WXpXSlVYLVhrNmdocWc&#038;output=html">Google Spreadsheet</a> which Khan Academy devs could modify to allocate their contributions.</p>
<p><center><iframe style="width:100%;height:400px;" frameborder='0' src='https://docs.google.com/spreadsheet/pub?key=0ApubWHv0aMirdE9LODNJY0s4WXpXSlVYLVhrNmdocWc&#038;output=html&#038;widget=true'></iframe></center></p>
<p>At the moment 21 Khan Academy devs are collectively giving $57.75/week to 15 different Open Source devs. This is a great start! Unfortunately we&#8217;re trying to give $46.25 to an additional 8 devs who aren&#8217;t yet on Gittip, so our contribution is stuck in limbo. (At the moment the best we can hope for is to pester them on Twitter, etc. and get them to sign up. In some cases devs seem to be disinclined to receive donations if they already have a full-time job &#8212; in that case they should feel free to donate the money to the charity of their choice, or even just back to other devs!)</p>
<blockquote><p><strong>Update July 17th:</strong> <a href="https://www.gittip.com/khanacademy/">We&#8217;re now up to</a> 26 Khan Academy devs giving $89/week to 17 Open Source devs on Gittip. Another $40.25/week is being held until some additional Open Source devs join Gittip.</p></blockquote>
<p>We&#8217;ve already started the process of contacting some of the devs that we want to support:</p>
<blockquote class="twitter-tweet">
<p><a href="https://twitter.com/jashkenas">@jashkenas</a> <a href="https://twitter.com/fat">@fat</a> <a href="https://twitter.com/cloudhead">@cloudhead</a> <a href="https://twitter.com/stuk">@stuk</a> <a href="https://twitter.com/ariyahidayat">@ariyahidayat</a> Heya! Could you join <a href="https://twitter.com/Gittip">@Gittip</a>? We want to thank you for your OSS work: <a href="http://t.co/jr6OHRDoVm">http://t.co/jr6OHRDoVm</a></p>
<p>&mdash; Khan Academy (@khanacademy) <a href="https://twitter.com/khanacademy/statuses/357251418228404225">July 16, 2013</a></p></blockquote>
<p><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<p>There is a script that I&#8217;ve made to automate the process of extracting the tips from the spreadsheet and uploading them to Gittip (run as a weekly cron job). You can find it on Github:</p>
<p><a href="https://github.com/Khan/gittip-gdoc">https://github.com/Khan/gittip-gdoc</a></p>
<p>I want to thank Chad for helping to <a href="https://github.com/gittip/www.gittip.com#api">add in an API</a> that would make it easier to create this script!</p>
<p>I hope others are as excited about Gittip as we are at Khan Academy. I strongly think that this is the future of providing developers with a financial incentive for creating useful Open Source work. Gittip is still quite young and our understanding of how this mode of contribution should work is still open for debate so I hope that this will help inspire others to give, and strive towards a financial ideal, as well.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/AqY20AX3QsM" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/gittip-at-khan-academy/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Asm.js: The JavaScript Compile Target</title>
		<link>https://johnresig.com/blog/asmjs-javascript-compile-target/</link>
		<comments>https://johnresig.com/blog/asmjs-javascript-compile-target/#comments</comments>
		<pubDate>Wed, 03 Apr 2013 15:18:50 +0000</pubDate>
		<dc:creator><![CDATA[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 [&#8230;]]]></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&#8217;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/bn-8dtULzGE" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/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>https://johnresig.com/blog/webkit-is-the-jquery-of-browser-engines/</link>
		<comments>https://johnresig.com/blog/webkit-is-the-jquery-of-browser-engines/#comments</comments>
		<pubDate>Wed, 13 Feb 2013 14:38:57 +0000</pubDate>
		<dc:creator><![CDATA[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 [&#8230;]]]></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/aEff-sdiDNE" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/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>https://johnresig.com/blog/fixing-google-analytics-for-ghostery/</link>
		<comments>https://johnresig.com/blog/fixing-google-analytics-for-ghostery/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 16:21:13 +0000</pubDate>
		<dc:creator><![CDATA[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 [&#8230;]]]></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>
<pre class="brush: xml; title: ; notranslate">&lt;script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;window.jQuery || document.write('&lt;script src=&quot;js/vendor/jquery-1.9.1.min.js&quot;&gt;&lt;\/script&gt;')&lt;/script&gt;</pre>
<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>
<pre class="brush: jscript; title: ; notranslate">// Add in Google Analytics tracking
var track = function(category, name, value) {
	if (window._gaq) {
		window._gaq.push([&quot;_trackEvent&quot;, category, name, value]);
	}
};</pre>
<p>and then when I wanted to track an actual event I would do something like this:</p>
<pre class="brush: jscript; title: ; notranslate">track(&quot;Source&quot;, &quot;Visit&quot;, this.href);</pre>
<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/LV-1IZWN9A0" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/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>https://johnresig.com/blog/secrets-of-the-javascript-ninja-released/</link>
		<comments>https://johnresig.com/blog/secrets-of-the-javascript-ninja-released/#comments</comments>
		<pubDate>Thu, 07 Feb 2013 18:39:30 +0000</pubDate>
		<dc:creator><![CDATA[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 [&#8230;]]]></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="https://johnresig.com/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="https://johnresig.com/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/SxpDPj349PU" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/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>https://johnresig.com/blog/keeping-passwords-in-source-control/</link>
		<comments>https://johnresig.com/blog/keeping-passwords-in-source-control/#comments</comments>
		<pubDate>Wed, 06 Feb 2013 21:23:32 +0000</pubDate>
		<dc:creator><![CDATA[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 [&#8230;]]]></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>
<pre class="brush: jscript; title: ; notranslate">// Copy to conf/settings.json
// and fill these in with your login details!
{
  &quot;db&quot;: {
    &quot;username&quot;: &quot;&quot;,
    &quot;password&quot;: &quot;&quot;
  }
}</pre>
<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>
<pre class="brush: plain; title: ; notranslate">conf/settings.json</pre>
<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>
<pre class="brush: jscript; title: ; notranslate">{
  &quot;db&quot;: {
    &quot;username&quot;: &quot;cool_guy&quot;,
    &quot;password&quot;: &quot;A1B2C3!&quot;
  }
}</pre>
<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>
<pre class="brush: bash; title: ; notranslate">.PHONY: _pwd_prompt decrypt_conf encrypt_conf

CONF_FILE=conf/settings.json

# 'private' task for echoing instructions
_pwd_prompt:
    @echo &quot;Contact jeresig@gmail.com for the password.&quot;

# to create conf/settings.json
decrypt_conf: _pwd_prompt
    openssl cast5-cbc -d -in ${CONF_FILE}.cast5 -out ${CONF_FILE}
    chmod 600 ${CONF_FILE}

# for updating conf/settings.json
encrypt_conf: _pwd_prompt
    openssl cast5-cbc -e -in ${CONF_FILE} -out ${CONF_FILE}.cast5</pre>
<p>With all this in place the next step is simple, you&#8217;ll run:</p>
<pre class="brush: bash; title: ; notranslate">make encrypt_conf</pre>
<p>and you&#8217;ll enter in a password with which to encrypt the config file:</p>
<pre class="brush: plain; title: ; notranslate">Contact jeresig@gmail.com for the password.
enter cast5-cbc decryption password:</pre>
<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>
<pre class="brush: bash; title: ; notranslate">git add .gitignore Makefile conf/settings.json.cast5
git commit -m &quot;Adding in an encrypted config file.&quot;</pre>
<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>
<pre class="brush: bash; title: ; notranslate">make decrypt_conf</pre>
<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>
<pre class="brush: jscript; title: ; notranslate">if (!fs.existsSync(&quot;conf/settings.json&quot;)) {
  console.error(&quot;Config file [conf/settings.json] missing!&quot;);
  console.error(&quot;Did you forget to run `make decrypt_conf`?&quot;);
  process.exit(1);
}</pre>
<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>
<p>(function() {<br />
  var conf_time = fs.statSync(&#8220;conf/settings.json&#8221;).mtime.getTime();<br />
  var cast5_time = fs.statSync(&#8220;conf/settings.json.cast5&#8221;).mtime.getTime();</p>
<p>  if (conf_time < cast5_time) {
    console.error("Your config file is out of date!");
    console.error("You need to run `make decrypt_conf` to update it.");
    process.exit(1);
  }
})();[/js]

And that'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/eCKx4mZeHQI" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/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>https://johnresig.com/blog/i18n-module-for-node-and-express-js/</link>
		<comments>https://johnresig.com/blog/i18n-module-for-node-and-express-js/#comments</comments>
		<pubDate>Tue, 15 Jan 2013 16:25:10 +0000</pubDate>
		<dc:creator><![CDATA[John Resig]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Projects]]></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 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>As a follow-up to my post from last week on <a href="https://johnresig.com/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>
<pre class="brush: jscript; title: ; notranslate">// load modules
var express = require('express'),
	I18n = require('i18n-2');

// Express Configuration
app.configure(function() {
	// ...

	// Attach the i18n property to the express request object
	// And attach helper methods for use in templates
	I18n.expressBind(app, {
		// setup some locales - other locales default to en silently
		locales: ['en', 'de']
	}));

	// Set up the rest of the Express middleware
	app.use(app.router);
	app.use(express.static(__dirname + '/public'));
});</pre>
<p>Inside your Express view:</p>
<pre class="brush: jscript; title: ; notranslate">module.exports = {
	index: function(req, res) {
		req.render(&quot;index&quot;, {
			title: req.i18n.__(&quot;My Site Title&quot;),
			desc: req.i18n.__(&quot;My Site Description&quot;)
		});
	}
};</pre>
<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="https://johnresig.com/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="https://johnresig.com/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" srcset="https://johnresig.com/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-4.08.10-PM-271x300.png 271w, https://johnresig.com/wp-content/uploads/2013/01/Screen-Shot-2013-01-11-at-4.08.10-PM.png 502w" sizes="(max-width: 271px) 100vw, 271px" /></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="https://johnresig.com/blog/a-strategy-for-i18n-and-node/">strategy for i18n and Node.js</a>.</p>
<img src="http://feeds.feedburner.com/~r/JohnResig/~4/fv-SqAEBiYY" height="1" width="1" alt=""/>]]></content:encoded>
			<wfw:commentRss>https://johnresig.com/blog/i18n-module-for-node-and-express-js/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
