<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Tender Lovemaking &#187; johnson</title>
	<atom:link href="http://tenderlovemaking.com/category/computadora/johnson/feed/" rel="self" type="application/rss+xml" />
	<link>http://tenderlovemaking.com</link>
	<description>The act of making love, tenderly.</description>
	<lastBuildDate>Sun, 15 Jan 2012 04:36:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Testing JavaScript Outside the Browser</title>
		<link>http://tenderlovemaking.com/2009/04/05/testing-javascript-outside-the-browser/</link>
		<comments>http://tenderlovemaking.com/2009/04/05/testing-javascript-outside-the-browser/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 03:15:24 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
				<category><![CDATA[computadora]]></category>
		<category><![CDATA[johnson]]></category>
		<category><![CDATA[nokogiri]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=233</guid>
		<description><![CDATA[The other day at LA RubyConf during the Johnson presentation, I showed a few slides which I don&#8217;t think were given the time that they deserve. Not that we didn&#8217;t have enough time, I just don&#8217;t think I made as big a deal about them as I should have. Those particular slides demonstrated HTML Document [...]]]></description>
			<content:encoded><![CDATA[<p>The other day at <a href="http://larubyconf.com">LA RubyConf</a> during the Johnson presentation, I showed a few slides which I don&#8217;t think were given the time that they deserve.  Not that we didn&#8217;t have enough time, I just don&#8217;t think I made as big a deal about them as I should have.  Those particular slides demonstrated HTML Document Object manipulation executed in JavaScript outside any web browser.  Those particular slides, and that particular code, is the culmination of over a year worth of work (and Yak Shaving) and I would like to talk about it a little more in detail here.</p>
<p>Since I started doing any sort of non-trivial browser dependent JavaScript, I&#8217;ve wanted to be able to test the code which I wrote.  Hitting refresh on a webpage seems like a hack.  Setting up a special browser to refresh the page for me also seems like a hack.  I want to run &#8220;rake test&#8221; and have my JavaScript DOM manipulations tested right along with everything else, no browser dependence required.  As far as I could tell, we need three things to make that happen:</p>
<ol>
<li>A JavaScript runtime that can be used in Ruby</li>
<li>A parser with browser-like HTML correction schemes</li>
<li>A DOM interface that mirrors a browsers DOM interface</li>
</ol>
<p>Over the weekend, I think we&#8217;ve come a lot closer.  <a href="http://www.jbarnette.com/">John</a> has finally released <a href="http://github.com/jbarnette/johnson/tree/master">Johnson</a>.  Johnson solves problem number 1.  Johnson provides a JavaScript runtime that is fully accessible in Ruby.  Watch our <a href="http://rubyconf2008.confreaks.com/how-i-learned-to-love-javascript.html">RubyConf 2008 presentation about Johnson</a> for more details about that project.</p>
<p>Number 2, I believe, has been solved by <a href="http://github.com/tenderlove/nokogiri">nokogiri</a>.  As far as I can tell, the tree generated inside libxml2 is very similar to one found in the browser.  Nokogiri was partly a Yak Shave for number 3.  Since I had writing a DOM interface in mind, nokogiri&#8217;s api lends well to writing a DOM api.</p>
<p>Number 3 was <i>partly</i> solved this weekend.  I&#8217;ve been working on a DOM api called <a href="http://github.com/tenderlove/taka">taka</a>.  Taka sits a DOM api on top of nokogiri.  The goal of the project is to mirror a browser&#8217;s DOM api in Ruby.</p>
<p>With these three tools in place, I believe that we have a good start on a browserless JavaScript testing environment.</p>
<h2>Codes</h2>
<p>Enough talk.  Let&#8217;s look at some codes.  Take this HTML page for example:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
  &lt;head&gt;
    &lt;script&gt;
      function populateDropDown() {
        var select = document.getElementById('colors');
        var options = ['red', 'green', 'blue', 'black'];
        var i;
        for(i = 0; i &lt; options.length; i++) {
          var option = document.createElement('option');
          option.appendChild(document.createTextNode(options[i]));
          option.value = options[i];
          select.appendChild(option);
        }
      }
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body onload=&quot;populateDropDown()&quot;&gt;
    &lt;h1&gt;Behold the Johnson&lt;/h1&gt;
    &lt;form&gt;
      &lt;select id=&quot;colors&quot;&gt;
      &lt;/select&gt;
    &lt;/form&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The JavaScript in this HTML will add a few option tags as children of the select tag.  Effectively populating the drop down for our user.  It would be nice if we could write a test to assert that when this JavaScript executes, the option tags are actually added as children of the select tag.</p>
<p>With Johnson and Taka, it is possible to write such a test:</p>
<pre class="brush: ruby; title: ; notranslate">
require 'rubygems'
require 'taka'
require 'johnson'
require 'test/unit'

class OptionTagsAppendedTest &lt; Test::Unit::TestCase
  def setup
    # Create our DOM object
    @document = Taka::DOM::HTML(DATA.read)

    # Create a new JavaScript runtime
    @rt = Johnson::Runtime.new

    # Set the document in the runtime
    @rt['document'] = @document

    # Execute any script tags
    @document.getElementsByTagName('script').each do |script|
      @rt.evaluate(script.textContent);
    end
  end

  def test_options_populated_by_onload
    # 0 option tags before onload is executed
    assert_equal 0, @document.getElementsByTagName('option').length

    # Execute the onload body attribute
    @rt.evaluate(@document.getElementsByTagName('body')[0].onload)

    # 4 option tags after onload is executed
    assert_equal 4, @document.getElementsByTagName('option').length
  end
end
</pre>
<p>There.  It&#8217;s done.  This test executes the JavaScript and manipulates your HTML the same way the browser would.  You can run this code today, just make sure to install the johnson and taka gems first.</p>
<h3>Problems</h3>
<p>There are at least a few problems.  This HTML code is, admittedly, carefully crafted.  So far, taka only implements the DOM 1 interface.  That means taka is missing many methods that are available in browsers.  The good news though is that Taka is pure ruby and open source.  As soon as you find methods that are missing, <a href="http://github.com/tenderlove/taka">fork the repo, add a test, and send a pull request</a>.  I will be sure to merge it.</p>
<h3>Conclusion</h3>
<p>We are making progress towards testing JavaScript without a browser.  We have to do it a step at a time.  The solution I have presented to you, while not complete, has promise.  I think that the only thing standing in our way <i>right now</i> is time and man power.  The methods that need to be implemented on Taka to make it mirror a browser are not hard (take a look at the taka source).  These methods just need to be written.</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2009/04/05/testing-javascript-outside-the-browser/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Write your Rails view in&#8230;&#8230;.  JavaScript?</title>
		<link>http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/</link>
		<comments>http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/#comments</comments>
		<pubDate>Tue, 06 May 2008 18:33:30 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
				<category><![CDATA[johnson]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=139</guid>
		<description><![CDATA[In my last post about Johnson, I said that next time I would talk about the JavaScript parse tree that Johnson provides. Well, I changed my mind. Sorry. I want to write about a rails plugin that I added to Johnson. Brohuda Katz wrote an ERb type parser in JavaScript, and added it to the [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="/2008/04/23/take-it-to-the-limit-one-more-time/">last post about Johnson</a>, I said that next time I would talk about the JavaScript parse tree that <a href="http://github.com/jbarnette/johnson/tree/master">Johnson</a> provides.  Well, I changed my mind.  Sorry.</p>
<p>I want to write about a rails plugin that I added to Johnson.  <a href="http://www.yehudakatz.com/">Brohuda Katz</a> wrote an <a href="http://github.com/jbarnette/johnson/tree/master/js/johnson/template.js">ERb type parser in JavaScript</a>, and added it to the (yet to be released) Johnson distribution.  With that in mind, and looking at the new template handlers in edge rails, I was able to throw together a rails plugin that allows me to use JavaScript in my rails view code.</p>
<p>Lets get to the code.  Here is my controller:</p>
<pre class="brush: ruby; title: ; notranslate">
class JohnsonController &lt; ApplicationController
  def index
    @users = User.find(:all)
  end
end
</pre>
<p>And my EJS view (the file is named index.html.ejs):</p>
<pre class="brush: php; title: ; notranslate">
&lt;% for(var user in at.users) { %&gt;
  &lt;%= user.first_name() %&gt;&lt;br /&gt;
&lt;% } %&gt;
</pre>
<p>The johnson rails plugin puts controller instance variables in to a special javascript variable called &#8220;at&#8221;.  The &#8220;at&#8221; variable is actually a proxy to the controller, lazily fetching instance variables from the controller and importing those objects in to javascript land.</p>
<p>Lets take a look at the plugin, its only a few lines:</p>
<pre class="brush: ruby; title: ; notranslate">
class EJSHandler &lt; ActionView::TemplateHandler
  class EJSProxy # :nodoc:
    def initialize(controller)
      @controller = controller
    end

    def key?(pooperty)
      @controller.instance_variables.include?(&quot;@#{pooperty}&quot;)
    end

    def [](pooperty)
      @controller.instance_variable_get(&quot;@#{pooperty}&quot;)
    end

    def []=(pooperty, value)
      @controller.instance_variable_set(&quot;@#{pooperty}&quot;, value)
    end
  end

  def initialize(view)
    @view = view
  end

  def render(template)
    ctx = Johnson::Context.new
    ctx.evaluate('Johnson.require(&quot;johnson/template&quot;);')
    ctx['template'] = template.source
    ctx['controller'] = @view.controller
    ctx['at'] = EJSProxy.new(@view.controller)

    ctx.evaluate('Johnson.templatize(template).call(at)')
  end
end

ActionView::Template.register_template_handler(&quot;ejs&quot;, EJSHandler)
</pre>
<p>When the template gets rendered (the render method), I wrap the controller with an EJS proxy, then compile the template into a javascript function, and call that function.  The &#8220;at&#8221; variable is set to the EJSProxy before executing the template, and all property accessing on the &#8220;at&#8221; variable is passed along to fetching instance variables from the controller.</p>
<p>Server side javascript coding in rails.  Weird, eh?</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Take it to the limit one more time</title>
		<link>http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/</link>
		<comments>http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 18:22:29 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
				<category><![CDATA[computadora]]></category>
		<category><![CDATA[ecma]]></category>
		<category><![CDATA[johnson]]></category>
		<category><![CDATA[rkelly]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=138</guid>
		<description><![CDATA[Sup bros. I need to post in this thing more often. Yesterday, someone tipped over my scooter again. I&#8217;m getting kind of tired of that. Anyway, its time for me to write about this. RKelly is pretty much dead. For the past few months, John and I have been working on RKelly&#8217;s replacement called Johnson. [...]]]></description>
			<content:encoded><![CDATA[<p>Sup bros.  I need to post in this thing more often.  Yesterday, someone tipped over <a href="http://flickr.com/photos/aaronp/150189237/">my scooter</a> again.  I&#8217;m getting kind of tired of that.</p>
<p>Anyway, its time for me to write about this.  <a href="http://rubyforge.org/projects/rkelly/">RKelly</a> is pretty much dead.  For the past few months, <a href="http://geeksomnia.com/">John</a> and I have been working on RKelly&#8217;s replacement called <a href="http://github.com/jbarnette/johnson/tree/master">Johnson</a>.  Basically we&#8217;re now putting a ruby wrapper around <a href="http://www.mozilla.org/js/spidermonkey/">Mozilla&#8217;s Spidermonkey</a>.  The project is coming along quite nicely.  Ruby objects can be passed in to javascript land, and javascript objects can be passed back in to ruby land.</p>
<p>For example, we can define an alert function in our javascript context:</p>
<pre class="brush: ruby; title: ; notranslate">
require 'johnson'

ctx = Johnson::Context.new
ctx['alert'] = lambda { |x| puts x }
ctx.evaluate('alert(&quot;Hello world!&quot;);')
</pre>
<p>Johnson::Context#evaluate will also return the last statement evaluated.  We can evaluate an expression, and manipulate that expression in ruby land.  For example, I&#8217;ll create an object in javascript, return it to ruby land, then access a property of the javascript object:</p>
<pre class="brush: ruby; title: ; notranslate">
require 'johnson'

ctx = Johnson::Context.new
obj = ctx.evaluate('var foo = { x: &quot;hello world&quot; }; foo')
puts obj.x  # =&gt; 'hello world'
</pre>
<p>We can even do the reverse by stuffing ruby objects in to the context:</p>
<pre class="brush: ruby; title: ; notranslate">
A = Struct.new(:foo)

ctx = Johnson::Context.new
ctx['alert'] = lambda { |x| puts x }
ctx['a'] = A.new(&quot;bar&quot;)
ctx.evaluate('alert(a.foo);') # =&gt; 'bar'
</pre>
<p>But it gets better.  We added a top level variable called &#8220;Ruby&#8221; that lets you access constants and globals from Ruby land.  We can rewrite the previous example completely in javascript:</p>
<pre class="brush: ruby; title: ; notranslate">
ctx = Johnson::Context.new
ctx.evaluate(&quot;var x = new (new Ruby.Struct(Johnson.symbolize('foo')));&quot;)
ctx.evaluate(&quot;x.foo = 'bar'&quot;)
puts ctx.evaluate('x').foo # =&gt; 'bar'
puts ctx.evaluate('x').class # =&gt; #&lt;Class:0x49714&gt;
</pre>
<p>Since the &#8216;Ruby&#8217; constant delegates to Object, you can access any constant.  Including ones you&#8217;ve defined yourself.  We could, for example, look up a bunch of User records through rails:</p>
<pre class="brush: ruby; title: ; notranslate">
ctx = Johnson::Context.new
ctx['alert'] = lambda { |x| puts x }
ctx.evaluate(&lt;&lt;-END
             for(var user in Ruby.User.find(Johnson.symbolize('all'))) {
               alert(user.first_name());
             }
             END
            )
</pre>
<p>You might be wondering what this Johnson.symbolize business is about.  Since Javascript doesn&#8217;t have a concept of a symbol, we&#8217;ve created a helper to &#8220;mark&#8221; a string as a symbol and pass it back in to ruby land.</p>
<p>To conclude this update about my Johnson, I&#8217;d like to show off an interactive shell for Johnson (thanks to <a href="http://www.yehudakatz.com/">Brohuda Katz</a>).  Johnson has an interactive shell that lets you try things out in javascript land or ruby land, and let you quickly switch between the two.  Typing &#8216;js&#8217; will put in you the javascript shell, &#8216;rb&#8217; will switch you to the ruby shell.  In the ruby shell, you can use the &#8216;cx&#8217; variable to get ahold of you javascript context:<br />
<code><br />
$ ruby -I lib bin/johnson<br />
js> var x = { foo: 'bar', hello: function() { return 'world' } };<br />
=> nil<br />
js> rb<br />
rb> cx['x'].foo<br />
=> "bar"<br />
rb> cx['x'].hello()<br />
=> "world"<br />
rb><br />
[/sourcecode]<br />
We aren't quite ready for a release yet, but if you'd like to play around with Johnson, you can pull it down from github <a href="http://github.com/jbarnette/johnson/tree/master">here</a>.  Just run 'rake', and you should have it compiled and running!</p>
<p>My next Johnson related post will be about Javascript parse trees and Javascript code generation.</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

