Tuesday, January 10, 2012

#Import, #Include and Real Dart Pages

‹prev | My Chain | next›

One of the more intriguing claims made by Dart is that is is made for the modern web. In my mind, the "modern web" means two things: library support and easy DOM manipulation. I should not have to resort to heavy browser hacks like require.js to load libraries like a real language can. I should be able to query and manipulate the DOM like jQuery.

To Dartium!

First, I need a web page. I borrow my fibonacci solution from last night, but adopt it to work in a web page:
<html>
  <script>{}</script>
  <body>
    <h1>Fibonacci!</h1>
    <div id="status"></div>
  </body>

  <script type="application/dart">
    #import('dart:html');
    #import('pretty_stopwatch.dart');
    void main() {
      var list = [5, 40, 39, 32, 6, 41];

      var timer = new PrettyStopwatch.start();
      list.forEach(fib_printer);
      timer.stop();
    }

    fib_printer(i) {
      var answer = fib(i)
        , el = new Element.tag('div');

      el.innerHTML = "fib(${i}) = " + answer;
      document.query('#status').nodes.add(el);
    }

    fib(i) {
      if (i < 2) return i;
      return fib(i-2) + fib(i-1);
    }

  </script>
</html>
Starting from the top of that HTML, I need an empty script in current Dartium builds to ensure that Javascript / Dart engines are engaged:
<script>{}</script>
The following bit of HTML is fairly plain:
  <body>
    <h1>Fibonacci!</h1>
    <div id="status"></div>
  </body>
I will stick the results of my fibonacci lists into the #status <div>.

Now comes the <script type="application/dart"> to define the script to be run on this page. The first lines of my Dart script import the built-in HTML library and my own "pretty printing timer":
    #import('dart:html');
    #import('pretty_stopwatch.dart');
The important thing to note here is that pretty_stopwatch.dart is stored on the filesystem alongside the HTML. I am not doing anything fancy to pull that code into my page's runtime—other than a very simple #import call. That is very modern indeed.

The main() block of code defines the list of numbers for which I would like to calculate the corresponding fibonacci number, iterates through each to perform that calculation and wraps the whole thing inside a timer:
    void main() {
      var list = [5, 40, 39, 32, 6, 41];

      var timer = new PrettyStopwatch.start();
      list.forEach(fib_printer);
      timer.stop();
    }
Of note in there is a little short-cut inside the forEach. It seems that very simple functions that take a single argument and then call another function with the same argument can be simplified to just the invoked function. Here, I am using fib_printer where I could have used the wordier (i) {fib_printer(i)}. That is a nice little convenience that I plan on using quite a bit.

Next, I make use of dart:html to create a <div> tag, add the fibonacci answer to it, and add the whole thing to the list of nodes underneath the #status element:
    fib_printer(i) {
      var answer = fib(i)
        , el = new Element.tag('div');

      el.innerHTML = "fib(${i}) = " + answer;
      document.query('#status').nodes.add(el);
    }
The remainder of the page is only last night's simple fibonacci calculator:
    fib(i) {
      if (i < 2) return i;
      return fib(i-2) + fib(i-1);
    }
And that's it! When I load the page, I see:


Last up tonight, I move those two fibonacci functions into their own Dart file:
// fib_printer.dart
fib_printer(i) {
  var answer = fib(i)
    , el = new Element.tag('div');

  el.innerHTML = "fib(${i}) = " + answer;
  document.query('#status').nodes.add(el);
}

fib(i) {
  if (i < 2) return i;
  return fib(i-2) + fib(i-1);
}
To get these in the original HTML, I need to "source" that library:
<script type="application/dart">
    #import('dart:html');
    #import('pretty_stopwatch.dart');
    #source('fib_printer.dart');
    void main() {
      var list = [5, 40, 39, 32, 6, 41];

      var timer = new PrettyStopwatch.start();
      list.forEach(fib_printer);
      timer.stop();
    }
  </script>
No other changes are required to allow me to factor those two functions out into a self-contained set of functions that I can mix-in anywhere. That is quite nice.


Day #261

2 comments:

  1. Hi chris,
    Starting to use Dartium now in your posts? BTW, I have a build for download and some instructions for Dartium http://goo.gl/ZZboE

    Regards,
    Adam

    ReplyDelete
  2. @Adam Yup. I can't avoid Dartium :)

    Cool, that build is sure to help folks. It definitely beats 36 hours of downloading and compiling!

    ReplyDelete