/harmony

Javascript + DOM in your ruby, the simple way

Primary LanguageRubyMIT LicenseMIT

Harmony

                   .,ad88888888baa,
               ,d8P"""        ""9888ba.
            .a8"          ,ad88888888888a
           aP'          ,88888888888888888a
         ,8"           ,88888888888888888888,
        ,8'            (888888888( )888888888,
       ,8'             `8888888888888888888888
       8)               `888888888888888888888,
       8                  "8888888888888888888)
       8                   `888888888888888888)
       8)                    "8888888888888888
       (b                     "88888888888888'
       `8,        (8)          8888888888888)
        "8a                   ,888888888888)
          V8,                 d88888888888"
           `8b,             ,d8888888888P'
             `V8a,       ,ad8888888888P'
                ""88888888888888888P"
                     """"""""""""

Summary

Harmony provides a simple DSL to execute javascript + DOM code within ruby.

Examples

Simple Javascript Parsing

require 'harmony'

page = Harmony::Page.new(<<-HTML)
  <html>
    <head>
      <title>Foo</title>
    </head>
    <body></body>
  </html>
HTML

page.execute_js("1+1")            #=> 2
page.execute_js("document.title") #=> "Foo"

The Page object's #execute_js method (aliased as #x for convenience) takes a string of javascript code, executes it and returns the last statement's value (just like a ruby method).

Javascript Unit Tests

One interesting use of Harmony is to test your javascript code within your ruby application's own tests (test/unit, minitest, RSpec, nanotest, etc). Which consequently means that you can now run browser-less, fully command-line based, DOM-javascript tests.

require 'test/unit'
require 'harmony'

class JavascriptTest < Test::Unit::TestCase
  def setup
    @page = Harmony::Page.new
    @page.load('public/javascripts/foo.js')
  end

  def test_foo
    assert_equal "world", @page.execute_js(<<-JS)
      foo = new Foo;
      foo.hello();
    JS
  end
end

DOM Handling

Don't be affraid to throw in your favorite client-side js framework, like JQuery or Prototype. And notice that scripts linked to in <script> tags will automatically get pulled in.

require 'harmony'

page = Harmony::Page.new(<<-HTML)
  <html>
    <head>
      <script src="javascripts/jquery.js" type="text/javascript"></script>
    </head>
    <body>
      <div id="widget">ohaie</div>
    </body>
  </html>
HTML

page.execute_js("$('#widget').innerHTML") #=> "ohaie"

Fetching Documents

Use Harmony::Page.fetch(uri) to create a page from a remote document.

require 'harmony'

page = Harmony::Page.fetch('http://example.com')
page.execute_js('document.title') #=> "Example Web Page"

fetch also accepts "file://" uris.

Install

# There's a gem dependency bug in rubygems currently, so we'll have to
# install dependencies manually. This will be fixed soon.
gem install stackdeck
gem install johnson -v "2.0.0.pre2"

gem install harmony

See Also

Acknowledgement

Harmony is a thin DSL wrapper around three amazing libs, Johnson, env.js and Envjs . The authors of those libs have been doing a huge amount of great work for quite a while, so please go recommend them on WorkingWithRails right now and/or follow them on github:

jbarnette, tenderlove, smparkes, wycats, matthewd, thatcher, jeresig

Special thanks go to smparkes for his patient help, and for providing the last puzzle pieces that made everything work together.

Links

YinYang ASCII art is © Normand Veilleux (nveilleuATemr1.emrDOTca)