<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CkYMQn47eSp7ImA9WhRbEUs.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527</id><updated>2012-02-02T00:23:03.001-05:00</updated><category term="iso8601" /><category term="xsl" /><category term="postgresql" /><category term="sysadmin" /><category term="cucumber-save" /><category term="clojure" /><category term="bug" /><category term="development" /><category term="date" /><category term="fabjs" /><category term="hydra" /><category term="chrome" /><category term="firefox" /><category term="passenger" /><category term="css" /><category term="raphaeljs" /><category term="push" /><category term="legendary" /><category term="git" /><category term="rack" /><category term="gem" /><category term="couch_docs" /><category term="nginx" /><category term="rails" /><category term="phantomjs" /><category term="v8" /><category term="bdd" /><category term="rack-cache" /><category term="float" /><category term="changes" /><category term="sort" /><category term="virtualbox" /><category term="spdy" /><category term="inside-out" /><category term="webrat" /><category term="retrospective" /><category term="refactoring" /><category term="anti-pattern" /><category term="rails3" /><category term="jasmine" /><category term="cucumber" /><category term="openssl" /><category term="mobi" /><category term="smoke-test" /><category term="couchdb-lucene" /><category term="wireshark" /><category term="jquery-ui" /><category term="rest" /><category term="less css" /><category term="vlad" /><category term="rspec" /><category term="dartlang" /><category term="svg" /><category term="vowsjs" /><category term="ssl" /><category term="sinatra" /><category term="benchmarking" /><category term="testing" /><category term="coffeescript" /><category term="datamapper" /><category term="zlib" /><category term="prototype" /><category term="json" /><category term="subversion" /><category term="exocortex" /><category term="ruby" /><category term="haml" /><category term="trunk" /><category term="couchdb" /><category term="attachment_fu" /><category term="print-stderr" /><category term="tcpdump" /><category term="javascript" /><category term="sctp" /><category term="git-scribe" /><category term="cache" /><category term="faye" /><category term="github" /><category term="websockets" /><category term="underscorejs" /><category term="backbonejs" /><category term="merb" /><category term="couch_design_docs" /><category term="npm" /><category term="couch-replicate" /><category term="compression" /><category term="expresso" /><category term="dart" /><category term="newbies" /><category term="commonjs" /><category term="agile" /><category term="python" /><category term="planning" /><category term="jeweler" /><category term="physics engine" /><category term="craftsmanship" /><category term="debian" /><category term="nodejs" /><category term="canvas" /><category term="requirejs" /><category term="haproxy" /><category term="inkscape" /><category term="calibre" /><category term="helpers" /><category term="expressjs" /><category term="thinking" /><category term="vps" /><category term="apache" /><category term="sinonjs" /><category term="node-dirty" /><category term="mod_spdy" /><category term="emacs" /><category term="dry" /><category term="beep" /><category term="process" /><category term="thin" /><category term="outside-in" /><category term="eventmachine" /><category term="chain" /><category term="views" /><category term="deployment" /><category term="sorting" /><category term="edge" /><category term="lucene" /><category term="monitoring" /><category term="couchapp" /><category term="pagination" /><category term="comet" /><category term="jquery" /><category term="tracer bullets" /><category term="named_scope" /><category term="public commitment" /><category term="active_record" /><category term="pipelining" /><category term="regression testing" /><category term="twitter" /><category term="npn" /><category term="class variables" /><category term="god" /><category term="exception" /><category term="jade" /><category term="spike" /><category term="oshn" /><category term="management" /><title>japh(r) by Chris Strom</title><subtitle type="html">Just Another Perl… Ruby… Just a Hacker</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://japhr.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>783</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/JaphrByChrisStrom" /><feedburner:info uri="japhrbychrisstrom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CkcNSHcyeyp7ImA9WhRbEUs.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-7703525657901694666</id><published>2012-02-01T23:59:00.001-05:00</published><updated>2012-02-02T00:21:39.993-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-02T00:21:39.993-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart Views for Creating Ajax Records</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/custom-events-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;span style="color: #ccc"&gt;next&amp;rsaquo;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I am relatively pleased, so far, with my refactoring of my &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; Ajax powered application into more of an MVC approach.  If nothing else, I have cleared away considerable amounts of the callback spaghetti code previously:&lt;pre class="prettyprint"&gt;#import('dart:html');
#import('dart:json');

main() { /* ... */ }
attach_create_handler() { /* ... */ }
enable_create_form(event) { /* ... */ }
_ensure_create_form(id_selector) { /* ... */ }
_show_form(form_container) { /* ... */ }
_attach_form_handlers(form_container) { /* ... */ }
_submit_create_form(form) { /* ... */ }
_disable_create_form(event) { /* ... */ }
load_comics() { /* ... */ }
attach_handler(parent, event_selector, callback) { /* ... */ }
delete(id, [callback]) { /* ... */ }
graphic_novels_template(list) { /* ... */ }
graphic_novel_template(graphic_novel) { /* ... */ }
form_template([graphic_novel]) { /* ... */ }&lt;/pre&gt;I replaced the bulk of that code with a collection class:&lt;pre class="prettyprint"&gt;#library('Collection View for My Comic Book Collection');

#import('dart:html');
#import('dart:json');

class ComicsCollectionView {
  var get el;
  var get collection;

  ComicsCollectionView([el, collection]) {/*...*/}

  // Be Backbone-lik
  render() {/*...*/}
  template(list) {/*...*/}

  // private helper methods
  _singleComicBookTemplate(comic) {/*...*/}
  _attachUiHandlers() {/*...*/}

  // Need to move these elsewhere
  delete(id, [callback]) {/*...*/}
  attach_handler(parent, event_selector, callback) {/*...*/}
}&lt;/pre&gt;And a Collection class:&lt;pre class="prettyprint"&gt;#library('Collection class to describe my comic book collection');

#import('dart:html');
#import('dart:htmlimpl');
#import('dart:json');

class ComicsCollection {
  var list;
  var get on;

  ComicsCollection() {/*...*/}

  // Be List-like
  forEach(fn) {/*...*/}
  get length() {/*...*/}

  // Be Backbone-like
  fetch() {/*...*/}

  // private helper methods
  _handleOnLoad(event) {/*...*/}
}

// Support MVC events
class CollectionEvents implements Events {/*...*/}
class CollectionEventList implements EventListenerList {/*...*/}&lt;/pre&gt;I especially like the Collection class—it does its thing with very few extraneous methods.&lt;br /&gt;
&lt;br /&gt;
The view class could probably benefit from being broken into a collection view &lt;i&gt;plus&lt;/i&gt; a sub-view for the individual items in the collection. Aside from that, I also have a bit of Model code (&lt;code&gt;delete()&lt;/code&gt;) lurking in there.  I will get to that in a bit (probably tomorrow).  First, I would like to finish extracting code out of my earlier mess.&lt;br /&gt;
&lt;br /&gt;
Left in the &lt;code&gt;main()&lt;/code&gt; entry point of my application is Collection and View instantiation along with a call to &lt;code&gt;attach_create_handler()&lt;/code&gt;:&lt;pre class="prettyprint"&gt;main() {
  var my_comics_collection = new ComicsCollection()
    , comics_view = new ComicsCollectionView(
        el:'#comics-list',
        collection: my_comics_collection
      );

  my_comics_collection.fetch();

&lt;b&gt;  attach_create_handler();&lt;/b&gt;
}&lt;/pre&gt;That handler function is responsible for attaching a handler to the already existing &lt;code&gt;#add-comics&lt;/code&gt; element, establishing a click handler to display a form.  Say, that sounds an awful lot like View work.  So I replace &lt;code&gt;attach_create_handler()&lt;/code&gt; with a new view:&lt;pre class="prettyprint"&gt;#import('ComicsCollection.dart');
#import('ComicsCollectionView.dart');
&lt;b&gt;#import('AddComicView.dart');&lt;/b&gt;

main() {
  var my_comics_collection = new ComicsCollection()
    , comics_view = new ComicsCollectionView(
        el:'#comics-list',
        collection: my_comics_collection
      );

  my_comics_collection.fetch();

&lt;b&gt;  new AddComicView(el:'#add-comic');&lt;/b&gt;
}&lt;/pre&gt;That is now the entire contents of the main &lt;code&gt;comics.dart&lt;/code&gt; file.  This is the only file that is loaded via a &lt;code&gt;&amp;lt;script&gt;&lt;/code&gt; tag.  All of the other code comes from those &lt;code&gt;#import()&lt;/code&gt; statements at the top the file. That is all kinds of nice.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;AddComicView()&lt;/code&gt; view is solely responsible for toggling the form:&lt;pre class="prettyprint"&gt;#library('Simple view to toggle new comic form view');

#import('dart:html');

#import('AddComicFormView.dart');

class AddComicView {
  var get el;
  var get collection;

  var form_view;

  AddComicView([el]) {
    this.el = document.query(el);

    _attachUiHandlers();
  }

  _attachUiHandlers() {
    el.on.click.add(_toggle_form);
  }

  _toggle_form(event) {
    if (form_view == null) {
      form_view = new AddComicFormView();
      form_view.render();
    }
    else {
      form_view.remove();
      form_view = null;
    }
  }
}&lt;/pre&gt;The &lt;code&gt;AddComicFormView&lt;/code&gt; is pretty straight-forward (and the guts most copied from the old callback spaghetti):&lt;pre class="prettyprint"&gt;#library('Form view to add new comic book to my sweet collection.');

#import('dart:html');

class AddComicFormView {
  var get el;

  AddComicFormView() {
    this.el = new Element.html('&amp;lt;div id="add-comic-form"/&gt;');
    this.el.style.opacity = "0";

    document.body.nodes.add(this.el);

    _attachUiHandlers();
  }

  _attachUiHandlers() {
    attach_handler(el, 'submit form', (event) {
      event.preventDefault();
      _submit_create_form(event.target);
    });

    attach_handler(el, 'click a', (event) {
      event.preventDefault();
      _disable_create_form(event);
    });
  }

  render() {...}

  remove() {
    this.el.remove();
  }

  template() {
    return """
&amp;lt;form action="comics" id="new-comic-form"&gt;
....
&amp;lt;/form&gt;
""";
  }

  _disable_create_form(event) {...}

  attach_handler(parent, event_selector, callback) {...}

  // Thar be model code here...
  _submit_create_form(event) {...}
}&lt;/pre&gt;And, yup, it still works:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-wppOBtlmW6k/TyoZ8Tb2ZPI/AAAAAAAADDA/YDM3R6JVbds/s1600/01-still_working.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="269" src="http://4.bp.blogspot.com/-wppOBtlmW6k/TyoZ8Tb2ZPI/AAAAAAAADDA/YDM3R6JVbds/s400/01-still_working.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
My not-another-MVC-framework framework is coming along nicely.  Except for the distinct lack of "M". And the presence of Model code in the Views (e.g. &lt;code&gt;_submit_create_form()&lt;/code&gt;). I will address that tomorrow.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #283&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-7703525657901694666?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/q29wbi_lXIB1oHNJGjy6maPz5_4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q29wbi_lXIB1oHNJGjy6maPz5_4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/q29wbi_lXIB1oHNJGjy6maPz5_4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q29wbi_lXIB1oHNJGjy6maPz5_4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/_RNj5PU_rnA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/7703525657901694666/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/02/dart-views-for-creating-ajax-records.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7703525657901694666?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7703525657901694666?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/_RNj5PU_rnA/dart-views-for-creating-ajax-records.html" title="Dart Views for Creating Ajax Records" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wppOBtlmW6k/TyoZ8Tb2ZPI/AAAAAAAADDA/YDM3R6JVbds/s72-c/01-still_working.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/02/dart-views-for-creating-ajax-records.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYMQn47cSp7ImA9WhRbEUs.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-7149094997598985711</id><published>2012-01-31T02:16:00.001-05:00</published><updated>2012-02-02T00:23:03.009-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-02T00:23:03.009-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Custom Events in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/psuedo-view-classes-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/02/dart-views-for-creating-ajax-records.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I have a deadline for the alpha release for &lt;a href="http://dart4hipsters.com/"&gt;Dart for Hipsters&lt;/a&gt;, but before I can get to that, I must appease the gods of my chain. I have yet to meet these gods, but they have been kind to me, so I must do what I can to keep them happy.&lt;br /&gt;
&lt;br /&gt;
Last night I got started breaking my Ajax based &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; application into real View classes (somewhat along the lines of &lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone.js&lt;/a&gt;).  Today, I hope to extract collection code from my view into a proper collection class.&lt;br /&gt;
&lt;br /&gt;
The heart of the collection, the fetching from the backend datastore, I can already do:&lt;pre class="prettyprint"&gt;class ComicsCollection {
  var list;

  ComicsCollection() {
  }

  // Be Backbone like
  fetch() {
    var req = new XMLHttpRequest();

    req.on.load.add(_handleOnLoad);
    req.open('get', '/comics', true);
    req.send();
  }

  _handleOnLoad(event) {
    var request = event.target;

    list = JSON.parse(request.responseText);

&lt;b&gt;    // How to tell the view that I'm done?&lt;/b&gt;
  }
}&lt;/pre&gt;But how can I communicate to my view that the collection has loaded new data? &lt;br /&gt;
&lt;br /&gt;
I would like to instantiate a collection and a collection view something along the lines of:&lt;pre class="prettyprint"&gt;&lt;code&gt;  var my_comics_collection = new ComicsCollection()
    , comics_view = new ComicsCollectionView(
        el:'#comics-list',
        collection: my_comics_collection
      );

  my_comics_collection.fetch();&lt;/code&gt;&lt;/pre&gt;In the collection view, I could then subscribe to the collection view's on-load event:&lt;pre class="prettyprint"&gt;&lt;code&gt;  ComicsCollectionView([el, collection]) {
    this.el = document.query(el);
    this.collection = collection;

&lt;b&gt;    collection.on.load.add((event) {
      render();
    });&lt;/b&gt;
  });&lt;/code&gt;&lt;/pre&gt;To get that to work, I will at least need an &lt;code&gt;on&lt;/code&gt; getter in the Collection:&lt;pre class="prettyprint"&gt;class ComicsCollection {
  var list;
  var get on;

  ComicsCollection() {
    on = new CollectionEvents();
  }
}&lt;/pre&gt;I could probably re-use one of the DOM &lt;code&gt;Events&lt;/code&gt; classes here, but it is not too hard to define my own:&lt;pre class="prettyprint"&gt;class CollectionEvents implements Events {
  var load_list;

  CollectionEvents() {
    load_list = new CollectionEventList();
  }

  get load() {
    return load_list;
  }
}&lt;/pre&gt;I defined a &lt;code&gt;load&lt;/code&gt; getter that returns an &lt;code&gt;EventList&lt;/code&gt; object. This &lt;code&gt;CollectionEventList&lt;/code&gt; class that I define will be the thing that holds event listeners.  It needs to define two methods: &lt;code&gt;add()&lt;/code&gt; to add listeners and &lt;code&gt;dispatch()&lt;/code&gt; to send events to all listeners:&lt;pre class="prettyprint"&gt;class CollectionEventList implements EventListenerList {
  var listeners;

  CollectionEventList() {
    listeners = [];
  }

  add(fn) {
    listeners.add(fn);
  }

  bool dispatch(Event event) {
    listeners.forEach((fn) {fn(event);});
    return true;
  }
}&lt;/pre&gt;No doubt I can be a little more elegant about that, but that should meet the spirit of what is needed. Amazingly, that does work.  To be sure that I am not somehow faking it, I add another debugging on-load handler to listen for my custom event:&lt;pre class="prettyprint"&gt;class ComicsCollectionView {
  var get el;
  var get collection;

  ComicsCollectionView([el, collection]) {
    this.el = document.query(el);
    this.collection = collection;

    collection.on.load.add((event) {
      render();
    });

&lt;b&gt;    collection.on.load.add((event) {
      print("This really did fire in response to a custom event");
    });&lt;/b&gt;

    _attachUiHandlers();
  }

  // ...
}&lt;/pre&gt;And indeed, it does work:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-L86pRALg730/TyeUnb7nLZI/AAAAAAAADC0/FTa-7EKOq50/s1600/01-custom_events.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="113" width="400" src="http://2.bp.blogspot.com/-L86pRALg730/TyeUnb7nLZI/AAAAAAAADC0/FTa-7EKOq50/s400/01-custom_events.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Nice. That almost seems a little too easy. I will take a look at this in the fresh light of a new day to make sure that I am not cheating somehow. If custom event handlers in Dart really are this easy, then I am thrilled. Bust mostly I'm sleepy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #282&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-7149094997598985711?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MkPzUR_LtDtt9cXZx1nHdgRANAY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MkPzUR_LtDtt9cXZx1nHdgRANAY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MkPzUR_LtDtt9cXZx1nHdgRANAY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MkPzUR_LtDtt9cXZx1nHdgRANAY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/olxotomx2_w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/7149094997598985711/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/custom-events-in-dart.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7149094997598985711?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7149094997598985711?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/olxotomx2_w/custom-events-in-dart.html" title="Custom Events in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-L86pRALg730/TyeUnb7nLZI/AAAAAAAADC0/FTa-7EKOq50/s72-c/01-custom_events.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/custom-events-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQCSHszfyp7ImA9WhRUGUQ.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-7720373851825088543</id><published>2012-01-30T23:29:00.000-05:00</published><updated>2012-01-31T02:19:29.587-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-31T02:19:29.587-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Psuedo View Classes in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/removing-dom-element-with-dart-tale-of.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/custom-events-in-dart.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Today, I think, I am in need of some code re-organization.  Currently my simple CRUD-over-XHR &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; application looks like:&lt;pre class="prettyprint"&gt;#import('dart:html');
#import('dart:json');

main() { /* ... */ }
attach_create_handler() { /* ... */ }
enable_create_form(event) { /* ... */ }
_ensure_create_form(id_selector) { /* ... */ }
_show_form(form_container) { /* ... */ }
_attach_form_handlers(form_container) { /* ... */ }
_submit_create_form(form) { /* ... */ }
_disable_create_form(event) { /* ... */ }
load_comics() { /* ... */ }
attach_handler(parent, event_selector, callback) { /* ... */ }
delete(id, [callback]) { /* ... */ }
graphic_novels_template(list) { /* ... */ }
graphic_novel_template(graphic_novel) { /* ... */ }
form_template([graphic_novel]) { /* ... */ }&lt;/pre&gt;That's quite a mess that I have made for myself. &lt;br /&gt;
&lt;br /&gt;
I have no intention of creating yet another MVC framework, but I would like to at least create two view-like things to bring some semblance of organization to this project. I start by replacing the &lt;code&gt;load_comics()&lt;/code&gt; entry point in &lt;code&gt;main()&lt;/code&gt;:&lt;pre class="prettyprint"&gt;main() {
  load_comics();
}&lt;/pre&gt;I replace that, because I lack imagination, with a very Backbone looking object:&lt;pre class="prettyprint"&gt;main() {
  var comics = new ComicsCollectionView('#comics-list');
  comics.render();
}&lt;/pre&gt;Now to make that work...&lt;br /&gt;
&lt;br /&gt;
I am going to do this entirely in a separate class library, so I make a &lt;code&gt;ComicsCollectionView.dart&lt;/code&gt; file with the following contents:&lt;pre class="prettyprint"&gt;#library('Collection View for My Comic Book Collection');

#import('dart:html');

class ComicsCollectionView {
  var get el;

  ComicsCollectionView(target_el) {
    el = document.query(target_el);
  }

  render() {
    print("Replace me with real code soon");
    print(el);
  }
}&lt;/pre&gt;I declare my &lt;code&gt;el&lt;/code&gt; property as a getter because I seem to recall having access to that in Backbone. For now, I will not expose a corresponding setter. In the constructor, I query the document for the supplied element (this forces me to import &lt;code&gt;'dart:html'&lt;/code&gt;).  Then I expose a simple &lt;code&gt;render()&lt;/code&gt; method that serves as tracer bullets for where I need to go next.&lt;br /&gt;
&lt;br /&gt;
Loading it up in the browser, I see that I am in OK shape so far:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-1TnMkp09dUs/TydVQZJfAYI/AAAAAAAADCc/TGEvWThxXlM/s1600/01-tracer_bullets.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="387" width="362" src="http://2.bp.blogspot.com/-1TnMkp09dUs/TydVQZJfAYI/AAAAAAAADCc/TGEvWThxXlM/s400/01-tracer_bullets.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
I add another getter for the collection. I am not going to attempt a full blown collection class tonight, but will simply stick with an array:&lt;pre class="prettyprint"&gt;class ComicsCollectionView {
  var get el;
&lt;b&gt;  var get collection;&lt;/b&gt;

  ComicsCollectionView(target_el) {
    el = document.query(target_el);
    collection = [];
  }

  render() { /* ... */ }
}&lt;/pre&gt;I am not quite sure how to load the collection. In backbone, a collection object would fire an event for which the view could listen. I am not, I will not create a full blown MVC framework. So what to do?  I opt for a private method to trigger the collection load in addition to applying the template:&lt;pre class="prettyprint"&gt;&lt;code&gt;  render() {
    _ensureCollectionLoaded();
    el.innerHTML = template(collection);
  }&lt;/code&gt;&lt;/pre&gt;The &lt;code&gt;template()&lt;/code&gt; method is taken directly from the old procedural code:&lt;pre class="prettyprint"&gt;&lt;code&gt;  template(list) {
    // This is silly, but [].forEach is broke
    if (list.length == 0) return '';

    var html = '';
    list.forEach((comic) {
      html += _singleComicBookTemplate(comic);
    });
    return html;
  }

  _singleComicBookTemplate(comic) {
    return """
      &amp;lt;li id="${comic['id']}"&gt;
        ${comic['title']}
        (${comic['author']})
        &amp;lt;a href="#" class="delete"&gt;[delete]&amp;lt;/a&gt;
      &amp;lt;/li&gt;
    """;
  }&lt;/code&gt;&lt;/pre&gt;As for the &lt;code&gt;_ensureCollectionLoaded()&lt;/code&gt; method, I again adopt the procedural code, but add a guard clause to prevent calling the method if it has already been loaded:&lt;pre class="prettyprint"&gt;&lt;code&gt;
  var _load_requested = false;

  _ensureCollectionLoaded() {
&lt;b&gt;    if (_load_requested) return;
    _load_requested = true;&lt;/b&gt;

    var req = new XMLHttpRequest();

    req.on.load.add(_handleOnLoad);
    req.open('get', '/comics', true);
    req.send();
  }&lt;/code&gt;&lt;/pre&gt;And lastly, I define the &lt;code&gt;_handleOnLoad()&lt;/code&gt; callback method.  In here, I finally assign the collection to a non-empty array:&lt;pre class="prettyprint"&gt;&lt;code&gt;  _handleOnLoad(event) {
    var request = event.target;

    // TODO trigger an event for which the view can listen and render
    collection = JSON.parse(request.responseText);

    render();
  }&lt;/code&gt;&lt;/pre&gt;Interestingly, the request is the event target.  Previously, I had been able to re-use the original request object as it was still in-scope. Now I have to extract it from the load event.&lt;br /&gt;
&lt;br /&gt;
Once I have the collection, I re-invoke render. This will by-pass &lt;code&gt;_ensureCollectionLoaded()&lt;/code&gt; since it has already been loaded.  But the now populated collection will result in the view actually displaying something.  And amazingly, it really does display:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-2DUHvljpENE/Tydsxp2T8HI/AAAAAAAADCo/hIvtnz7Jl5w/s1600/02-works.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="194" width="320" src="http://3.bp.blogspot.com/-2DUHvljpENE/Tydsxp2T8HI/AAAAAAAADCo/hIvtnz7Jl5w/s400/02-works.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
I have definitely improved my situation. All of the view code for my comic book collection is now in its own class. But wow, jamming all of that collection code in the view is messy. I may want to extract that out into a proper collection class.  Tomorrow.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #281&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-7720373851825088543?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7QLEA-4kKiuQxue4ym0aMvV5dN4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7QLEA-4kKiuQxue4ym0aMvV5dN4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7QLEA-4kKiuQxue4ym0aMvV5dN4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7QLEA-4kKiuQxue4ym0aMvV5dN4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/F9tt8xrA8P4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/7720373851825088543/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/psuedo-view-classes-in-dart.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7720373851825088543?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7720373851825088543?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/F9tt8xrA8P4/psuedo-view-classes-in-dart.html" title="Psuedo View Classes in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-1TnMkp09dUs/TydVQZJfAYI/AAAAAAAADCc/TGEvWThxXlM/s72-c/01-tracer_bullets.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/psuedo-view-classes-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUNRX4yfyp7ImA9WhRUGUU.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-6263424381303302063</id><published>2012-01-29T23:58:00.000-05:00</published><updated>2012-01-30T23:31:34.097-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T23:31:34.097-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Removing DOM Elements with Dart (A Tale of Null)</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/dart-html-templates-and.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/psuedo-view-classes-in-dart.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
For the next couple of days, I hope to keep it simple as I push toward a usable alpha release for &lt;a href="http://dart4hipsters.com/"&gt;Dart for Hipsters&lt;/a&gt;.  While mucking about with my &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; sample application, I notice that cancelling the create form was not removing the form element from the page. &lt;br /&gt;
&lt;br /&gt;
To remove the element, I had been:&lt;pre class="prettyprint"&gt;if (form_div) form_div.remove();&lt;/pre&gt;That is not how the &lt;code&gt;removeChild()&lt;/code&gt; &lt;a href="https://developer.mozilla.org/En/DOM/Node.removeChild"&gt;works in Javascript&lt;/a&gt; (operates on a parent node, removing the specified child).  I had tried working off of the API reference for &lt;a href="http://api.dartlang.org/html/Node.html#remove"&gt;Dart's remove()&lt;/a&gt;, which does not require an argument.&lt;br /&gt;
&lt;br /&gt;
It may not require an argument, but it does state that it renames &lt;code&gt;removeChild()&lt;/code&gt;, which would seem to indicate that it does operate on the parent. So I give it a try:&lt;pre class="prettyprint"&gt;if (form_div) form_div.parent.remove(form_div);&lt;/pre&gt;But that fails to work as well.&lt;br /&gt;
&lt;br /&gt;
OK, this is getting a bit annoying. When annoying, break it down to simplest case, I add a &lt;code&gt;test_remove()&lt;/code&gt; method:&lt;pre class="prettyprint"&gt;main() {
  test_remove();
  // ...
}

test_remove() {
  var test_div = new Element.html('&amp;lt;div id="test"/&gt;');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
  test_div.parent.remove(test_div);
}&lt;/pre&gt;For that, I get a not-too-helpful backtrace:&lt;pre class="prettyprint"&gt;Exception: NoSuchMethodException - receiver: 'Instance of 'BodyElementWrappingImplementation'' function name: 'remove' arguments: [Instance of 'DivElementWrappingImplementation']]
Stack Trace:  0. Function: 'Object.noSuchMethod' url: 'bootstrap' line:356 col:3
 1. Function: '::test_remove' url: 'http://localhost:3000/scripts/comics.dart' line:17 col:25
 2. Function: '::main' url: 'http://localhost:3000/scripts/comics.dart' line:5 col:14&lt;/pre&gt;So there is no &lt;code&gt;remove()&lt;/code&gt; method on the test_div Element/Node?  Surely there is because it is in the documentation. Ah, but it's in there with zero arity.  So maybe:&lt;pre class="prettyprint"&gt;test_remove() {
  var test_div = new Element.html('&amp;lt;div id="test"/&gt;');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
&lt;b&gt;  test_div.remove();&lt;/b&gt;
}&lt;/pre&gt;And, indeed that does work. But wait, why did that fail to remove an element in my original version?&lt;pre class="prettyprint"&gt;if (form_div) form_div.remove();&lt;/pre&gt;Ah, dang it. I have a conditional in there.  Sure enough, if I switch my test case to include that conditional:&lt;pre class="prettyprint"&gt;test_remove() {
  var test_div = new Element.html('&amp;lt;div id="test"/&gt;');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
&lt;b&gt;  if (test_div) test_div.remove();&lt;/b&gt;
}&lt;/pre&gt;Then the test DIV is not removed:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-yK-LjHrK3q8/TyYhyNel7tI/AAAAAAAADCQ/k9u7P5y-zKU/s1600/01-test_div_remains.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="75" width="278" src="http://2.bp.blogspot.com/-yK-LjHrK3q8/TyYhyNel7tI/AAAAAAAADCQ/k9u7P5y-zKU/s400/01-test_div_remains.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
It turns out that Dart very much wants a boolean in its conditionals. Lacking a conditional, it would appear to assume &lt;code&gt;false&lt;/code&gt;.  I cannot say that I am a fan of this, especially since the only resolution seems to be comparing to &lt;code&gt;null&lt;/code&gt;:&lt;pre class="prettyprint"&gt;test_remove() {
  var test_div = new Element.html('&amp;lt;div id="test"/&gt;');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
&lt;b&gt;  if (test_div != null) test_div.remove();&lt;/b&gt;
}&lt;/pre&gt;Ew. Not even the old &lt;code&gt;!!test_div&lt;/code&gt; trick works. I seem to be stuck with this less than desirable &lt;code&gt;null&lt;/code&gt; comparison.&lt;br /&gt;
&lt;br /&gt;
I may not like this conditional structure (hopefully that can change), but I do much prefer the simple &lt;code&gt;remove()&lt;/code&gt; in Dart to the traditional &lt;code&gt;child.parent.removeChild(child)&lt;/code&gt; dance.  All-in-all, I am willing to call this a net win for Dart. But it's a narrow win.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #280&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-6263424381303302063?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9HtGB2av791nim6d8G8t53s9Pp8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9HtGB2av791nim6d8G8t53s9Pp8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9HtGB2av791nim6d8G8t53s9Pp8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9HtGB2av791nim6d8G8t53s9Pp8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/QwGaCXJ6B1Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/6263424381303302063/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/removing-dom-element-with-dart-tale-of.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6263424381303302063?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6263424381303302063?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/QwGaCXJ6B1Q/removing-dom-element-with-dart-tale-of.html" title="Removing DOM Elements with Dart (A Tale of Null)" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-yK-LjHrK3q8/TyYhyNel7tI/AAAAAAAADCQ/k9u7P5y-zKU/s72-c/01-test_div_remains.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/removing-dom-element-with-dart-tale-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04ARH4-fip7ImA9WhRUGEQ.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-3508804247810680272</id><published>2012-01-28T23:59:00.000-05:00</published><updated>2012-01-30T00:05:45.056-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T00:05:45.056-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart HTML Templates and insertAdjacentElement</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/regular-expressions-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/removing-dom-element-with-dart-tale-of.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Picking back up with my web app now that my laptop is back (yay!), tonight I would like to get back to my &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; web application. I hope to figure out how to handle checkbox elements in my form, but first, I need to get it displaying (again).  &lt;br /&gt;
&lt;br /&gt;
The form is now in a template method:&lt;pre class="prettyprint"&gt;form_template([graphic_novel]) {
  return """
&amp;lt;form action="comics" id="new-comic-form"&gt;
&amp;lt;p&gt;
&amp;lt;label&gt;Title&amp;lt;br/&gt;
&amp;lt;input type="text" name="title" id="comic-title"/&gt;
&amp;lt;/label&gt;&amp;lt;/p&gt;

&amp;lt;p&gt;
&amp;lt;label&gt;Author&amp;lt;br/&gt;
&amp;lt;input type="text" name="author" id="comic-author"/&gt;
&amp;lt;/label&gt;&amp;lt;/p&gt;

&amp;lt;p&gt;Format
&amp;lt;p&gt;
&amp;lt;label&gt;
&amp;lt;input type="checkbox" name="format" value="tablet" id="comic-table"/&gt;
Tablet&amp;lt;/label&gt;&amp;lt;/p&gt;
&amp;lt;p&gt;
&amp;lt;label&gt;
&amp;lt;input type="checkbox" name="format" value="dead-tree" id="comic-dead-tree"/&gt;
Dead Tree&amp;lt;/label&gt;&amp;lt;/p&gt;
&amp;lt;/p&gt;

&amp;lt;p&gt;
&amp;lt;input type="submit" value="Bazinga!"/&gt;&amp;lt;/p&gt;

&amp;lt;/form&gt;
""";
}
&lt;/pre&gt;To insert that into that DOM, I need the Dart equivalent of jQuery's &lt;code&gt;prepend()&lt;/code&gt;, &lt;code&gt;append()&lt;/code&gt;, &lt;code&gt;before()&lt;/code&gt;, or &lt;code&gt;after()&lt;/code&gt;. Looking through the &lt;a href="http://api.dartlang.org/html/Element.html"&gt;API reference for Element&lt;/a&gt;, however, I do not see anything of the sort.  I do come across an odd little beastie named &lt;code&gt;insertAdjacentElement&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
I had never heard of that one, but apparently &lt;a href="http://msdn.microsoft.com/en-us/library/ie/ms536451(v=vs.85).aspx"&gt;insertAdjacentElement is an Internet Explorer thing&lt;/a&gt;.  Instead of invoking &lt;code&gt;before()&lt;/code&gt;, &lt;code&gt;after&lt;/code&gt;, etc. on an element, I am supposed to invoke &lt;code&gt;insertAdjacentElement()&lt;/code&gt; with the first argument of "beforeBegin", "afterBegin", "beforeEnd", or "afterEnd". Ew.&lt;br /&gt;
&lt;br /&gt;
I do not see any obvious better way to accomplish this in the Dart HTML library, so I get started.  First, in the method responsible for enabling the form, I add a call to a separate method that ensure the DOM element is present:&lt;pre class="prettyprint"&gt;enable_add_form(event) {
  final form_div = _ensure_add_form('#add-comic-form');

  // effect and handlers here
}&lt;/pre&gt;Then, I create a new &lt;code&gt;&amp;lt;div&gt;&lt;/code&gt; tag with that selector and insert the result of the form template:&lt;pre class="prettyprint"&gt;_ensure_add_form(id_selector) {
  var form_div = document.query(id_selector);
  if (form_div) form_div.remove();

&lt;b&gt;  form_div = new Element.html("""
&amp;lt;div id="$id_selector"&gt;
${form_template()}
&amp;lt;/div&gt;
""");&lt;/b&gt;

  document.body.insertAdjacentElement('beforeEnd', form_div);

  return form_div;
}&lt;/pre&gt;I do rather like the string interpolation that is possible in Dart. It is wonderful for working with strings.&lt;br /&gt;
&lt;br /&gt;
I really do &lt;i&gt;not&lt;/i&gt; care for that &lt;code&gt;instertAdjacentElement()&lt;/code&gt; method. It is way too long which does not lend itself to clear intent.  It does work, but... no.&lt;br /&gt;
&lt;br /&gt;
So instead, I stick with the &lt;code&gt;add()&lt;/code&gt; method available to nodeList objects:&lt;pre class="prettyprint"&gt;_ensure_add_form(id_selector) {
  var form_div = document.query(id_selector);
  if (form_div) form_div.remove();

  form_div = new Element.html("""
&amp;lt;div id="$id_selector"&gt;
${form_template()}
&amp;lt;/div&gt;
""");

&lt;b&gt;  document.body.nodes.add(form_div);&lt;/b&gt;

  return form_div;
}&lt;/pre&gt;Hopefully the HTML API will continue to evolve.  That &lt;code&gt;insertAjacentElement()&lt;/code&gt; is just crazy noisy. Fortunately, the &lt;code&gt;add()&lt;/code&gt; method covers the primary use-case of the various jQuery DOM manipulation methods. &lt;br /&gt;
&lt;br /&gt;
Regardless, the ability to perform string interpolation and the support for multi-line strings in Dart is a big win.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #279&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-3508804247810680272?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NR-BGJXg223wEUlKmgdkJlxuLfs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NR-BGJXg223wEUlKmgdkJlxuLfs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NR-BGJXg223wEUlKmgdkJlxuLfs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NR-BGJXg223wEUlKmgdkJlxuLfs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/uF2N8FY2wRo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/3508804247810680272/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/dart-html-templates-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/3508804247810680272?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/3508804247810680272?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/uF2N8FY2wRo/dart-html-templates-and.html" title="Dart HTML Templates and insertAdjacentElement" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/dart-html-templates-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcDQnk7eCp7ImA9WhRUGEw.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-1878563755642444711</id><published>2012-01-27T23:59:00.001-05:00</published><updated>2012-01-29T00:14:33.700-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-29T00:14:33.700-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Regular Expressions in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/dart-setters-and-getters.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/dart-html-templates-and.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Up tonight, I am going to explore regular expressions in &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt;. As an old time Perl hacker, I love regular expressions. Even thought it has been years since I last coded Perl, I still think of its regular expressions as the best implementation that I have ever used. I do not care for the Ruby implementation--I never got the hang of the API and still have to refer to the documentation when using them. Javascript is better, but I forget whether &lt;code&gt;matches()&lt;/code&gt; or &lt;code&gt;test()&lt;/code&gt; is a string method or a regular expression method.&lt;br /&gt;
&lt;br /&gt;
Unfortunately for me, the Dart implementation looks to be closer to Ruby's than Javascript's. But I will give it the benefit of the doubt.&lt;br /&gt;
&lt;br /&gt;
Last night, I was working with simple greetings (e.g. "Howdy, Bob!"). In the end, I stuck with string splitting in order to identify the two parts:&lt;pre class="prettyprint"&gt;&lt;code&gt;  set greeting(greeting) {
    var parts = greeting.split(',');

    if (parts.length == 2) {
      _greeting_opening = parts[0];
      name = parts[1].replaceAll(' ', '').replaceAll('!', '');
    }
    else {
      _full_greeting = greeting;
    }
  }&lt;/code&gt;&lt;/pre&gt;That is a little noisy (because it does not use regular expressions!), but fairly straight forward. I take the greeting (e.g. "Howdy, Bob!") and split on commas.  In the default case, I am left with two parts: "Howdy" and " Bob!". This falls into the first conditional in which I set the &lt;code&gt;_greeting_opening&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt; to the two parts.  The second part, in particular is painful since I have to strip spaces and punctuation.&lt;br /&gt;
&lt;br /&gt;
As noisy as this solution is, it does not even cover even simple deviations from the default case. When I attempted to set a greeting of "Yo, Yo, Yo, Alice!", my scheme was thwarted.&lt;br /&gt;
&lt;br /&gt;
The regular expression that ought to cover both cases is: &lt;code&gt;/^(.+)\s*,\s*([\w\s]+)\W?$/&lt;/code&gt;. The two parentheses indicate the portions of the string that I want to extract.  The greeting opening is all characters starting at the beginning of the line (&lt;code&gt;^&lt;/code&gt;) all the way up to the last comma, ignoring any space around the comma (&lt;code&gt;\s*,\s*&lt;/code&gt;).  The period in &lt;code&gt;(.+)&lt;/code&gt; matches any character and the plus indicates one or more of them.&lt;br /&gt;
&lt;br /&gt;
The second part of the string in which I am interested starts after the comma and any spaces (&lt;code&gt;\s*,\s*&lt;/code&gt;).  Here I try to match one or more characters or spaces: &lt;code&gt;([\w\s]+)&lt;/code&gt;. I match any number of those characters until the end of the string (&lt;code&gt;$&lt;/code&gt;) with the exception of a possible non-alphanumeric at the end of the line (&lt;code&gt;\W?&lt;/code&gt;).&lt;br /&gt;
&lt;br /&gt;
So let's see how this works in Dart.  Regular expressions in Dart are built with the &lt;code&gt;RegExp&lt;/code&gt; class. I try this against my default case:&lt;pre class="prettyprint"&gt;main() {
  var matcher = new RegExp('^(.+)\s*,\s*([\w\s]+)\W?$');

  matcher.allMatches("Howdy, Bob!").forEach((m) {
    print(m[0]);
  });
}&lt;/pre&gt;I am not quite sure about the &lt;code&gt;allMatches()&lt;/code&gt; usage--I am just trying that as my first attempt. It hardly matters because I am greeted by:&lt;pre class="prettyprint"&gt;$ dart regexp.dart
'/home/cstrom/repos/dart-book/samples/regexp.dart': Error: line 2 pos 54: illegal character after $ in string interpolation
  var matcher = new RegExp('^(.+)\s*,\s*([\w\s]+)\W?$');
                                                     ^&lt;/pre&gt;Well that is unfortunate. The dollar sign character in Dart strings is special--it signifies a string interpolation ("$name" might produce "Bob"). But here I am not attempting to interpolate a variable--I just want to match the end of the line. Ugh.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://api.dartlang.org/dart_core/RegExp.html"&gt;API reference for RegExp&lt;/a&gt; puts an at sign before strings in RegExp's.  Perhaps that prevents interpolation? There is one way to find out:&lt;pre class="prettyprint"&gt;main() {
  var matcher = new RegExp(&lt;b&gt;@&lt;/b&gt;'^(.+)\s*,\s*([\w\s]+)\W?$');

  matcher.allMatches("Howdy, Bob!").forEach((m) {
    print(m[0]);
  });
}&lt;/pre&gt;That does appear to prevent interpolation because I now get output:&lt;pre class="prettyprint"&gt;$ dart regexp.dart
Howdy, Bob!&lt;/pre&gt;Aha! I get &lt;code&gt;allMatches()&lt;/code&gt; now. That is used when there is an expectation that there are multiple matches within a string. Since I do not have to worry about that here, I should use &lt;code&gt;firstMatch&lt;/code&gt;. I also see that the zeroth match is the entire string that matched the whole regular expression. I want the first and second sub-expressions. Something like:&lt;pre class="prettyprint"&gt;main() {
  var matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  matcher.firstMatch("Howdy, Bob!").tap((m) {
    print(m[1]);
    print(m[2]);
  });
}&lt;/pre&gt;This results in:&lt;pre class="prettyprint"&gt;$ dart regexp.dart
Unhandled exception:
NoSuchMethodException - receiver: 'Instance of 'JSRegExpMatch'' function name: 'tap' arguments: [Closure]]
 0. Function: 'Object.noSuchMethod' url: 'bootstrap' line:360 col:3
 1. Function: '::main' url: '/home/cstrom/repos/dart-book/samples/regexp.dart' line:4 col:40&lt;/pre&gt;Aw, man! No &lt;code&gt;tap()&lt;/code&gt; in Dart? Say it ain't so!&lt;br /&gt;
&lt;br /&gt;
Ah well, I can manage with:&lt;pre class="prettyprint"&gt;main() {
  final matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  var m = matcher.firstMatch("Howdy, Bob!");
  print(m[1]);
  print(m[2]);
}&lt;/pre&gt;This results in:&lt;pre class="prettyprint"&gt;$ dart regexp.dart
Howdy
Bob&lt;/pre&gt;Trying this out against the very challenging "Yo, yo, yo, Alice!":&lt;pre class="prettyprint"&gt;main() {
  final matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  var m = matcher.firstMatch("Howdy, Bob!");
  print(m[1]);
  print(m[2]);

  m = matcher.firstMatch("Yo, yo, yo, Alice!");
  print(m[1]);
  print(m[2]);
}&lt;/pre&gt;I find:&lt;pre class="prettyprint"&gt;$ dart regexp.dart                                  ~/repos/dart-book/samples
Howdy
Bob
Yo, Yo, Yo
Alice&lt;/pre&gt;Hunh. I think I might like that. That makes sense and I can definitely see myself remembering how to use those.&lt;br /&gt;
&lt;br /&gt;
What about the match vs. test from Javascript? It seems that Dart improves on that. Instead of &lt;code&gt;test&lt;/code&gt;, Dart uses &lt;code&gt;contains&lt;/code&gt;. It still uses the &lt;code&gt;matches()&lt;/code&gt; method on regular expressions.  I try this out with a generalized version of my regular expression exploration code:&lt;pre class="prettyprint"&gt;main() {
  final matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  try_regexp(matcher, "Howdy, Bob!");

  try_regexp(matcher, "Yo, yo, yo, Alice!");

  try_regexp(matcher, "Hey. You.");
}

try_regexp(regexp, str) {
  print('----');
  print(str);

  print("contains? ${str.contains(regexp)}");
  print("hasMatch? ${regexp.hasMatch(str)}");

  var m = regexp.firstMatch(str);
  print(m[1]);
  print(m[2]);
  print('');
}&lt;/pre&gt;I have also added a new string, "Hey. You.", which should not match. And indeed it does not:&lt;pre class="prettyprint"&gt;dart regexp.dart                                  ~/repos/dart-book/samples
----
Howdy, Bob!
contains? true
hasMatch? true
Howdy
Bob

----
Yo, yo, yo, Alice!
contains? true
hasMatch? true
Yo, yo, yo
Alice

----
Hey. You.
contains? false
hasMatch? false
Unhandled exception:
NullPointerException
 0. Function: 'Object.noSuchMethod' url: 'bootstrap' line:360 col:3
 1. Function: '::try_regexp' url: '/home/cstrom/repos/dart-book/samples/regexp.dart' line:19 col:10
 2. Function: '::main' url: '/home/cstrom/repos/dart-book/samples/regexp.dart' line:8 col:13&lt;/pre&gt;(&lt;a href="http://try.dartlang.org/s/iRko"&gt;try.dartlang.org&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the end, I am forced to admit that I rather like Dart's regular expressions. They will even improve my Javascript coding (I will always remember that Dart has a saner &lt;code&gt;contains()&lt;/code&gt; method, which is analogous to the silly &lt;code&gt;test()&lt;/code&gt;). It may not be Perl, and it would be nice if there were regular expression literals, but this is pretty darn nice.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #278&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-1878563755642444711?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Q64OwmHNdlVTASO2JmcRQZmsUZ8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Q64OwmHNdlVTASO2JmcRQZmsUZ8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Q64OwmHNdlVTASO2JmcRQZmsUZ8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Q64OwmHNdlVTASO2JmcRQZmsUZ8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/pUJYrUzdivs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/1878563755642444711/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/regular-expressions-in-dart.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/1878563755642444711?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/1878563755642444711?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/pUJYrUzdivs/regular-expressions-in-dart.html" title="Regular Expressions in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/regular-expressions-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMGRHw5eyp7ImA9WhRUGU0.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-810656241345216814</id><published>2012-01-26T23:59:00.001-05:00</published><updated>2012-01-30T00:13:45.223-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T00:13:45.223-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart Setters and Getters</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/singletons-via-factories-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;span style="color: #ccc"&gt;next&amp;rsaquo;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I remain stuck without a proper web development environment (c'mon Apple geniuses!), so tonight I continue to explore some &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; internals.  I played about with factory constructors last night, and have to admit they are pretty darn cool.  Tonight, I take a look at setters and getters.&lt;br /&gt;
&lt;br /&gt;
On the face of it, setters and getters in objects is a pretty simple thing. Instead of needing full blown method syntax to retrieve a value:&lt;pre class="prettyprint"&gt;var bob = new Person("Bob");
bob.greeting(); // =&gt; "Howdy, Bob!"&lt;/pre&gt;In Dart, we should be able to do something like:&lt;pre class="prettyprint"&gt;var bob = Person.new("Bob");
bob.greeting; // =&gt; "Howdy, Bob!"&lt;/pre&gt;It is a simple enough thing, but over the long haul, removing parenthesis can only help with readability / maintainability.&lt;br /&gt;
&lt;br /&gt;
So let's see if I know how to do this:&lt;pre class="prettyprint"&gt;class Person {
  var name;
  var _greeting_opening = "Howdy";

  Person(this.name);

  get greeting() =&gt; "${_greeting_opening}, ${name}!";
}&lt;/pre&gt;I declare two instance variables--one public, one private--to hold the name of the person and the word used to open the greeting. My constructor is simple enough (assign the supplied string as the name of the person), so the constructor declaration can make use of the nifty Dart shortcut that assign the argument to an instance variable.&lt;br /&gt;
&lt;br /&gt;
Lastly, I declare a greeting method that puts the two variables together in a string.  Here again, I have a simple method, so I can use the compact &lt;code&gt;() =&gt;&lt;/code&gt; function syntax.&lt;br /&gt;
&lt;br /&gt;
To use this class, I print out the greeting to two different people:&lt;pre class="prettyprint"&gt;main() {
  var bob = new Person("Bob")
    , alice = new Person("Alice");

  print(bob.greeting);
  print(alice.greeting);
}&lt;/pre&gt;Running this results in:&lt;pre class="prettyprint"&gt;$ dart setters_getters.dart
Howdy, Bob!
Howdy, Alice!&lt;/pre&gt;What I really like about this is that I do not have to follow a convention for these beasties (&lt;i&gt;e.g.&lt;/i&gt; &lt;code&gt;getGreeting&lt;/code&gt;, &lt;code&gt;setGreeting&lt;/code&gt;). I never stick with whatever convention I start and end up with way too much confusion over a simple thing.&lt;br /&gt;
&lt;br /&gt;
Setting things is similarly easy in Dart. In the class defintion, I need to use &lt;code&gt;set&lt;/code&gt; instead of &lt;code&gt;get&lt;/code&gt;. The usage of setters looks like any other property being assigned:&lt;pre class="prettyprint"&gt;bob.greeting = "Yo, Bob!";&lt;/pre&gt;To make this work, the class would then need the &lt;code&gt;set&lt;/code&gt; method:&lt;pre class="prettyprint"&gt;class Person {
  var name;
  var _greeting_opening = "Howdy"
&lt;b&gt;    , _full_greeting;&lt;/b&gt;

  Person(this.name);

  get greeting() {
&lt;b&gt;    (_full_greeting != null) ?
      _full_greeting :&lt;/b&gt;
      "${_greeting_opening}, ${name}!";
  }
&lt;b&gt;  set greeting(greeting) {
    _full_greeting = greeting;
  }&lt;/b&gt;
}&lt;/pre&gt;I have introduced a new, private instance variable &lt;code&gt;_full_greeting&lt;/code&gt;. If set, the &lt;code&gt;greeting&lt;/code&gt; getting will use this as the return value, otherwise it will stick with the regular "Howdy &amp;lt;&amp;lt;your name here&gt;&gt;!" version.&lt;br /&gt;
&lt;br /&gt;
When I run this code:&lt;pre class="prettyprint"&gt;main() {
  var bob = new Person("Bob")
    , alice = new Person("Alice");

  print(bob.greeting);
  print(alice.greeting);

  bob.greeting = "Yo, Bob!";
  print(bob.greeting);
}&lt;/pre&gt;I am greeted with:&lt;pre class="prettyprint"&gt;null
null
null&lt;/pre&gt;Ah. I missed a &lt;code&gt;return&lt;/code&gt; statement:&lt;pre class="prettyprint"&gt;class Person {
  var name;
  var _greeting_opening = "Howdy"
    , _full_greeting;

  Person(this.name);

  get greeting() {
    &lt;b&gt;return&lt;/b&gt; (_full_greeting != null) ?
      _full_greeting :
      "${_greeting_opening}, ${name}!";
  }
  set greeting(greeting) {
    _full_greeting = greeting;
  }
}&lt;/pre&gt;Now, I get:&lt;pre class="prettyprint"&gt;Howdy, Bob!
Howdy, Alice!
Yo, Bob!&lt;/pre&gt;Of course, the real fun starts when you begin making calculations based on setters:&lt;pre class="prettyprint"&gt;&lt;code&gt;  set greeting(greeting) {
    var parts = greeting.split(',');

    if (parts.length == 2) {
      _greeting_opening = parts[0];
      name = parts[1].replaceAll(' ', '').replaceAll('!', '');
    }
    else {
      _full_greeting = greeting;
    }
  }&lt;/code&gt;&lt;/pre&gt;Running the following:&lt;pre class="prettyprint"&gt;main() {
  var bob = new Person("Bob")
    , alice = new Person("Alice");

  print(bob.greeting);
  print(alice.greeting);

  bob.greeting = "Yo, Fred!";
  print(bob.greeting);
  print(bob.name);

  alice.greeting = "Yo, yo, yo, Alice!";
  print(alice.greeting);
  print(alice.name);
}&lt;/pre&gt;Results in:&lt;pre class="prettyprint"&gt;Howdy, Bob!
Howdy, Alice!
Yo, Fred!
Fred
Yo, yo, yo, Alice!
Alice
&lt;/pre&gt;(&lt;a href="http://try.dartlang.org/s/Kw0o"&gt;try.dartlang.org&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is some definite power there.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #276&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-810656241345216814?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PllSu6isAZd48LGerLxiR_2gkEk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PllSu6isAZd48LGerLxiR_2gkEk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PllSu6isAZd48LGerLxiR_2gkEk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PllSu6isAZd48LGerLxiR_2gkEk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/DnHftqyUcjw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/810656241345216814/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/dart-setters-and-getters.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/810656241345216814?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/810656241345216814?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/DnHftqyUcjw/dart-setters-and-getters.html" title="Dart Setters and Getters" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/dart-setters-and-getters.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMGRHw6fCp7ImA9WhRUGU0.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-8017380513010830449</id><published>2012-01-25T23:59:00.001-05:00</published><updated>2012-01-30T00:13:45.214-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T00:13:45.214-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Singletons via Factories in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/how-not-to-modify-dart-clases.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/dart-setters-and-getters.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Coding for the web on the ipad has not been working well for me over these past few nights. So tonight, I switch gears and explore me some &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; internals.  Specifically, I am going to play with factory constructors.&lt;br /&gt;
&lt;br /&gt;
By declaring an otherwise normal constructor as a factory, we are telling Dart that it need not create instances of the Class under construction.  Rather, we will handle it ourselves.&lt;br /&gt;
&lt;br /&gt;
My limited brain has fixated on the most obvious use-case in the world: a singleton. In a sign of just how sleep deprived I am, I will create a class named &lt;code&gt;Foo&lt;/code&gt; with a property of &lt;code&gt;bar&lt;/code&gt;.  If I create two instances of the singleton Foo, then both should have the same value for &lt;code&gt;bar&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
In other words, both of the following statements should have the same value for &lt;code&gt;bar&lt;/code&gt;:&lt;pre class="prettyprint"&gt;main() {
  final foo1 = new Foo("bar1")
      , foo2 = new Foo("bar2");

  print("foo1 is: ${foo1.bar}");
  print("foo2 is: ${foo2.bar}");
}&lt;/pre&gt;If I implement the Foo class correctly, then the output should be:&lt;pre class="prettyprint"&gt;foo1 is: bar2
foo2 is: bar2&lt;/pre&gt;So let's take a look at the factory constructor for this beast:&lt;pre class="prettyprint"&gt;class Foo {
  var bar;
  static Foo instance;

  factory Foo(name) {
    if (instance == null) {
      instance = new Foo._internal(name);
    }
    return instance;
  }

  Foo._internal(this.bar);
}&lt;/pre&gt;Starting from the bottom, the &lt;code&gt;Foo._internal(this.bar)&lt;/code&gt; line is a constructor.  The underscore in the name is a convention for a private constructor. By using &lt;code&gt;this.bar&lt;/code&gt; as the argument in the constructor, I am saying that any arguments supplied should be used to set the &lt;code&gt;this.bar&lt;/code&gt; property.&lt;br /&gt;
&lt;br /&gt;
That is, the following:&lt;pre class="prettyprint"&gt;var internal = new Foo._internal("internal");
print("internal is: ${internal.bar}");&lt;/pre&gt;Should produce:&lt;pre class="prettyprint"&gt;internal is: internal&lt;/pre&gt;Moving up in the class, the factory is defined as:&lt;pre class="prettyprint"&gt;&lt;code&gt;  factory Foo(name) {
    if (instance == null) {
      instance = new Foo._internal(name);
    }
    return instance;
  }&lt;/code&gt;&lt;/pre&gt;Just as with my internal construtor, I accept a single argument which will be used to set the &lt;code&gt;bar&lt;/code&gt; property.  If the static/class property &lt;code&gt;instance&lt;/code&gt; is null, then I create it fresh from the internal constructor. If instance has already been set (e.g. a previous object has already defined this static/class variable, then I do nothing.  In either case, I return the instance. It is this return value, not internal Dart magic which creates the object instance for factories.&lt;br /&gt;
&lt;br /&gt;
When I run the following:&lt;pre class="prettyprint"&gt;main() {
  final bar1 = new Foo("bar1")
      , bar2 = new Foo("bar2");

  print("bar1 is: ${bar1.bar}");
  print("bar2 is: ${bar2.bar}");
}&lt;/pre&gt;I get the following output:&lt;pre class="prettyprint"&gt;bar1 is: bar1
bar2 is: bar1
&lt;/pre&gt;So indeed, I do have my Singleton factory working as desired. Nice.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #276&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-8017380513010830449?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6oWwDrZrhW0uOLAGDVCXDhXRjPU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6oWwDrZrhW0uOLAGDVCXDhXRjPU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6oWwDrZrhW0uOLAGDVCXDhXRjPU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6oWwDrZrhW0uOLAGDVCXDhXRjPU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/sDzwJFq4alI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/8017380513010830449/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/singletons-via-factories-in-dart.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/8017380513010830449?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/8017380513010830449?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/sDzwJFq4alI/singletons-via-factories-in-dart.html" title="Singletons via Factories in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/singletons-via-factories-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMGRHw7fip7ImA9WhRUGU0.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-5737869943396101205</id><published>2012-01-24T23:55:00.000-05:00</published><updated>2012-01-30T00:13:45.206-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-30T00:13:45.206-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>How Not to Modify Dart Classes</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/better-delegated-events.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/singletons-via-factories-in-dart.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Yesterday, I was able to make a a decent start at a delegating event listener. The format&lt;br /&gt;
the listener ended up looking like:&lt;pre class="prettyprint"&gt;&lt;code&gt;  attach_handler(list_el, 'click .delete', (event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });&lt;/code&gt;&lt;/pre&gt;As with jQuery delegated events, that is a fairly compact, literate&lt;br /&gt;
syntax. Under the list element (&lt;code&gt;list_el&lt;/code&gt;), I establish a listener for click&lt;br /&gt;
events on '.delete' elements. Since this is a delegated listener, this works for '.delete'&lt;br /&gt;
elements present now as well as any added later.  The actual callback fired when the 'click&lt;br /&gt;
.delete' event is seen is a call to my XHR delete that, upon success, removes the parent LI&lt;br /&gt;
element.&lt;br /&gt;
&lt;br /&gt;
That works, but it is a procedural approach. Ideally, I would like to add a delegated&lt;br /&gt;
listener something like:&lt;pre class="prettyprint"&gt;&lt;code&gt;  list_el.on['click .delete'].add((event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });&lt;/code&gt;&lt;/pre&gt;If this were Ruby, I could re-open the Events class and redefine the&lt;br /&gt;
&lt;code&gt;on&lt;/code&gt; getter:&lt;pre class="prettyprint"&gt;class Events {
  EventListenerList operator [](String type) {
    document.query
}&lt;/pre&gt;I cannot even compile that, however, without getting a redefinition error.&lt;br /&gt;
&lt;br /&gt;
Hrm.. perhaps if I try with the implementation?&lt;pre class="prettyprint"&gt;class EventsImplementation {
  EventListenerList operator [](String type) {
    document.query('#status').innerHTML = 'foo';
  }
}&lt;/pre&gt;Well, that compiles, but it has no effect. The default implementation of the &lt;code&gt;on[]&lt;/code&gt; operator still kicks in.&lt;br /&gt;
&lt;br /&gt;
Hrm... is it even possible to modify the EventsImplementation class (let alone override an existing method)?  To test this out, I define the attach_handler()&lt;/code&gt; directly on the EventsImplementation class:&lt;pre class="prettyprint"&gt;class EventsImplementation {
  attach_handler(event_handler, fn) {
    document.query('#status').innerHTML = 'foo';
  }
}&lt;/pre&gt;Then, I invoke this with:&lt;pre class="prettyprint"&gt;list_el.on.attach_handler('click .delete', (event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });&lt;/pre&gt;Unfortunately, that compiles, but crashes in the browser.&lt;br /&gt;
&lt;br /&gt;
I am stuck developing in Safari for iPad here, so I think it is best that I call it a night at this point. Tomorrow, I will switch to a desktop Dartium to attempt to see exactly where I am going wrong here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-5737869943396101205?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dv_yizUXf7HUZ95RuXA6bge-vYs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dv_yizUXf7HUZ95RuXA6bge-vYs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dv_yizUXf7HUZ95RuXA6bge-vYs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dv_yizUXf7HUZ95RuXA6bge-vYs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/9-lq2QGKAZM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/5737869943396101205/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/how-not-to-modify-dart-clases.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/5737869943396101205?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/5737869943396101205?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/9-lq2QGKAZM/how-not-to-modify-dart-clases.html" title="How Not to Modify Dart Classes" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/how-not-to-modify-dart-clases.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UER3czeSp7ImA9WhRUFkk.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-5988550786565166177</id><published>2012-01-23T23:56:00.001-05:00</published><updated>2012-01-27T00:13:26.981-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-27T00:13:26.981-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Better Delegated Events</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/delegated-events-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/how-not-to-modify-dart-clases.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
This will be an extremely brief post just to keep my chain alive. Unfortunately, the LCD on my primary machine died, so I've had to spend time getting up to speed with a new one...&lt;br /&gt;
&lt;br /&gt;
Last night, I was able to fake delegated events in &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; with event listeners along the lines of:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.on.click.add((event) {
    var found = false;
    parent.queryAll('.delete').forEach((el) {
      if (el == event.target) found = true;
    });
    if (!found) return;

    print(event.target.parent.id);

    delete(event.target.parent.id, callback:() {
      print("[delete] ${event.target.parent.id}");
      event.target.parent.remove();
    });

    event.preventDefault();
  });
}&lt;/pre&gt;In there, I have conflated delegating the event (the &lt;code&gt;queryAll&lt;/code&gt; selector) with firing the event handler (the call to the &lt;code&gt;delete()&lt;/code&gt; method. What I would like, is something like:&lt;pre class="prettyprint"&gt;attach_handler('click', '.delete', (event) {
  // handle event
})&lt;/pre&gt;That might be difficult to implement if I were stuck with the &lt;code&gt;parent.on.click&lt;/code&gt; mechanism for accessing a list of event listeners.  Fortunately, the on getter also supports a lookup format like &lt;code&gt;on['click']&lt;/code&gt;, which ought to allow me to pass in all of the information that I need.&lt;br /&gt;
&lt;br /&gt;
Starting with baby steps, I convert the &lt;code&gt;on&lt;/code&gt; getting:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.on['click'].add((event) {
    // ...
  });
}&lt;/pre&gt;That still works, so I get a bit more ambitious:&lt;pre class="prettyprint"&gt;attach_handler(parent,event_type, selector, callback) {
  parent.on[event_type].add((event) {
    var found = false;
    parent.queryAll(selector).forEach((el) {
      if (el == event.target) found = true;
    });
    if (!found) return;

    print(event.target.parent.id);
    callback(event);

    event.preventDefault();
  });
}&lt;/pre&gt;Which I can then use thusly:&lt;pre class="prettyprint"&gt;&lt;code&gt;  attach_handler(list_el, 'click',  '.delete', (event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });&lt;/code&gt;&lt;/pre&gt;And that still works. Nice.&lt;br /&gt;
&lt;br /&gt;
OK, I really should not do this, but, the &lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone.js&lt;/a&gt; convention with these delgated events is to describe the event type and the selector in the same string (e.g. &lt;code&gt;"click .delete"&lt;/code&gt;). Let's see if I can figure that out in time to post.&lt;br /&gt;
&lt;br /&gt;
Ultimately, I think I would prefer a regular expression, but this will do:&lt;pre class="prettyprint"&gt;attach_handler(parent, event_selector, callback) {
&lt;b&gt;  var index = event_selector.indexOf(' ')
    , event_type = event_selector.substring(0,index)
    , selector = event_selector.substring(index+1);&lt;/b&gt;

  parent.on[event_type].add((event) {
    var found = false;
    parent.queryAll(selector).forEach((el) {
      if (el == event.target) found = true;
    });
    if (!found) return;

    print(event.target.parent.id);
    callback(event);

    event.preventDefault();
  });
}&lt;/pre&gt;That'll do as a stopping point for tonight. I made a little progress on this, but it was painful with this new setup. Hopefully I can figure out how to make it easier tomorrow. Or my old machine gets fixed sooner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-5988550786565166177?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CCLcFrdtfk6WnljK53x-K04YCeQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CCLcFrdtfk6WnljK53x-K04YCeQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CCLcFrdtfk6WnljK53x-K04YCeQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CCLcFrdtfk6WnljK53x-K04YCeQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/KXYGPwP7ols" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/5988550786565166177/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/better-delegated-events.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/5988550786565166177?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/5988550786565166177?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/KXYGPwP7ols/better-delegated-events.html" title="Better Delegated Events" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/better-delegated-events.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UHQXs_fCp7ImA9WhRUFkk.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-2579268414513943462</id><published>2012-01-22T23:56:00.001-05:00</published><updated>2012-01-27T00:13:50.544-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-27T00:13:50.544-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Delegated Events in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/supporting-both-dart-and-javascript.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/better-delegated-events.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I do not believe that &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; has an equivalent to jQuery's &lt;a href="http://api.jquery.com/on/#direct-and-delegated-events"&gt;delegated events&lt;/a&gt;, but tonight I take a look. As the jQuery documentation states, delegated events are nice for two reasons: specifying handlers for elements not yet added to the page and significantly cutting down on the total number of handlers in some circumstances. It was while working with &lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone.js&lt;/a&gt; that I especially came to know and love delegated events, hence the desire for them in Dart.&lt;br /&gt;
&lt;br /&gt;
In my comic book application, I am inserting a list of comic books into a static page via XHR:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-mLHUNjiutR8/TxzdFAdqQRI/AAAAAAAADBk/pdmyiLt50LM/s1600/01-list_o_comics.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="202" width="265" src="http://1.bp.blogspot.com/-mLHUNjiutR8/TxzdFAdqQRI/AAAAAAAADBk/pdmyiLt50LM/s400/01-list_o_comics.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
After list is inserted, I attach delete handlers to each of those Delete links:&lt;pre class="prettyprint"&gt;load_comics() {
  var list_el = document.query('#comics-list')
    , req = new XMLHttpRequest();

  req.open('get', '/comics', true);

  req.on.load.add((res) {
    var list = JSON.parse(req.responseText);
    list_el.innerHTML = graphic_novels_template(list);
    &lt;b&gt;attach_delete_handlers(list_el);&lt;/b&gt;
  });

  req.send();
}&lt;/pre&gt;What I would like to do is move that &lt;code&gt;attach_delete_handers()&lt;/code&gt; function before the XHR request:&lt;pre class="prettyprint"&gt;load_comics() {
  var list_el = document.query('#comics-list')
    , req = new XMLHttpRequest();

  &lt;b&gt;attach_delete_handlers(list_el);&lt;/b&gt;

  req.open('get', '/comics', true);

  req.on.load.add((res) {
    var list = JSON.parse(req.responseText);
    list_el.innerHTML = graphic_novels_template(list);
  });

  req.send();
}&lt;/pre&gt;If the event handlers was in delegate mode, then this would still work. Unfortunately it does not. Clicking any of the links incurs the default behavior of the &lt;code&gt;&amp;lt;a&gt;&lt;/code&gt; tags—in this case requesting the current resource with a hash tag:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xaBcYaq2Zus/TxzeuSCh_sI/AAAAAAAADBw/EIYDBJM7k2s/s1600/02-stupid_hash.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="288" width="306" src="http://1.bp.blogspot.com/-xaBcYaq2Zus/TxzeuSCh_sI/AAAAAAAADBw/EIYDBJM7k2s/s400/02-stupid_hash.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The reason that I do not believe that Dart supports this is the manner in which event handlers are added. All elements have an &lt;code&gt;on&lt;/code&gt; getter, which returns an &lt;a href="http://api.dartlang.org/html/ElementEvents.html"&gt;ElementEvents&lt;/a&gt;.  Since &lt;code&gt;on&lt;/code&gt; does not support any arguments, there is no mechanism to record a selector that might put the listener into delegate mode.  The &lt;code&gt;ElementEvents&lt;/code&gt; object exposes a series of &lt;a href="http://api.dartlang.org/html/EventListenerList.html"&gt;EventListenerList&lt;/a&gt; getters (e.g. click, mouseOver, etc) to which event listeners can be added.  I see no room for delegation anywhere.&lt;br /&gt;
&lt;br /&gt;
This can be seen in my &lt;code&gt;attach_delete_handlers()&lt;/code&gt; function, which iterates through each &lt;i&gt;existing&lt;/i&gt; Delete link of the supplied UL list, attaching he same event listener to each:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    &lt;b&gt;el.on.click.add((event) {&lt;/b&gt;
      delete(event.target.parent.id, callback:() {
        print("[delete] ${event.target.parent.id}");
        event.target.parent.remove();
      });
      event.preventDefault();
    });
  });
}&lt;/pre&gt;If I call &lt;code&gt;attach_delete_handlers&lt;/code&gt; before the XHR request, then the &lt;code&gt;queryAll('.delete')&lt;/code&gt; call will return an empty list and thus no handlers are attached.&lt;br /&gt;
&lt;br /&gt;
Since that won't work (unless I am overlooking something), let's try adding a handler to the UL parent element. That handler should look through all of the &lt;code&gt;.delete&lt;/code&gt; links and handle the event if the event target is on of those:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.on.click.add((event) {
    if (parent.queryAll('.delete').indexOf(event.target) == -1) return;

    print(event.target.parent.id);
    event.preventDefault();
  });
}&lt;/pre&gt;Sadly, when I click the delete link, I get the following:&lt;pre class="prettyprint"&gt;Exception: Not impl yet. todo(jacobr)
Stack Trace:  0. Function: 'FrozenElementList.indexOf' url: 'dart:htmlimpl' line:22497 col:5
 1. Function: '::function' url: 'http://localhost:3000/scripts/comics.dart' line:59 col:43
 2. Function: 'EventListenerListImplementation.function' url: 'dart:htmlimpl' line:23183 col:35&lt;/pre&gt;Dang it. OK it is a new language. Things like that are bound to happen.  Perhaps &lt;code&gt;some()&lt;/code&gt; will work where &lt;code&gt;indexOf()&lt;/code&gt; did not:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.on.click.add((event) {
&lt;b&gt;    if (parent.queryAll('.delete').some((el) { el == event.target;})) return;&lt;/b&gt;

    print(event.target.parent.id);
    event.preventDefault();
  });
}&lt;/pre&gt;Now when I click a Delete link I get:&lt;pre class="prettyprint"&gt;Exception: Not impl yet. todo(jacobr)
Stack Trace:  0. Function: 'FrozenElementList.some' url: 'dart:htmlimpl' line:22434 col:5
 1. Function: '::function' url: 'http://localhost:3000/scripts/comics.dart' line:59 col:40
 2. Function: 'EventListenerListImplementation.function' url: 'dart:htmlimpl' line:23183 col:35&lt;/pre&gt;Shakes fist at jacobr!&lt;br /&gt;
&lt;br /&gt;
So &lt;code&gt;indexOf&lt;/code&gt; does not work, nor does &lt;code&gt;some&lt;/code&gt;. I know that &lt;code&gt;forEach()&lt;/code&gt; works for certain, so...&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.on.click.add((event) {
&lt;b&gt;    var found = false;
    parent.queryAll('.delete').forEach((el) {
      if (el == event.target) found = true;
    });
    if (!found) return;&lt;/b&gt;

    print(event.target.parent.id);
    event.preventDefault();
  });
}&lt;/pre&gt;Not the prettiest code, but I can live with it until jacobr implements cleaner iterator methods.&lt;br /&gt;
&lt;br /&gt;
With that working, I can add my XHR delete call to this psuedo-delegated event handler:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.on.click.add((event) {
    var found = false;
    parent.queryAll('.delete').forEach((el) {
      if (el == event.target) found = true;
    });
    if (!found) return;

    print(event.target.parent.id);

&lt;b&gt;    delete(event.target.parent.id, callback:() {
      print("[delete] ${event.target.parent.id}");
      event.target.parent.remove();
    });&lt;/b&gt;

    event.preventDefault();
  });
}&lt;/pre&gt;And, now I can delete comics again:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-l0Xt0z4xEQE/Txznn3iqQJI/AAAAAAAADB8/NGPic5y1q-4/s1600/03-deleted.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://4.bp.blogspot.com/-l0Xt0z4xEQE/Txznn3iqQJI/AAAAAAAADB8/NGPic5y1q-4/s400/03-deleted.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
That is not ideal, but at least it is possible.  jQuery still has Dart beat in this respect, but I can live with this for now...&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #273&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-2579268414513943462?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QzkOzt-Eu6L2OyK8SZVdeMJ2RBw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QzkOzt-Eu6L2OyK8SZVdeMJ2RBw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QzkOzt-Eu6L2OyK8SZVdeMJ2RBw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QzkOzt-Eu6L2OyK8SZVdeMJ2RBw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/Iy0J35s3Mrk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/2579268414513943462/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/delegated-events-in-dart.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/2579268414513943462?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/2579268414513943462?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/Iy0J35s3Mrk/delegated-events-in-dart.html" title="Delegated Events in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-mLHUNjiutR8/TxzdFAdqQRI/AAAAAAAADBk/pdmyiLt50LM/s72-c/01-list_o_comics.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/delegated-events-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4DRn48fSp7ImA9WhRUEkQ.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-6492449917537014490</id><published>2012-01-21T23:59:00.001-05:00</published><updated>2012-01-23T00:02:57.075-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-23T00:02:57.075-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Supporting Both Dart and Javascript</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/dart-animation.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/delegated-events-in-dart.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Tonight I would like to get my &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; code running side-by-side with the Javascript equivalent. That is, I would like to serve up Dart to Dart-enabled browsers, but the Javascript equivalent for other browsers. No doubt that, as the language and platform evolves, there will be easy ways to accomplish this. For tonight, I would like to know if it is possible.&lt;br /&gt;
&lt;br /&gt;
Currently, the Dart in my web application is loaded via a &lt;code&gt;&amp;lt;script&gt;&lt;/code&gt; tag:&lt;pre class="prettyprint"&gt;&amp;lt;!DOCTYPE html&gt;
&amp;lt;html&gt;
&amp;lt;head&gt;
  &amp;lt;title&gt;Dart Comics&amp;lt;/title&gt;
  &amp;lt;link rel="stylesheet" href="/stylesheets/style.css"&gt;

  &amp;lt;!-- Force Dartium to start the script engine --&gt;
  &amp;lt;script&gt;{}&amp;lt;/script&gt;
&lt;b&gt;  &amp;lt;script src="/scripts/comics.dart" type="application/dart"&gt;&amp;lt;/script&gt;&lt;/b&gt;
&amp;lt;/head&gt;

&amp;lt;body&gt;
&amp;lt;!-- ... --&gt;
&amp;lt;/body&gt;
&amp;lt;/html&gt;&lt;/pre&gt;When I compile this dart into Javascript with the &lt;a href="http://japhr.blogspot.com/2011/12/command-line-dart-and-frogc-wha.html"&gt;frogc&lt;/a&gt; (I still don't get the name), it produces a file named &lt;code&gt;comics.dart.js&lt;/code&gt;. I would almost like one of those old timey IE conditional comments to load in that Javascript file:&lt;pre class="prettyprint"&gt;&amp;lt;!--[if Dart]&gt;
  &amp;lt;script src="/scripts/comics.dart" type="application/dart"&gt;&amp;lt;/script&gt;
&amp;lt;![endif]--&gt;
&lt;b&gt;&amp;lt;!--[if !Dart]&gt;
  &amp;lt;script src="/scripts/comics.dart.js" type="text/javasript"&gt;&amp;lt;/script&gt;
&amp;lt;![endif]--&gt;&lt;/b&gt;&lt;/pre&gt;But I don't really want that. It sucks.  Besides, I am duplicating the basename of &lt;code&gt;/scripts/comics.dart&lt;/code&gt; in both &lt;code&gt;&amp;lt;script&gt;&lt;/code&gt; tags.&lt;br /&gt;
&lt;br /&gt;
What I would like is for the Dart code—and only the Dart code—to execute in Dart browsers. Getting the Dart code is easy enough, but how do I detect that dart is enabled so that I can prevent &lt;code&gt;&amp;lt;script src="/scripts/comics.dart"&gt;&lt;/code&gt; from being evaluated?&lt;br /&gt;
&lt;br /&gt;
In other browsers, I would like a simple, unobtrusive fallback to the Javascript.&lt;br /&gt;
&lt;br /&gt;
There are plans to use &lt;a href="http://api.dartlang.org/dart_core/Isolate.html"&gt;Isolates&lt;/a&gt; to allow Dart to communicate with Javascript code. But, since that is not available today, I need some other way for Dart to tell Javascript that it is present. The only way that I can think to communicate between the two is the DOM:&lt;pre class="prettyprint"&gt;&amp;lt;script type="application/dart"&gt;
  #import('dart:html');
  main() {
    var el = new Element.html('&amp;lt;div id="_is-dart-enabled"/&gt;');
    document.nodes.add(el);
  }
&amp;lt;/script&gt;&lt;/pre&gt;If Dart is enabled, that bit of code will insert a &lt;code&gt;&amp;lt;div&gt;&lt;/code&gt; tag into the DOM with an ID of &lt;code&gt;_is-dart-enabled&lt;/code&gt;.  I should then be able to to query for the presence of that tag from Javascript:&lt;pre class="prettyprint"&gt;&amp;lt;script&gt;
  if (document.getElementById('_is-dart-enabled') == null) {
    console.log('Not Dart enabled.');
  }
&amp;lt;/script&gt;&lt;/pre&gt;Only that does not work. I always see that &lt;code&gt;console.log()&lt;/code&gt; output—even in Dartium which does add the &lt;code&gt;_is_dart-enabled&lt;/code&gt; tag as expected. &lt;br /&gt;
&lt;br /&gt;
This turns out to be caused by the different ways in which Javascript and Dart are evaluated. Dart only executes once the DOM is ready.  Javascript is evaluated immediately (unless wrapped in something like a DOM ready callback). Thus, the Javascript is always evaluated before Dart has a chance to insert the DOM element.&lt;br /&gt;
&lt;br /&gt;
To get around this, at least for now, I add a &lt;code&gt;setTimeout&lt;/code&gt;:&lt;pre class="prettyprint"&gt;&amp;lt;script&gt;
&lt;b&gt;  setTimeout(function() {&lt;/b&gt;
    if (document.getElementById('_is-dart-enabled') == null) {
      console.log('Not Dart enabled.');
    }
&lt;b&gt;  }, 50);&lt;/b&gt;
&amp;lt;/script&gt;&lt;/pre&gt;With that, I only see "Not Dart enabled." when the browser really does not support Dart.  So far so good.  I convert that into a &lt;code&gt;noDart()&lt;/code&gt; function that takes a callback and arguments to be invoked when there is no Dart available:&lt;pre class="prettyprint"&gt;function notDart() {
  var args = Array.prototype.slice.call(arguments)
    , fn_when_no_dart = args.shift();

  setTimeout(function() {
    if (document.getElementById('_is-dart-enabled') == null) {
      console.log('Not Dart enabled.');
      fn_when_no_dart.apply(null, args);
    }
  }, 50);
}&lt;/pre&gt;With that, I can say that, in cases when there is no Dart, I should load the Javascript equivalents:&lt;pre class="prettyprint"&gt;notDart(loadJsEquivalentScripts);

function loadJsEquivalentScripts() {
  var scripts = document.getElementsByTagName('script');
  for (var i=0; i&amp;lt;scripts.length; i++) {
    loadJsEquivalent(scripts[i]);
  }
}

function loadJsEquivalent(script) {
  if (!script.hasAttribute('src')) return;
  if (!script.hasAttribute('type')) return;
  if (script.getAttribute('type') != 'application/dart') return;

  var js_script = document.createElement('script');
  js_script.setAttribute('src', script.getAttribute('src') + '.js');
  document.body.appendChild(js_script);
}&lt;/pre&gt;And, with that, I have Firefox loading my Dart application:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-qoAMAUN1kD4/TxuXDT1O1zI/AAAAAAAADBM/qcp9Cww6zjM/s1600/01-firefox.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="380" width="400" src="http://1.bp.blogspot.com/-qoAMAUN1kD4/TxuXDT1O1zI/AAAAAAAADBM/qcp9Cww6zjM/s400/01-firefox.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
And it still works in Dartium (with no console message about Dart not being enabled):&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-i9FabwsUlXM/TxuXbwXYsiI/AAAAAAAADBY/VQzeCiV6ZnM/s1600/02-dartium_no_messges.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://1.bp.blogspot.com/-i9FabwsUlXM/TxuXbwXYsiI/AAAAAAAADBY/VQzeCiV6ZnM/s400/02-dartium_no_messges.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
That is a little hackish, but it works. I will clean that up and make it available for others if anyone else would like to use it.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #272&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-6492449917537014490?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8Bssdw5o9ePwSYV0SCivxVBGSaU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8Bssdw5o9ePwSYV0SCivxVBGSaU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8Bssdw5o9ePwSYV0SCivxVBGSaU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8Bssdw5o9ePwSYV0SCivxVBGSaU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/e49-J-I-rOA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/6492449917537014490/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/supporting-both-dart-and-javascript.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6492449917537014490?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6492449917537014490?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/e49-J-I-rOA/supporting-both-dart-and-javascript.html" title="Supporting Both Dart and Javascript" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-qoAMAUN1kD4/TxuXDT1O1zI/AAAAAAAADBM/qcp9Cww6zjM/s72-c/01-firefox.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/supporting-both-dart-and-javascript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkECRXg_fSp7ImA9WhRUEkw.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-1740734251066846755</id><published>2012-01-20T23:57:00.000-05:00</published><updated>2012-01-22T00:37:44.645-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-22T00:37:44.645-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart Animation</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/delete-xhr-and-dom-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/supporting-both-dart-and-javascript.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
My sweet comic book application written entirely in &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; is starting to come together:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-r8WdIXTpk2Y/Txjwh5FcVMI/AAAAAAAADAw/rsnnEPHxUfc/s1600/03-gone_gone.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://2.bp.blogspot.com/-r8WdIXTpk2Y/Txjwh5FcVMI/AAAAAAAADAw/rsnnEPHxUfc/s400/03-gone_gone.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
At this point, I can delete stuff from my front-end, but I am forced to navigate to a separate page to add new comics to the collection. Bah!&lt;br /&gt;
&lt;br /&gt;
Instead, I would like to convert that last line to a link to a smooth animation of an add-form.  Since I am building this in Dartium, a webkit based browser, I should be able to do something along the lines of CSS3 animations.  Let's see...&lt;br /&gt;
&lt;br /&gt;
First up, I define a "faded" CSS class that describes the start state for my add-form.  In this case, I want the thing hidden:&lt;pre class="prettyprint"&gt;.faded {
  opacity: 0;
  -webkit-transition: opacity 1s ease-in-out;
}&lt;/pre&gt;To get my fade animation, I make the opacity as a "-webkit-transition" property with a duration of 1 second.  The &lt;code&gt;ease-in-out&lt;/code&gt; transformation function starts things off slow, gets going at a pretty good pace, and then stops slowly.  Next, I define two other CSS classes describing the end state of my transitions:&lt;pre class="prettyprint"&gt;.fade-in {
  opacity: 1;
}

.fade-out {
  opacity: 0;
}&lt;/pre&gt;With that, I am ready for some Dart.  In addition to loading my comic book collection via Ajax, I now want to attach the necessary handlers to the add-form:&lt;pre class="prettyprint"&gt;main() {
  load_comics();
&lt;b&gt;  attach_add_handler();&lt;/b&gt;
}&lt;/pre&gt;The appropriate action when clicking the add text is to enable the add-form.  So I add &lt;code&gt;enable_add_form&lt;/code&gt; as a click handler:&lt;pre class="prettyprint"&gt;attach_add_handler() {
  document.
    query('#add-comic').
    on.
    click.
    add(enable_add_form);
}&lt;/pre&gt;(yes, I hate horizontal code that much)&lt;br /&gt;
&lt;br /&gt;
To enable the form, I merely need to add the &lt;code&gt;fade-in&lt;/code&gt; class to my form:&lt;pre class="prettyprint"&gt;enable_add_form(event) {
  final form_div = document.query('#add-comic-form');

  form_div.classes.remove('fade-out');
&lt;b&gt;  form_div.classes.add('fade-in');&lt;/b&gt;

  form_div.queryAll('a').forEach((el) {
    el.on.click.add(disable_add_form);
    event.preventDefault();
  });
}&lt;/pre&gt;For good measure, I also remove the &lt;code&gt;fade-out&lt;/code&gt; class (if present). I also add the &lt;code&gt;disable_add_form&lt;/code&gt; handler as a click handler to all child &lt;code&gt;&amp;lt;a&gt;&lt;/code&gt; tags (e.g. Cancel links).&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;disable_add_form&lt;/code&gt; handler is, of course, the inverse of &lt;code&gt;enable_add_form&lt;/code&gt;:&lt;pre class="prettyprint"&gt;disable_add_form(event) {
  final form_div = document.query('#add-comic-form');

  form_div.classes.remove('fade-in');
  form_div.classes.add('fade-out');

  form_div.queryAll('a').forEach((el) {
    el.on.click.remove(disable_add_form);
    event.preventDefault();
  });
}&lt;/pre&gt;And it works. When the page first loads, there is no form (as before).  Clicking on the add comic text causes the form to fade into view:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-X2iCnRIlsDs/TxpEpG7cRLI/AAAAAAAADBA/5HdzvvFEXhk/s1600/02-form.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://1.bp.blogspot.com/-X2iCnRIlsDs/TxpEpG7cRLI/AAAAAAAADBA/5HdzvvFEXhk/s400/02-form.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The problem with this approach is that I need to build those CSS classes in addition to Dart.  One way to get around this is to replace the add/remove class names and, instead, use webkit's animation frames:&lt;pre class="prettyprint"&gt;enable_add_form(event) {
  final form_div = document.query('#add-comic-form');

&lt;b&gt;  var start = new Date.now();
  step(timestamp) {
    var progress = timestamp - start.value
      , opacity = "${progress/1000}";

    form_div.style.opacity = opacity;
    if (progress &amp;lt; 1000) window.webkitRequestAnimationFrame(step, form_div);
    true;
  }
  window.webkitRequestAnimationFrame(step, form_div);&lt;/b&gt;
}&lt;/pre&gt;Hooking in to this &lt;a href="https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame"&gt;animation stuff&lt;/a&gt; is cool, but it is overkill for simple animations.  &lt;br /&gt;
&lt;br /&gt;
Happily, while rooting through documentation, I found that &lt;a href="http://api.dartlang.org/html/CSSStyleDeclaration.html"&gt;CSSStyleDeclaration&lt;/a&gt; supports setting animation properties rather easily:&lt;pre class="prettyprint"&gt;enable_add_form(event) {
  final form_div = document.query('#add-comic-form');

&lt;b&gt;  form_div.style.transition = 'opacity 1s ease-in-out';
  form_div.style.opacity = "1";&lt;/b&gt;

  form_div.queryAll('a').forEach((el) {
    el.on.click.add(disable_add_form);
    event.preventDefault();
  });
}&lt;/pre&gt;&lt;i&gt;That&lt;/i&gt; is pretty darn nice.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #271&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-1740734251066846755?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BrFGmzVSHUhXzm3yR8BcO_Q22EM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BrFGmzVSHUhXzm3yR8BcO_Q22EM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BrFGmzVSHUhXzm3yR8BcO_Q22EM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BrFGmzVSHUhXzm3yR8BcO_Q22EM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/P-4wZCj8O1E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/1740734251066846755/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/dart-animation.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/1740734251066846755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/1740734251066846755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/P-4wZCj8O1E/dart-animation.html" title="Dart Animation" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-r8WdIXTpk2Y/Txjwh5FcVMI/AAAAAAAADAw/rsnnEPHxUfc/s72-c/03-gone_gone.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/dart-animation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUICQX4yeSp7ImA9WhRUEU8.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-3508271614733491616</id><published>2012-01-19T23:46:00.001-05:00</published><updated>2012-01-21T00:26:00.091-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-21T00:26:00.091-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Delete (XHR and DOM) in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/simple-ajax-gets-and-json-parsing-in.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/dart-animation.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
As of last night, I have my little comic book &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; application querying the data store over REST and populating the web page thusly:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-PxO5gmoicNc/Txej0GWEvAI/AAAAAAAADAM/OEUEfeb8aQ8/s1600/01-list.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="340" src="http://2.bp.blogspot.com/-PxO5gmoicNc/Txej0GWEvAI/AAAAAAAADAM/OEUEfeb8aQ8/s400/01-list.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Tonight I would like to attach handlers to those delete links. If possible, I would like the handlers to DELETE the record from the backend and, on successful delete, I would like to remove the item from the page.&lt;br /&gt;
&lt;br /&gt;
First up I attach the delete handlers after the comic books have been loaded and populated on the page:&lt;pre class="prettyprint"&gt;load_comics() {
  var list_el = document.query('#comics-list')
    , req = new XMLHttpRequest();

  req.open('get', '/comics', true);

  req.on.load.add((res) {
    var list = JSON.parse(req.responseText);
    list_el.innerHTML = graphic_novels_template(list);
&lt;b&gt;    attach_delete_handlers(list_el);&lt;/b&gt;
  });

  req.send();
}&lt;/pre&gt;Having done quite a bit of Backbone.js coding recently, I am already fighting an intense urge to convert this into a collection fronted by a collection view / item view.  I will experiment with that later—for now, I will just get this working.&lt;br /&gt;
&lt;br /&gt;
As for actually adding the delete event handler, I query the list element for all delete items.  For each of them, I add an on-click handler:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
      print("id: " + event.target.parent.id);
      event.preventDefault();
    });
  });
}&lt;/pre&gt;For now, I just print out the ID of the containing LI tag, in which, as can be seen in the screenshot above, I am storing the ID of the element in the data store. Then I prevent the default event bubbling from occurring so that no navigation takes place.&lt;br /&gt;
&lt;br /&gt;
And that works. Clicking the delete links prints out the IDs of the comic books in question:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-uaqtqPgy6Io/TxjjmNfKD4I/AAAAAAAADAY/3EFNsn5X97Y/s1600/02-bullet_trace_delete.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://1.bp.blogspot.com/-uaqtqPgy6Io/TxjjmNfKD4I/AAAAAAAADAY/3EFNsn5X97Y/s400/02-bullet_trace_delete.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
In my &lt;a href="http://expressjs.com/"&gt;express.js&lt;/a&gt; + &lt;a href="https://github.com/felixge/node-dirty"&gt;node-dirty&lt;/a&gt; backend, I have a simple delete route:&lt;pre class="prettyprint"&gt;app.delete('/comics/:id', function(req, res) {
  db.rm(req.params.id);
  res.send('{}');
});&lt;/pre&gt;With that, I update the delete handlers to call a new &lt;code&gt;delete()&lt;/code&gt; function:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
&lt;b&gt;      delete(event.target.parent.id);&lt;/b&gt;
      event.preventDefault();
    });
  });
}&lt;/pre&gt;In the &lt;code&gt;delete()&lt;/code&gt; function, I open an Ajax request with the delete HTTP verb and the proper ID:&lt;pre class="prettyprint"&gt;delete(id, [callback]) {
  var req = new XMLHttpRequest()
    , default_callback = () { print("[delete] $id"); };

  req.on.load.add((res) {
    (callback || default_callback)();
  });

  req.open('delete', '/comics/$id', true);
  req.send();
}&lt;/pre&gt;In there, I have added an on-load handler that will invoke an optional callback.  If the callback is not supplied (I have not supplied it yet), then the &lt;code&gt;default_callback()&lt;/code&gt; is invoked.&lt;br /&gt;
&lt;br /&gt;
Except it isn't. When I try this out, I am greeted by:&lt;pre class="prettyprint"&gt;Exception: Object is not closure
Stack Trace:  0. Function: '::function' url: 'http://localhost:3000/scripts/comics.dart' line:37 col:35
 1. Function: 'EventListenerListImplementation.function' url: 'dart:htmlimpl' line:23183 col:35&lt;/pre&gt;The "Object is not a closure" error message in Dart is quickly becoming my least favorite.  It usually takes me a while to figure out what it is trying to tell me.&lt;br /&gt;
&lt;br /&gt;
What it is telling this time, it turns out, is that the result of &lt;code&gt;(callback || default_callback)&lt;/code&gt; is a boolean, not one or the other functions. Dang. Looks like short-circuit evaluations don't behave as I hoped in Dart. Thus I am forced to use a slightly more verbose ternary:&lt;pre class="prettyprint"&gt;delete(id, [callback]) {
  var req = new XMLHttpRequest()
    , default_callback = () { print("[delete] $id"); };

  req.on.load.add((res) {
&lt;b&gt;    (callback != null ? callback : default_callback)();&lt;/b&gt;
  });

  req.open('delete', '/comics/$id', true);
  req.send();
}&lt;/pre&gt;That does work as I hope as I see my default &lt;code&gt;[delete]&lt;/code&gt; message logged to the console:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-7Vo_X0MXeHs/TxjuDbNMExI/AAAAAAAADAk/gFhloMq0X9s/s1600/02-deleted.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://4.bp.blogspot.com/-7Vo_X0MXeHs/TxjuDbNMExI/AAAAAAAADAk/gFhloMq0X9s/s400/02-deleted.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The last thing that I would like to get done tonight is removing the list item from the DOM once it has been successfully removed from the backend store.  This is where that optional &lt;code&gt;callback&lt;/code&gt; parameter of &lt;code&gt;delete()&lt;/code&gt; comes in handy.  &lt;br /&gt;
&lt;br /&gt;
I specify the optional &lt;code&gt;callback&lt;/code&gt; argument to delete when I attach the delete handler.  In addition to printing the ID of the item being deleted, I also remove the element from the DOM:&lt;pre class="prettyprint"&gt;attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
      delete(event.target.parent.id, &lt;b&gt;callback:() {
        print("[delete] ${event.target.parent.id}");
        event.target.parent.remove();
      }&lt;/b&gt;);
      event.preventDefault();
    });
  });
}&lt;/pre&gt;I am just guessing on the &lt;code&gt;remove()&lt;/code&gt; method for the element.  But, given what I know of Dart, I am reasonably sure that will work because, as a long-time Javascript developer, that is what I would use.&lt;br /&gt;
&lt;br /&gt;
And it works!  Not only is the item removed from the backend, but it is also removed from the UI:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-r8WdIXTpk2Y/Txjwh5FcVMI/AAAAAAAADAw/rsnnEPHxUfc/s1600/03-gone_gone.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://2.bp.blogspot.com/-r8WdIXTpk2Y/Txjwh5FcVMI/AAAAAAAADAw/rsnnEPHxUfc/s400/03-gone_gone.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
With delete from XHR and delete from the DOM both working, I call it a night.  Up tomorrow, I may try to refactor this a bit. Or I might play with animations. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #270&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-3508271614733491616?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AxapcyEtfNSwZEO-SLWi6qNJ2YA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AxapcyEtfNSwZEO-SLWi6qNJ2YA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AxapcyEtfNSwZEO-SLWi6qNJ2YA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AxapcyEtfNSwZEO-SLWi6qNJ2YA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/mBk96C1FYuo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/3508271614733491616/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/delete-xhr-and-dom-in-dart.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/3508271614733491616?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/3508271614733491616?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/mBk96C1FYuo/delete-xhr-and-dom-in-dart.html" title="Delete (XHR and DOM) in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-PxO5gmoicNc/Txej0GWEvAI/AAAAAAAADAM/OEUEfeb8aQ8/s72-c/01-list.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/delete-xhr-and-dom-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDRX8-eSp7ImA9WhRVGUk.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-6949418112859277694</id><published>2012-01-18T23:59:00.001-05:00</published><updated>2012-01-19T00:06:14.151-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-19T00:06:14.151-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Simple Ajax GETs and JSON Parsing in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/dart-ajax-take-two.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;span style="color: #ccc"&gt;next&amp;rsaquo;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Drat! Thwarted temporarily in my efforts to get Dart to send Ajax requests with data in the request body, I set my sites a little to the side tonight.  In particular, I would like to get simple listings of my comic book collection working.  &lt;br /&gt;
&lt;br /&gt;
The first thing I need is a REST-like listing resource for my &lt;code&gt;/comics&lt;/code&gt;.  With &lt;a href="http://expressjs.com/"&gt;express.js&lt;/a&gt; and &lt;a href="https://github.com/felixge/node-dirty"&gt;node-dirty&lt;/a&gt;, that can be written as:&lt;pre class="prettyprint"&gt;var db = require('dirty')('comix.db');
// ...

app.get('/comics', function(req, res) {
  var list = [];
  db.forEach(function(id, graphic_novel) {
    if (graphic_novel) list.push(graphic_novel);
  });

  res.send(JSON.stringify(list));
});&lt;/pre&gt;I am going to populate the listing page almost entirely with Dart, so the initial view is breathtakingly simple:&lt;pre class="prettyprint"&gt;&amp;lt;script src="scripts/comics.dart" type="application/dart"&gt;&amp;lt;/script&gt;

&amp;lt;h1&gt;Dart Comics&amp;lt;/h1&gt;

&amp;lt;p&gt;Welcome to Dart Comics&amp;lt;/p&gt;

&amp;lt;ul id="comics-list"&gt;&amp;lt;/ul&gt;&lt;/pre&gt;As for my &lt;code&gt;comics.dart&lt;/code&gt; Dart code, I start with a small XHR to GET the &lt;code&gt;/comics&lt;/code&gt; resource and print the results in the console:&lt;pre class="prettyprint"&gt;#import('dart:html');

main() {
  var req = new XMLHttpRequest();
  req.open('get', '/comics', true);

  req.on.load.add((res) {
    print(req.responseText);
  });

  req.send();
}&lt;/pre&gt;I have to import the &lt;code&gt;dart:html&lt;/code&gt; library to gain access to the &lt;code&gt;XMLHttpRequest&lt;/code&gt; object, which is kinda important for Ajax.  &lt;br /&gt;
&lt;br /&gt;
Sending the request is a simple matter of calling &lt;code&gt;open()&lt;/code&gt; with the appropriate HTTP verb and URL, and then instructing my XHR request to &lt;code&gt;send()&lt;/code&gt; itself to the server.  I pass in &lt;code&gt;true&lt;/code&gt; as the third argument &lt;code&gt;open&lt;/code&gt; to make this an asynchronous call so that this code will not block the browser while waiting on a response.  &lt;br /&gt;
&lt;br /&gt;
Since this is an asynchronous call, I need an on-load callback to be fired after the request has been successfully loaded.  For this, I make use of the nice &lt;code&gt;req.on.load.add&lt;/code&gt; syntax to add my callback that simply prints out the response.&lt;br /&gt;
&lt;br /&gt;
The result, after loading the page, is:&lt;pre class="prettyprint"&gt;[
  {"title":"Watchmen","author":"Alan Moore","id":"a1f9bcaa4e9939019ec9e4c36fa7a97e"},
  {"title":"Watchmen","author":"Alan Moore","id":"12e5c6c33b16399f778bad86fc6bc082"}
]&lt;/pre&gt;Whoops! Looks like I have duplicate entries.  I will need to add validation code another day to prevent this situation.  For now, I would like to list all of the returned entries along with a delete link.&lt;br /&gt;
&lt;br /&gt;
For this, I iterate through each of the returned comic books, building up an HTML string along the way:&lt;pre class="prettyprint"&gt;#import('dart:html');
#import('dart:json');

main() {
   var list_el = document.query('#comics-list')
    , req = new XMLHttpRequest();

  req.open('get', '/comics', true);

  req.on.load.add((res) {
    print(req.responseText);
    var list = JSON.parse(req.responseText);

    var html = '';
    list.forEach((graphic_novel) {
      html +=
        "&amp;lt;li id='${graphic_novel['id']}'&gt;" +
        "${graphic_novel['title']}" +
        " " +
        "&amp;lt;a href='#'&gt;[delete]&amp;lt;/a&gt;" +
        "&amp;lt;/li&gt;";
    });
  req.send();
}
&lt;/pre&gt;Which results in:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-PxO5gmoicNc/Txej0GWEvAI/AAAAAAAADAM/OEUEfeb8aQ8/s1600/01-list.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="340" src="http://2.bp.blogspot.com/-PxO5gmoicNc/Txej0GWEvAI/AAAAAAAADAM/OEUEfeb8aQ8/s400/01-list.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Nice.  It was fairly easy to connect my Dart application to a REST-like backend.  The string interpolation with the dollar sign delimiter helps a bit with the HTML, but a template engine might still be nice.  It is definitely nice to have first-level support for JSON (which I find a bit amusing considering that Javascript does not).&lt;br /&gt;
&lt;br /&gt;
Satisfied with my progress so far, I will pick back up tomorrow adding event handlers to the delete links.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #269&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-6949418112859277694?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/a4plJs7Di92R_T0BifneRudK6Yk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/a4plJs7Di92R_T0BifneRudK6Yk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/a4plJs7Di92R_T0BifneRudK6Yk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/a4plJs7Di92R_T0BifneRudK6Yk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/x5AWsnzKmSg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/6949418112859277694/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/simple-ajax-gets-and-json-parsing-in.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6949418112859277694?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6949418112859277694?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/x5AWsnzKmSg/simple-ajax-gets-and-json-parsing-in.html" title="Simple Ajax GETs and JSON Parsing in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-PxO5gmoicNc/Txej0GWEvAI/AAAAAAAADAM/OEUEfeb8aQ8/s72-c/01-list.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/simple-ajax-gets-and-json-parsing-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08HQXY_fSp7ImA9WhRVGUk.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-4485340279842137383</id><published>2012-01-17T23:54:00.000-05:00</published><updated>2012-01-19T00:10:30.845-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-19T00:10:30.845-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="expressjs" /><category scheme="http://www.blogger.com/atom/ns#" term="nodejs" /><category scheme="http://www.blogger.com/atom/ns#" term="node-dirty" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart Ajax Take Two</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/submitting-forms-via-ajax-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/simple-ajax-gets-and-json-parsing-in.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Last night, I came oh-so-close to getting XHR requests from a Dart web page working. To be precise, I was able to get HTTP GET requests to flow via XHR, but POSTs eluded me.  Tonight, I pick back up, starting with some tips passed along by Adam Coding in &lt;a href="http://japhr.blogspot.com/2012/01/submitting-forms-via-ajax-in-dart.html#comments"&gt;last night's comments&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The first thing that I try is setting the request headers. I do not think that this will help as the error that I am getting is that &lt;code&gt;send()&lt;/code&gt; is not implemented, but fingers crossed.  In yesterday's comic book application, I now specify that I am passing &lt;code&gt;application/json&lt;/code&gt;:&lt;pre class="prettyprint"&gt;&lt;code&gt;    var data = {'title':title.value, 'author':author.value}
      , json = JSON.stringify(data);

    print(json);

    var req = new XMLHttpRequest();
    req.open('post', '/comics', true);
&lt;b&gt;    req.setRequestHeader('Content-type', 'application/json');&lt;/b&gt;
    req.send(json);
    print(req.responseText);&lt;/code&gt;&lt;/pre&gt;Unfortunately, but not too surprisingly, I am still greeted with a not-implemented exception when I trigger the XHR send by submitting the form:&lt;pre class="prettyprint"&gt;Exception: NotImplementedException
Stack Trace:  0. Function: 'XMLHttpRequestImplementation.send' url: '/home/cstrom/repos/dartium/src/out/Release/obj/gen/webkit/bindings/XMLHttpRequestImplementation.dart' line:43 col:3
 1. Function: 'XMLHttpRequestWrappingImplementation.send' url: 'dart:htmlimpl' line:25561 col:20
 2. Function: '::function' url: 'http://localhost:3000/scripts/comic_put.dart' line:27 col:13
 3. Function: 'EventListenerListImplementation.function' url: 'dart:htmlimpl' line:23183 col:35&lt;/pre&gt;Bummer.&lt;br /&gt;
&lt;br /&gt;
My next step is to try this from the command-line version of Dart that I have.  I reduce my browser script to the following:&lt;pre class="prettyprint"&gt;#import('dom');
#import('dart:json');

main() {
    var data = {
          'title':"Watchmen",
          'author':"Alan Moore"
        }
      , json = JSON.stringify(data);

    print(json);

    var req = new XMLHttpRequest();
    req.open('post', 'http://localhost:3000/comics', true);
    req.setRequestHeader('Content-type', 'application/json');
    req.send(json);
    print(req.responseText);
  });
}&lt;/pre&gt;Unfortunately, that also fails to work.  It seems that the command-line version of Dart lacks the dom, html, and json libaries:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart xhr01.dart
'/home/cstrom/repos/dart-site/examples/command_line/xhr01.dart': Error: line 1 pos 1: library handler failed: Do not know how to load 'dart:html'
#import('dart:html');
^
&lt;/pre&gt;Again bummer.&lt;br /&gt;
&lt;br /&gt;
The last thing that I can try is compiling the Dart code into Javascript:&lt;pre class="prettyprint"&gt;scripts git:(master) ✗ &lt;b&gt;frogc comic_put.dart &lt;/b&gt;
/home/cstrom/local/dart-sdk/lib/htmlimpl/htmlimpl.dart:23094:21: warning: a map literal takes one type argument specifying the value type
    _listenerMap = &lt;String, EventListenerList&gt;{};
                    ^^^^^^
➜  scripts git:(master) ✗ ls -1
comic_put.dart
&lt;b&gt;comic_put.dart.js&lt;/b&gt;&lt;/pre&gt;That warning message is a bit weird, but seems to be ignorable.&lt;br /&gt;
&lt;br /&gt;
After switching  my web page to use the compiled Javascript instead of the pure Dart:&lt;pre class="prettyprint"&gt;&amp;lt;script src="scripts/comic_put.dart.js" type="application/javascript"&gt;&amp;lt;/script&gt;&lt;/pre&gt;&lt;i&gt;Then&lt;/i&gt; things work.  My &lt;a href="http://expressjs.com/"&gt;express.js&lt;/a&gt; + &lt;a href="https://github.com/felixge/node-dirty"&gt;node-dirty&lt;/a&gt; backend responds with:&lt;pre class="prettyprint"&gt;{"title":"Watchmen","author":"Alan Moore","id":"12e5c6c33b16399f778bad86fc6bc082"}&lt;/pre&gt;And, indeed, checking the node-dirty store, my new record is indeed in place:&lt;pre class="prettyprint"&gt;➜  comix git:(master) ✗ node
&gt; db = require('dirty')('comix.db')
&gt; db.get('12e5c6c33b16399f778bad86fc6bc082')
{ title: 'Watchmen',
  author: 'Alan Moore',
  id: '12e5c6c33b16399f778bad86fc6bc082' }&lt;/pre&gt;For the sake of completeness, the POST route in my express.js backend looks like:&lt;pre class="prettyprint"&gt;app.post('/comics', function(req, res) {
  var graphic_novel = req.body;
  graphic_novel['id'] = dirtyUuid();

  db.set(graphic_novel['id'], graphic_novel);

  res.statusCode = 201;
  res.send(JSON.stringify(graphic_novel));
});&lt;/pre&gt;And yes, externally they might look like comic books, but I will always think of them internally as graphic novels. ANYhow...&lt;br /&gt;
&lt;br /&gt;
One caveat with the compiled Javascript is that it is &lt;i&gt;not&lt;/i&gt; executed on DOM-ready like the equivalent Dart code.  With the Dart version, I could put the &lt;code&gt;&amp;lt;script&gt;&lt;/code&gt; tag before the form HTML.  Once I converted to the compiled Javascript, I had to move the &lt;code&gt;&amp;lt;script&gt;&lt;/code&gt; tag after the HTML—otherwise the attempt to add an on-submit event handler failed because the Javascript could not find the form element.&lt;br /&gt;
&lt;br /&gt;
I am a bit surprised that the version of Dartium that I have does not support XHR &lt;code&gt;send()&lt;/code&gt; with a data argument.  The &lt;code&gt;frogc&lt;/code&gt; dart-to-javascript compiler is older than Dartium and yet it supports sending data via XHR.  I will likely recompile Dartium with the latest source code changes included and follow up on the mailing list in the upcoming days.&lt;br /&gt;
&lt;br /&gt;
In the end, a few NotImplemented exceptions are to be expected for such a &lt;a href="http://dart4hipsters.com"&gt;hipsterish&lt;/a&gt; language.  If nothing else, it is pretty cool to know that the Dart code that I quickly threw together last night was sufficient to read form values and submit them via XHR. That is a definite win for Dart.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #268&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-4485340279842137383?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PzA0Q6kDPdicNcmn6Vje_auU56A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PzA0Q6kDPdicNcmn6Vje_auU56A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PzA0Q6kDPdicNcmn6Vje_auU56A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PzA0Q6kDPdicNcmn6Vje_auU56A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/O5t5Gp3XqVE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/4485340279842137383/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/dart-ajax-take-two.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/4485340279842137383?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/4485340279842137383?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/O5t5Gp3XqVE/dart-ajax-take-two.html" title="Dart Ajax Take Two" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/dart-ajax-take-two.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEHQ3s4cCp7ImA9WhRVGEs.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-774634628402533558</id><published>2012-01-16T23:59:00.000-05:00</published><updated>2012-01-17T23:57:12.538-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-17T23:57:12.538-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="dart" /><category scheme="http://www.blogger.com/atom/ns#" term="expressjs" /><category scheme="http://www.blogger.com/atom/ns#" term="nodejs" /><category scheme="http://www.blogger.com/atom/ns#" term="node-dirty" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Submitting Forms via Ajax in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/simple-physics-with-dartbox2d.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/dart-ajax-take-two.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I had a pleasant time messing about with &lt;a href="http://code.google.com/p/dartbox2d/"&gt;DartBox2D&lt;/a&gt; for the past couple of days. I set that aside, for the time being, to investigate writing more typical web applications with &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt;..&lt;br /&gt;
&lt;br /&gt;
For the sake of argument, let us assume that I was a comic book nerd back in the day.  If a certain tablet had suddenly spurred me to obtain some of my old-time favorites in digital format, I might like to have a simple application to keep track of where my various comics reside.  &lt;br /&gt;
&lt;br /&gt;
Eventually, I will see if I can figure out how to store this on the client, but for now, I stick with a server to store the data.  The simplest way (that I know) to serve up HTML, Dart and a REST-like store is an &lt;a href="http://expressjs.com/"&gt;express.js&lt;/a&gt; application server with a &lt;a href="https://github.com/felixge/node-dirty"&gt;node-dirty&lt;/a&gt; store embedded. &lt;br /&gt;
&lt;br /&gt;
I already have npm installed on my system as well as express.js installed globally.  The upshot of this is that I can generate a new express.js app quickly:&lt;pre class="prettyprint"&gt;➜  comix git:(master) ✗ express

   create : .
   create : ./package.json
   create : ./app.js
   create : ./public
   create : ./routes
   create : ./routes/index.js
   create : ./views
   create : ./views/layout.jade
   create : ./views/index.jade
   create : ./public/javascripts
   create : ./public/images
   create : ./public/stylesheets
   create : ./public/stylesheets/style.css

   dont forget to install dependencies:
   $ cd . &amp;amp;&amp;amp; npm install&lt;/pre&gt;I update the generated &lt;code&gt;package.json&lt;/code&gt; to include node-dirty (a simple, nosql backend store):&lt;pre class="prettyprint"&gt;{
    "name": "comic-power"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.5.2"
    , "jade": "&gt;= 0.0.1"
&lt;b&gt;    , "dirty": "0.9.5"
    , "dirty-uuid": "&gt;= 0.0.1"&lt;/b&gt;
  }
}&lt;/pre&gt;With that, I can the use npm to install all of the dependencies for my application:&lt;pre class="prettyprint"&gt;➜  comix git:(master) ✗ npm install
dirty-uuid@0.0.2 ./node_modules/dirty-uuid 
dirty@0.9.5 ./node_modules/dirty 
jade@0.20.0 ./node_modules/jade 
├── mkdirp@0.2.2
└── commander@0.2.1
express@2.5.2 ./node_modules/express 
├── mime@1.2.4
├── qs@0.4.0
├── mkdirp@0.0.7
└── connect@1.8.5&lt;/pre&gt;I then proceed to create a simple form to collect comic book information:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-WMmv5pcefXw/TxT8XuV5alI/AAAAAAAAC_o/iIKMQRvl9zA/s1600/01-add_comix_form.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://2.bp.blogspot.com/-WMmv5pcefXw/TxT8XuV5alI/AAAAAAAAC_o/iIKMQRvl9zA/s400/01-add_comix_form.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
To query the values of the form to submit to the backend, I do the usual dance of adding a reference to my Dart script and a kicker to get the scripting engine started:&lt;pre class="prettyprint"&gt;&amp;lt;script&gt;{}&amp;lt;/script&gt;
&amp;lt;script src="scripts/comic_put.dart" type="application/dart"&gt;&amp;lt;/script&gt;&lt;/pre&gt;To query the form, I import "dart:html" and employ the &lt;code&gt;query&lt;/code&gt; method to find and attach an event listener to the form element:&lt;pre class="prettyprint"&gt;#import('dart:html');

main() {
  var form_el = document.query('#new-comic-form');

  form_el.on.submit.add((event) {
    var form = event.target
      , title = form.query('input[name=title]')
      , author = form.query('input[name=author]')
      , format = form.queryAll('input[name=format]');

    print("title: ${title.value}");
    print("author: ${author.value}");
    print(format);

    event.preventDefault();
  });
}&lt;/pre&gt;This results in the following console output:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-1SQz1NFN8UU/TxT9ZkdwMoI/AAAAAAAAC_0/Tli7qcdIa34/s1600/02-on_submit.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="366" width="333" src="http://1.bp.blogspot.com/-1SQz1NFN8UU/TxT9ZkdwMoI/AAAAAAAAC_0/Tli7qcdIa34/s400/02-on_submit.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
I will worry about the checkboxes another day.  For now, I would dearly love to submit that data to the backend.  Unfortunately, the following:&lt;pre class="prettyprint"&gt;&lt;code&gt;    var data = {'title':title.value, 'author':author.value};
    print(JSON.stringify(data));

    var req = new XMLHttpRequest();
    req.open('post', '/comics', false);
    req.send(JSON.stringify(data));
    print(req.responseText);&lt;/code&gt;&lt;/pre&gt;Ends up causing a not-implemented error:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-KkXOVvfcsYA/TxUB3kaXvbI/AAAAAAAADAA/B561RlB9ebg/s1600/03-not_implemented.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="347" width="400" src="http://1.bp.blogspot.com/-KkXOVvfcsYA/TxUB3kaXvbI/AAAAAAAADAA/B561RlB9ebg/s400/03-not_implemented.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
If I change the &lt;code&gt;req.send(JSON.stringify(data))&lt;/code&gt; call to just &lt;code&gt;req.send()&lt;/code&gt;, then the request is sent... only without the data that is the whole point.&lt;br /&gt;
&lt;br /&gt;
Thwarted for the moment, I call it an evening.  I do very much like the &lt;code&gt;query()&lt;/code&gt; interface for finding elements and collections of elements. Event handlers in Dart are also nice and readable. Still, it would be nice if I could submit data via XHR. I will pick back up here tomorrow.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #267&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-774634628402533558?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/E8K6Y2hK4pBOCqb2-v8SDcgLW1M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/E8K6Y2hK4pBOCqb2-v8SDcgLW1M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/E8K6Y2hK4pBOCqb2-v8SDcgLW1M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/E8K6Y2hK4pBOCqb2-v8SDcgLW1M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/dBF8-aqWx7Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/774634628402533558/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/submitting-forms-via-ajax-in-dart.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/774634628402533558?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/774634628402533558?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/dBF8-aqWx7Q/submitting-forms-via-ajax-in-dart.html" title="Submitting Forms via Ajax in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-WMmv5pcefXw/TxT8XuV5alI/AAAAAAAAC_o/iIKMQRvl9zA/s72-c/01-add_comix_form.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/submitting-forms-via-ajax-in-dart.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4NQH87fyp7ImA9WhRVF0o.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-8029745636737533087</id><published>2012-01-15T23:59:00.001-05:00</published><updated>2012-01-17T00:09:51.107-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-17T00:09:51.107-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="physics engine" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Simple Physics with DartBox2D</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/getting-started-with-dartbox2d.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/submitting-forms-via-ajax-in-dart.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Last night, I got started with &lt;a href="http://code.google.com/p/dartbox2d/"&gt;DartBox2D&lt;/a&gt;, the &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; version of &lt;a href="http://box2d.org/"&gt;Box2D&lt;/a&gt;.  I was able to run the demos and take a stab at drawing some things on the page, but without really understanding what I was doing.  Tonight, I am going to follow along with the "Hello World!" in the &lt;a href="http://box2d.org/manual.pdf"&gt;Box2D Manual&lt;/a&gt; and see if I can get it working in Dart.&lt;br /&gt;
&lt;br /&gt;
From the manual, the first thing to do is create the world:&lt;pre class="prettyprint"&gt;b2Vec2 gravity(0.0f, -10.0f);
bool doSleep = true;
b2World world(gravity, doSleep);
&lt;/pre&gt;The stuff that I already copied from the DartBox2D demo into my Simple2D constructor covers just this:&lt;pre class="prettyprint"&gt;&lt;code&gt;  Simple2d() {
    // Setup the World.
    final gravity = new Vector(0, GRAVITY);
    bool doSleep = true;
    world = new World(gravity, doSleep, new DefaultWorldPool());
  }&lt;/code&gt;&lt;/pre&gt;The only significant difference between the two is the third argument to the world constructor, &lt;code&gt;DefaultWorldPool&lt;/code&gt;.  From the DartBox2D documentation the &lt;code&gt;DefaultWorldPool&lt;/code&gt;:&lt;blockquote&gt;Provides object pooling for some objects used in the engine. Objects retrieved from here should only be used temporarily.&lt;/blockquote&gt;That does not provide much illumination for me, but, looking that the &lt;code&gt;World&lt;/code&gt; code, it definitely requires a third argument.&lt;br /&gt;
&lt;br /&gt;
Next up in the tutorial is to create a "ground box".  As far as I can tell this is not a first order concept in Box2D.  Rather, it is a box that is meant to serve as the ground.  I am probably just being dense, but I am happy to be a newbie.&lt;br /&gt;
&lt;br /&gt;
From the tutorial, the ground box looks like:&lt;pre class="prettyprint"&gt;// Create the body &amp;amp; add it to the world
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);
b2Body* groundBody = world.CreateBody(&amp;amp;groundBodyDef);

// Fixture with width 100 and height 10
b2PolygonShape groundBox;
groundBox.SetAsBox(50.0f, 10.0f)

// Bind shape to body
groundBody-&gt;CreateFixture(&amp;groundBox, 0.0f);
&lt;/pre&gt;The equivalent DartBox2D takes place (adapted from the demo code) in the &lt;code&gt;initialize()&lt;/code&gt; method:&lt;pre class="prettyprint"&gt;void initialize() {
    Body ground;
    {
      BodyDef bd = new BodyDef();
      bd.position.setCoords(0.0, 0.0);
      assert(world != null);
      ground = world.createBody(bd);

      PolygonShape sd = new PolygonShape();
      sd.setAsBox(50.0, 0.4);

      ground.createFixtureFromShape(sd);
    }
  }
&lt;/pre&gt;Next up in the tutorial is adding a box.  Just as with the static ground object, the tutorial creates a dynamic box by defining a body, shape and "fixture" (which connects the two):&lt;pre class="prettyprint"&gt;// Body definition
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&amp;bodyDef);

// Define the shape of the body
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(1.0f, 1.0f)

// Bind shape to the body (e.g. Fixture)
b2FixtureDef fixtureDef;
fixtureDef.shape = &amp;dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3
body-&gt;CreateFixture(&amp;fixtureDef);
&lt;/pre&gt;I add the equivalent Dart code to the &lt;code&gt;initialize()&lt;/code&gt; block:&lt;pre class="prettyprint"&gt;&lt;code&gt;  void initialize() {
    Body ground;
    { /* ... */ }


    Body body;
    {
      BodyDef bodyDef = new BodyDef();
      bodyDef.type = BodyType.DYNAMIC;
      bodyDef.position.setCoords(20.0, 20.0);
      body = world.createBody(bodyDef);

      PolygonShape dynamicBox = new PolygonShape();
      dynamicBox.setAsBox(1.0, 1.0);

      FixtureDef fixtureDef = new FixtureDef();
      fixtureDef.shape = dynamicBox;
      fixtureDef.density = 1.0;
      fixtureDef.friction = 0.3;

      body.createFixture(fixtureDef);
    }
  }&lt;/code&gt;&lt;/pre&gt;The complete set of objects needed to do something in Box2D is somewhat overwhelming: body (for position), shape (for, er.. shape), fixture definition (shape plus real-world attributes), and fixture (the fixture definition realized in the world).  Still, I much prefer it in Dart to C++ (though I may be biased).&lt;br /&gt;
&lt;br /&gt;
The remainder of the tutorial specifies steps for printing out the position of the square as it falls.  That is rather dull and, thankfully, the Box2D folks have provided methods for GUI representations of DartBox2D things via an &lt;code&gt;initializeAnimation()&lt;/code&gt; method:&lt;pre class="prettyprint"&gt;&lt;code&gt;  /**
   * Creates the canvas and readies the demo for animation. Must be called
   * before calling runAnimation.
   */
  void initializeAnimation() {
    // Setup the canvas.
    canvas = document.createElement('canvas');
    canvas.width = CANVAS_WIDTH;
    canvas.height = CANVAS_HEIGHT;
    document.body.appendChild(canvas);
    ctx = canvas.getContext("2d");

    // Create the viewport transform with the center at extents.
    final extents = new Vector(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2);
    viewport = new CanvasViewportTransform(extents, extents);
    viewport.scale = _VIEWPORT_SCALE;

    // Create our canvas drawing tool to give to the world.
    debugDraw = new CanvasDraw(viewport, ctx);

    // Have the world draw itself for debugging purposes.
    world.debugDraw = debugDraw;

    frameCount = 0;
    window.setInterval(() { fps = frameCount; frameCount = 0; }, 1000);
  }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
And a &lt;code&gt;runAnimation()&lt;/code&gt; method:&lt;pre class="prettyprint"&gt;&lt;code&gt;  /**
   * Starts running the demo as an animation using an animation scheduler.
   */
  void runAnimation() {
    window.webkitRequestAnimationFrame((num time) {
      step(time);
    }, canvas);
  }

  void step(num timestamp) {
    world.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);

    // Clear the animation panel and draw new frame.
    ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    world.drawDebugData();
    ctx.setFillColor('black');

    window.webkitRequestAnimationFrame((num time) {
      step(time);
    }, canvas);
  }&lt;/code&gt;&lt;/pre&gt;I find the box a little odd, so I switch it to a ball:&lt;pre class="prettyprint"&gt;&lt;code&gt;    Body body;
    {
      // ...

&lt;b&gt;      CircleShape circle = new CircleShape();
      circle.radius = 2.0;

      FixtureDef fixtureDef = new FixtureDef();
      fixtureDef.shape = circle;&lt;/b&gt;
      fixtureDef.density = 0.8;
      fixtureDef.friction = 0.0;
      fixtureDef.restitution = 0.5;

      body.createFixture(fixtureDef);
    }&lt;/code&gt;&lt;/pre&gt;I also give the body an initial velocity:&lt;pre class="prettyprint"&gt;&lt;code&gt;    Body body;
    {
      BodyDef bodyDef = new BodyDef();
      bodyDef.type = BodyType.DYNAMIC;
      bodyDef.position.setCoords(-25.0, 30.0);
      body = world.createBody(bodyDef);

      body.linearVelocity = new Vector(20.0, 0.0);
      //...
    }&lt;/code&gt;
&lt;/pre&gt;With some bounding box shapes, I have me a nice animation (actually starts ~6 second mark):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-92561ba1ce592014" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;
&lt;param name="bgcolor" value="#FFFFFF"&gt;
&lt;param name="allowfullscreen" value="true"&gt;
&lt;param name="flashvars" value="flvurl=http://v24.nonxt2.googlevideo.com/videoplayback?id%3D92561ba1ce592014%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330309869%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D7E2D3044D1E264B02FAFC77CF83AAFB05EEAFBEA.74F011559384C10B5BAC9357E711D699FB0027A1%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D92561ba1ce592014%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dj76Vy09cV0cjbPDW7K-7EfWWwfM&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;
&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"
width="320" height="266" bgcolor="#FFFFFF"
flashvars="flvurl=http://v24.nonxt2.googlevideo.com/videoplayback?id%3D92561ba1ce592014%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330309869%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D7E2D3044D1E264B02FAFC77CF83AAFB05EEAFBEA.74F011559384C10B5BAC9357E711D699FB0027A1%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D92561ba1ce592014%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dj76Vy09cV0cjbPDW7K-7EfWWwfM&amp;autoplay=0&amp;ps=blogger"
allowFullScreen="true" /&gt;&lt;/object&gt;
&lt;/div&gt;&lt;br /&gt;
That's a fun little library.  Wish I knew about this sooner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #266&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-8029745636737533087?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kpAH2pAIaP0ubODi3aA-wn48Nn8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kpAH2pAIaP0ubODi3aA-wn48Nn8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kpAH2pAIaP0ubODi3aA-wn48Nn8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kpAH2pAIaP0ubODi3aA-wn48Nn8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/KFMenGi8xOg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/8029745636737533087/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/simple-physics-with-dartbox2d.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/8029745636737533087?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/8029745636737533087?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/KFMenGi8xOg/simple-physics-with-dartbox2d.html" title="Simple Physics with DartBox2D" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/simple-physics-with-dartbox2d.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8AQn04eip7ImA9WhRVFkQ.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-1649982281387776688</id><published>2012-01-14T23:59:00.000-05:00</published><updated>2012-01-16T00:47:23.332-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-16T00:47:23.332-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Getting Started with DartBox2D</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/heavy-vs-light-dart-isolates.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/simple-physics-with-dartbox2d.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I have played about with the internals of &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; enough that I feel safe in moving onto some of the browser / DOM integration features.  But first a quick diversion to take a look at &lt;a href="http://code.google.com/p/dartbox2d/"&gt;DartBox2D&lt;/a&gt; port of &lt;a href="http://box2d.org"&gt;Box2D&lt;/a&gt;, a two dimensional physics engine.  &lt;br /&gt;
&lt;br /&gt;
First up, I clone the repository:&lt;pre class="prettyprint"&gt;➜  repos  git clone https://code.google.com/p/dartbox2d/
Cloning into dartbox2d...
remote: Counting objects: 583, done.
remote: Finding sources: 100% (583/583), done.
remote: Total 583 (delta 390)
Receiving objects: 100% (583/583), 377.38 KiB | 139 KiB/s, done.
Resolving deltas: 100% (390/390), done.&lt;/pre&gt;Then take a look at the demo page.  When I click on the first link and check the console output, I see that the Dart detection is not doing a good job of detecting the Dart in my Dartium:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-EUQS4PMPFsM/TxJT5z2jYeI/AAAAAAAAC-g/Yav4ioberm4/s1600/01-no_dart.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="100" width="400" src="http://3.bp.blogspot.com/-EUQS4PMPFsM/TxJT5z2jYeI/AAAAAAAAC-g/Yav4ioberm4/s400/01-no_dart.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Looking through the code, I see:&lt;pre class="prettyprint"&gt;&lt;code&gt;        if(&lt;b&gt;getQueryVariable('native')&lt;/b&gt; &amp;amp;&amp;amp; document.implementation.hasFeature('dart')) {
          // Browser has the goods, so kick it in to dart gear.
          console.log('Dart supported.');
          script.setAttribute('type', 'application/dart');
          script.setAttribute('src', 'demos/' + demo + '.dart');
        } else {
          // If browser doesn't support dart, redirect to js version.
          console.log('JS fallback.');
          script.setAttribute('src', 'js/demos/' + demo + '.dart.js');
        }
        document.body.appendChild(script);&lt;/code&gt;&lt;/pre&gt;Ah, so I need to manually specify a &lt;code&gt;native=1&lt;/code&gt; query parameter to get native detection to work.  With that, DartBox2d admits that I do have Dart:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-M7C_tR_KPtc/TxJV2UCVQOI/AAAAAAAAC-4/A380rUtoLsE/s1600/02-yes_dart.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="70" width="400" src="http://3.bp.blogspot.com/-M7C_tR_KPtc/TxJV2UCVQOI/AAAAAAAAC-4/A380rUtoLsE/s400/02-yes_dart.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
And, more importantly, I get nice demos like a bouncing ball in the "Ball Cage":&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-WunRMEesjHA/TxJV2Xxp72I/AAAAAAAAC_E/43FEuafvMpY/s1600/03-ball_cage.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="313" width="400" src="http://3.bp.blogspot.com/-WunRMEesjHA/TxJV2Xxp72I/AAAAAAAAC_E/43FEuafvMpY/s400/03-ball_cage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
And "Circle Stress":&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-YrUP7y2qDCs/TxJT58t_M0I/AAAAAAAAC-o/A37TJzd37R4/s1600/01-circle_stress.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="249" width="400" src="http://3.bp.blogspot.com/-YrUP7y2qDCs/TxJT58t_M0I/AAAAAAAAC-o/A37TJzd37R4/s400/01-circle_stress.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Since I know next to nothing about physics engines, I plan to familiarize myself like I always do: by shamelessly copying.  Of the demos that are included, the simplest might be the blob test (at least the game board), so I start there.&lt;br /&gt;
&lt;br /&gt;
I create myself an HTML document to hold my test:&lt;pre class="prettyprint"&gt;&amp;lt;!DOCTYPE html&gt;
&amp;lt;html&gt;
  &amp;lt;head&gt;
    &amp;lt;title&gt;Simple DartBox2D&amp;lt;/title&gt;
    &amp;lt;script&gt;{}&amp;lt;/script&gt;
    &amp;lt;script type="application/dart" src="simple.dart"&gt;&amp;lt;/script&gt;
  &amp;lt;/head&gt;
  &amp;lt;body&gt;
    &amp;lt;h1&gt;Simple DartBox2D&amp;lt;/h1&gt;
  &amp;lt;/body&gt;
&amp;lt;/html&gt;
&lt;/pre&gt;And, in the &lt;code&gt;simple.dart&lt;/code&gt; file, I copy the skeleton of the board from the blob test:&lt;pre class="prettyprint"&gt;#import('dart:dom');
#import('lib/box2d.dart');

class Simple2d {
  /** The default canvas width and height. */
  static final int CANVAS_WIDTH = 900;
  static final int CANVAS_HEIGHT = 600;

  /** Scale of the viewport. */
  static final num _VIEWPORT_SCALE = 10;

  /** The gravity vector's y value. */
  static final num GRAVITY = -10;


  // other setup

  Simple2d() {
    // Setup the World.
    final gravity = new Vector(0, GRAVITY);
    bool doSleep = true;
    world = new World(gravity, doSleep, new DefaultWorldPool());
  }

  /** Entrypoint. */
  static void main() {
    final simple2d = new Simple2d();
    simple2d.initialize();
    simple2d.initializeAnimation();
    simple2d.runAnimation();
  }

  void initialize() { /* ... */ }
  void initializeAnimation() { /* ... */ }
  void runAnimation() { /* ... /* }
  void step(num timestamp) { /* ... */ }
}

void main() {
  Simple2d.main();
}
&lt;/pre&gt;All in all, there is quite a bit of setup required just to draw the board.  But it works.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-fniLr5r71sw/TxJeRjvezZI/AAAAAAAAC_Q/4GT_LQdDydw/s1600/05-gameboard.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="233" width="400" src="http://1.bp.blogspot.com/-fniLr5r71sw/TxJeRjvezZI/AAAAAAAAC_Q/4GT_LQdDydw/s400/05-gameboard.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
That is just the gameboard and there is much that I cargo-coded without understanding.  Tomorrow I will try to actually add something on that board besides lines and, maybe, gain a deeper understanding of everything that is involved.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #265&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-1649982281387776688?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sKFiFXfjSBSp6QO33PsVmYormFQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sKFiFXfjSBSp6QO33PsVmYormFQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sKFiFXfjSBSp6QO33PsVmYormFQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sKFiFXfjSBSp6QO33PsVmYormFQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/R2okirLZZ3o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/1649982281387776688/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/getting-started-with-dartbox2d.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/1649982281387776688?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/1649982281387776688?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/R2okirLZZ3o/getting-started-with-dartbox2d.html" title="Getting Started with DartBox2D" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-EUQS4PMPFsM/TxJT5z2jYeI/AAAAAAAAC-g/Yav4ioberm4/s72-c/01-no_dart.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/getting-started-with-dartbox2d.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUHRH88fyp7ImA9WhRVFk0.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-2019846486402843951</id><published>2012-01-13T23:59:00.001-05:00</published><updated>2012-01-15T00:10:35.177-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-15T00:10:35.177-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Heavy vs. Light Dart Isolates</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/dart-mixins.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/getting-started-with-dartbox2d.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Spurred by some comments in a &lt;a href="http://japhr.blogspot.com/2012/01/dart-isolates-for-speed.html"&gt;previous post&lt;/a&gt;, I investigate the differences between light and heavy &lt;a href="http://api.dartlang.org/dart_core/Isolate.html"&gt;Isolates&lt;/a&gt; in &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt;.  Heavy isolates run in separate threads whereas the light versions all run in the same thread.  In theory this should mean that heavy threads can take better advantage of multi-core CPUs.  Let's see if "in-practice" agrees.&lt;br /&gt;
&lt;br /&gt;
For my testing, I am using the following for heavy Isolates:&lt;pre class="prettyprint"&gt;#import('pretty_stopwatch.dart');
&lt;b&gt;#import('solver_heavy.dart');&lt;/b&gt;
#source('spawn.dart');

main() {
  final fib_solver = new FibSolver();

  // List of number to obtain the fibonacci number
  var list = [5, 40, 39, 32, 6, 41];

  // Timer
  var timer = new PrettyStopwatch.start()
    , completer = new Completer();

  // completer to be signaled when all isolates complete
  completer.future.then((args) {
    timer.stop();
  });

  // spawn 2 isolates, each solving half
  spawn(fib_solver, list, completer);
}&lt;/pre&gt;The only difference between this version and the light version is the solver being imported.  And the only difference between the two solver libraries is the constructor being used:&lt;pre class="prettyprint"&gt;#library('heavy weight isolates for solving fibs');

class FibSolver extends Isolate {
  FibSolver(): super.heavy();
  // ...
}&lt;/pre&gt;When I run the heavy version from the command line, I find:&lt;pre class="prettyprint"&gt;➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 6406ms
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 6648ms
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6540ms
➜  isolate_timing git:(master) ✗ dart heavy.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 7631ms
&lt;/pre&gt;So, around 6.5 seconds.&lt;br /&gt;
&lt;br /&gt;
When I do the same for the lighter version, I find:&lt;pre class="prettyprint"&gt;➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6880ms
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6328ms
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6418ms
➜  isolate_timing git:(master) ✗ dart light.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 7480ms
&lt;/pre&gt;Again, around 6.5 seconds.  So unexpectedly, there is no difference.  &lt;br /&gt;
&lt;br /&gt;
Perhaps this is not yet implemented in the command line tool? To test that hypothesis, I load the same script up in the browser.  For the heavy version, I find:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Ba4R_6ga6X0/TxELZAsRDpI/AAAAAAAAC9w/AVa4zZvqmaM/s1600/03-heavy.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="297" width="241" src="http://1.bp.blogspot.com/-Ba4R_6ga6X0/TxELZAsRDpI/AAAAAAAAC9w/AVa4zZvqmaM/s400/03-heavy.png" /&gt;&lt;/a&gt;&lt;/div&gt;(&lt;a href="http://dart4hipsters.com/examples/isolate_timing/heavy.html"&gt;try on dart4hipsters&lt;/a&gt; -- requires Dart-enabled browser)&lt;br /&gt;
&lt;br /&gt;
For the light version, I find:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-lnrIHA0U14U/TxELZKBsuRI/AAAAAAAAC94/Ge3KV1Wcrfw/s1600/04-light.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="281" width="271" src="http://4.bp.blogspot.com/-lnrIHA0U14U/TxELZKBsuRI/AAAAAAAAC94/Ge3KV1Wcrfw/s400/04-light.png" /&gt;&lt;/a&gt;&lt;/div&gt;(&lt;a href="http://dart4hipsters.com/examples/isolate_timing/light.html"&gt;try on dart4hipsters&lt;/a&gt; -- requires Dart-enabled browser)&lt;br /&gt;
&lt;br /&gt;
So again, both are about the same.&lt;br /&gt;
&lt;br /&gt;
For completeness, I do the same for compiled Javascript versions.  But, since Javascript is single-threaded, there should certainly be no differences.&lt;br /&gt;
&lt;br /&gt;
For the heavy version I find that the numbers are a little slower than the Dart equivalent:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-du6_GCe1orc/TxELZQopinI/AAAAAAAAC-I/aXIU9tfE3QI/s1600/06-heavy_js.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="299" width="249" src="http://2.bp.blogspot.com/-du6_GCe1orc/TxELZQopinI/AAAAAAAAC-I/aXIU9tfE3QI/s400/06-heavy_js.png" /&gt;&lt;/a&gt;&lt;/div&gt;(&lt;a href="http://dart4hipsters.com/examples/isolate_timing/heavy_js.html"&gt;try on dart4hipsters&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
But, astonishingly, the light version is much, much slower:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-a-KYMrNEhGk/TxELZtYwVII/AAAAAAAAC-U/UQcYZ98g3G8/s1600/07-light_js.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="281" width="301" src="http://2.bp.blogspot.com/-a-KYMrNEhGk/TxELZtYwVII/AAAAAAAAC-U/UQcYZ98g3G8/s400/07-light_js.png" /&gt;&lt;/a&gt;&lt;/div&gt;(&lt;a href="http://dart4hipsters.com/examples/isolate_timing/light_js.html"&gt;try on dart4hipsters&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
I reload the web page several times to be sure that the results are consistent.  Within an acceptable margin, the light Javascript Isolates are always nearly twice as slow as the heavy version.&lt;br /&gt;
&lt;br /&gt;
I am quite surprised by this.  Since Dart can be multi-threaded, while Javascript is always single threaded, I would have expected to find discrepancies between heavy and light isolates in Dart, not Javascript.  I can only speculate as to why at this point, but I would guess that light-weight Isolates are not yet implemented in Dart (I can see two CPUs pegged for both scenarios).  As for the Javascript differences, I know that Chrome is capable of doing some calculations multi-threaded even though Javascript is normally single threaded.  I can only guess that Chrome is doing so for the heavy.js case.&lt;br /&gt;
&lt;br /&gt;
I will investigate a bit more tomorrow.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #264&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-2019846486402843951?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0jvXt9djxDrcFIa_dLxGbPDbuxs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0jvXt9djxDrcFIa_dLxGbPDbuxs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0jvXt9djxDrcFIa_dLxGbPDbuxs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0jvXt9djxDrcFIa_dLxGbPDbuxs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/2IMBUAxTHhw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/2019846486402843951/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/heavy-vs-light-dart-isolates.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/2019846486402843951?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/2019846486402843951?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/2IMBUAxTHhw/heavy-vs-light-dart-isolates.html" title="Heavy vs. Light Dart Isolates" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Ba4R_6ga6X0/TxELZAsRDpI/AAAAAAAAC9w/AVa4zZvqmaM/s72-c/03-heavy.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/heavy-vs-light-dart-isolates.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMBRng8eyp7ImA9WhRVFUw.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-6701369804125926998</id><published>2012-01-12T23:59:00.001-05:00</published><updated>2012-01-14T00:20:57.673-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-14T00:20:57.673-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart (Pseudo) Mixins</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/converting-complex-dart-apps-to.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/heavy-vs-light-dart-isolates.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I am perfectly up front for harboring and intense, but completely rational dislike for inheritance.  It is one of those things that works quite well in academics but is rarely useful in real life.  But, because most of us learned that object oriented programming is synonymous with inheritance, inheritance often gets used when it does not make sense.  And when it does not make sense to use a pattern, bad things are sure to follow.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; supports inheritance.  I am sorely tempted to completely omit this tidbit of information from &lt;a href="http://dart4hipsters.com"&gt;Dart for Hipsters&lt;/a&gt;.  I will probably wimp out and mention it in passing, but what I will focus on (if it works) are mixins.&lt;br /&gt;
&lt;br /&gt;
Mixins are a mechanism for adding a slice of functionality.  Consider two shape classes:&lt;pre class="prettyprint"&gt;#library('Super amazing shapes!');

class Rectangle {
  final num height, width;
  Rectangle(this.width, this.height);
  area() =&gt; this.width * this.height;
  perimeter() =&gt; 2*this.width + 2*this.height;
}

class Circle {
  final num radius;
  Circle(this.radius);
  area() =&gt; 2 * Math.PI * this.radius * this.radius;
  perimeter() =&gt; 2 * Math.PI * this.radius;
}&lt;/pre&gt;To use them I might do something like:&lt;pre class="prettyprint"&gt;#import('shapes01.dart');

main() {
  var r = new Rectangle(2, 10);
  print("The area of the rectangle is: " + r.area());
  print("The perimeter of the rectangle is: " + r.perimeter());
  print("");

  var c = new Circle(5);
  print("The area of the circle is: " + c.area());
  print("The perimeter of the circle is: " + c.perimeter());
  print("");
}&lt;/pre&gt;Which would result in the following output:&lt;pre class="prettyprint"&gt;➜  mixins git:(master) ✗ dart main01.dart
The area of the rectangle is: 20
The perimeter of the rectangle is: 24

The area of the circle is: 157.079633
The perimeter of the circle is: 31.415927&lt;/pre&gt;Easy-peasey, but there is duplication in there that I might like to factor out into a series of functions:&lt;pre class="prettyprint"&gt;p_area(shape) {
  print("Area: " + shape.area());
}

p_perimiter() {
  print("Perimeter: " + this.perimeter());
}&lt;/pre&gt;Dart defines the &lt;code&gt;#source()&lt;/code&gt; directive to pull in arbitrary code.  Might I be able to do something like:&lt;pre class="prettyprint"&gt;class Circle {
  final num radius;
  Circle(this.radius);
  area() =&gt; 2 * Math.PI * this.radius * this.radius;
  perimeter() =&gt; 2 * Math.PI * this.radius;
  &lt;b&gt;#source('pretty_shapes.dart');&lt;/b&gt;
}
&lt;/pre&gt;Sadly no:&lt;pre class="prettyprint"&gt;➜  mixins git:(master) ✗ dart main02.dart
'/home/cstrom/repos/dart-site/examples/command_line/mixins/main02.dart': Error: line 1 pos 1: library handler failed: '/home/cstrom/repos/dart-site/examples/command_line/mixins/shapes02.dart': Error: line 28 pos 3: identifier expected
  #source('pretty_shapes.dart');
  ^

#import('shapes02.dart');
^&lt;/pre&gt;The closest that I can come is to source the libary in main, and then inject the functions into the constructor:&lt;pre class="prettyprint"&gt;#import('shapes02.dart');
&lt;b&gt;#source('pretty_shapes.dart');&lt;/b&gt;

main() {
&lt;b&gt;  var r = new Rectangle(2, 10, mixins:{
    'p_area':p_area, 'p_perimeter':p_perimeter'
  });&lt;/b&gt;
  r.p_area();
  print("");

  var c = new Circle(5);
  print("The area of the circle is: " + c.area());
  print("The perimeter of the circle is: " + c.perimeter());
  print("");
}
&lt;/pre&gt;The Rectangle class then needs to support the optional &lt;code&gt;mixins&lt;/code&gt; parameter.  The &lt;code&gt;noSuchMethod()&lt;/code&gt; method can then invoke the called method on the injected "mixin":&lt;pre class="prettyprint"&gt;#library('Super amazing shapes!');

class Rectangle {
  final num height, width;
  var _mixins;

  Rectangle(this.width, this.height, &lt;b&gt;[mixins]&lt;/b&gt;) {
&lt;b&gt;    _mixins = mixins;&lt;/b&gt;
  }
  area() =&gt; this.width * this.height;
  perimeter() =&gt; 2*this.width + 2*this.height;

&lt;b&gt;  noSuchMethod(String name, List args) {
    _mixins['p_area'](this);
  }&lt;/b&gt;
}
&lt;/pre&gt;The pretty_shapes library also needs to change such that the functions accept a shape argument, on which the corresponding methods are called (instead of calling them on &lt;code&gt;this&lt;/code&gt;):&lt;pre class="prettyprint"&gt;p_area(shape) {
  print("Area: " + shape.area());
}

p_perimeter(shape) {
  print("Perimeter: " + shape.perimeter());
}
&lt;/pre&gt;The result of running the script is now:&lt;pre class="prettyprint"&gt;➜  mixins git:(master) ✗ dart main02.dart
Area: 20
Perimeter: 24

The area of the circle is: 157.079633
The perimeter of the circle is: 31.415927&lt;/pre&gt;Of course, now I have traded one for of duplication for another.  I might try to solve this with inheritance from a "Mixinable" class:&lt;pre class="prettyprint"&gt;#library('Super amazing shapes!');

class Mixinable {
  var _mixins;

  noSuchMethod(String name, List args) {
    if (_mixins != null &amp;&amp; _mixins[name] != null) {
      _mixins[name](this);
    }
    else {
      throw new NoSuchMethodException(this, name, args);
    }
  }
}

class Rectangle extends Mixinable {
  final num height, width;

  Rectangle(this.width, this.height, [mixins]) {
    _mixins = mixins;
  }
  area() =&gt; this.width * this.height;
  perimeter() =&gt; 2*this.width + 2*this.height;
}

class Circle extends Mixinable {
  final num radius;

  Circle(this.radius, [mixins]) {
    _mixins = mixins;
  }
  area() =&gt; 2 * Math.PI * this.radius * this.radius;
  perimeter() =&gt; 2 * Math.PI * this.radius;
}&lt;/pre&gt;That will work, but... Since Dart only supports single inheritance, I cannot sub-class a "Shape" class if I decided it was necessary.  Also, injecting methods seems fraught with danger.  It really feels as though I am off the Dart rails here.&lt;br /&gt;
&lt;br /&gt;
Although not ideal, it is better than nothing.  Still, I think I will hold out hope for reflection to solve this for real—or at least a little better.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #263&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-6701369804125926998?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bA-ELmUO7BKrPFE-EvbjjzO2GJU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bA-ELmUO7BKrPFE-EvbjjzO2GJU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bA-ELmUO7BKrPFE-EvbjjzO2GJU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bA-ELmUO7BKrPFE-EvbjjzO2GJU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/osJMgFCaQuQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/6701369804125926998/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/dart-mixins.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6701369804125926998?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/6701369804125926998?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/osJMgFCaQuQ/dart-mixins.html" title="Dart (Pseudo) Mixins" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/dart-mixins.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8FRnk4eSp7ImA9WhRVFE4.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-9220847472163675162</id><published>2012-01-11T23:09:00.001-05:00</published><updated>2012-01-13T00:33:37.731-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-13T00:33:37.731-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Converting Complex Dart Apps to Javascript</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/import-include-and-real-dart-pages.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/dart-mixins.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Last night I had me a good old time making a Fibonacci page driven by &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt;.  At its heart, the page was pretty simple (calculate the Fibonacci number for a list of numbers, display the results on the page, time the whole thing in the console).  Simple, but making use of two cool Dart features: &lt;code&gt;#import()&lt;/code&gt; and &lt;code&gt;#source()&lt;/code&gt; to load libaries.&lt;br /&gt;
&lt;br /&gt;
Since Dart is not available in any major browsers, I had to run all of this in &lt;a href="http://japhr.blogspot.com/2012/01/dartium.html"&gt;my Dartium build&lt;/a&gt;.  Until Dart is supported in all major browsers, Dart applications will have to be compiled into Javascript.  That got me wondering as to how the compiler handles libraries.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, I cannot simply point the compiler, oddly named &lt;code&gt;frogc&lt;/code&gt;, at the web page containing the &lt;code&gt;main()&lt;/code&gt; Dart code:&lt;pre class="prettyprint"&gt;➜  timer git:(master) ✗ frogc index.html                  
unrecognized flag: "index.html"
fatal: no script provided to compile
Unhandled exception:
Compilation failed
 0. Function: '::main' url: '/home/cstrom/local/dart-sdk/lib/frog/minfrogc.dart' line:32 col:5
 1. Function: '::main' url: '/home/cstrom/local/dart-sdk/bin/frogc.dart' line:11 col:16&lt;/pre&gt;Bummer.&lt;br /&gt;
&lt;br /&gt;
So first up, I factor the &lt;code&gt;main()&lt;/code&gt; code block out of the web page:&lt;pre class="prettyprint"&gt;&amp;lt;html&gt;
  &amp;lt;body&gt;
    &amp;lt;h1&gt;Fibonacci!&amp;lt;/h1&gt;
    &amp;lt;div id="status"&gt;&amp;lt;/div&gt;
  &amp;lt;/body&gt;

  &amp;lt;script&gt;{}&amp;lt;/script&gt;
&lt;b&gt;  &amp;lt;script type="application/dart" src="main.dart"&gt;&amp;lt;/script&gt;&lt;/b&gt;
&amp;lt;/html&gt;&lt;/pre&gt;Next, I double-check that this still works in Dartium:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-GDkDIYIAamo/Tw5HOD9ROqI/AAAAAAAAC9Y/J4Keaigrs4c/s1600/01-dart_src.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="295" width="400" src="http://2.bp.blogspot.com/-GDkDIYIAamo/Tw5HOD9ROqI/AAAAAAAAC9Y/J4Keaigrs4c/s400/01-dart_src.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Yup, I even get a warning about an incorrect mime-type for my new &lt;code&gt;main.dart&lt;/code&gt; resource.  &lt;br /&gt;
&lt;br /&gt;
So now I ought to be able to compile the dart script into Javascript:&lt;pre class="prettyprint"&gt;➜  timer git:(master) ✗ frogc main.dart       
/home/cstrom/local/dart-sdk/lib/htmlimpl/htmlimpl.dart:23094:21: warning: a map literal takes one type argument specifying the value type
    _listenerMap = &lt;String, EventListenerList&gt;{};
                    ^^^^^^&lt;/pre&gt;Again, I get an error deep within &lt;code&gt;htmlimpl&lt;/code&gt;, but this time I know that &lt;a href="http://japhr.blogspot.com/2011/12/command-line-dart-and-frogc-wha.html"&gt;it can be safely ignored&lt;/a&gt;.  And indeed, I do have a brand-new, admittedly very large, &lt;code&gt;main.dart.js&lt;/code&gt; file:&lt;pre class="prettyprint"&gt;➜  timer git:(master) ✗ ls -ltrh
total 240K
-rw-rw-r-- 1 cstrom cstrom  342 2012-01-10 23:03 pretty_stopwatch.dart
-rw-rw-r-- 1 cstrom cstrom  227 2012-01-10 23:56 fib_printer.dart
-rw-rw-r-- 1 cstrom cstrom   66 2012-01-11 21:26 fib_printer.dart.js
-rw-rw-r-- 1 cstrom cstrom  240 2012-01-11 21:32 main.dart
-rw-rw-r-- 1 cstrom cstrom  169 2012-01-11 21:32 index.html
-rw-rw-r-- 1 cstrom cstrom 218K 2012-01-11 21:39 main.dart.js&lt;/pre&gt;The resultant Javascript version of my Dart code (which starts on line 4,266!) is actually quite readable:&lt;pre class="prettyprint"&gt;//  ********** Library A very pretty stop watch class **************
// ********** Code for PrettyStopwatch **************
function PrettyStopwatch() {}
PrettyStopwatch.start$ctor = function() {
  // Initializers done
  this.timer = new StopwatchImplementation.start$ctor();
}
PrettyStopwatch.start$ctor.prototype = PrettyStopwatch.prototype;
PrettyStopwatch.prototype.stop = function() {
  this.timer.stop();
  dart_core_print("Elapsed time: " + this.timer.elapsedInMs() + "ms");
}
PrettyStopwatch.prototype.stop$0 = PrettyStopwatch.prototype.stop;
// ********** Code for top level **************
//  ********** Library main **************
// ********** Code for top level **************
function main() {
  var list = [5, 40, 39, 32, 6, 41];
  var timer = new PrettyStopwatch.start$ctor();
  list.forEach$1(fib_printer);
  timer.stop$0();
}
function fib_printer(i) {
  var answer = fib(i), el = ElementWrappingImplementation.ElementWrappingImplementation$tag$factory('div');
  el.set$innerHTML(("fib(" + i + ") = ") + answer);
  html_get$document().query('#status').get$nodes().add(el);
}
function fib(i) {
  if (i &amp;lt; 2) return i;
  return fib(i - 2) + fib(i - 1);
}&lt;/pre&gt;The other 4,265 lines of core are the core Dart and dart:html Javascript implementations.  As for my code, I am thrilled to see that both the &lt;code&gt;#import()&lt;/code&gt; of my library code and the &lt;code&gt;#source()&lt;/code&gt; of my mixins are represented in the compiled Javascript.  Without resorting to &lt;a href="http://requirejs.org"&gt;require.js&lt;/a&gt; hackery there is no way to import/source files in Javascript, so bundling it all up into a single file is probably the way to go.  I must confess that I am pleased to see it already working this early on in the life-cycle of Dart.&lt;br /&gt;
&lt;br /&gt;
Anyhow, a couple of other things to note are the &lt;code&gt;#libary()&lt;/code&gt; argument in my Dart code:&lt;pre class="prettyprint"&gt;#library('&lt;b&gt;A very pretty stop watch class&lt;/b&gt;');

class PrettyStopwatch {
  // ...
}&lt;/pre&gt;Gets translated into comments in the compiled Javascript:&lt;pre class="prettyprint"&gt;//  ********** Library &lt;b&gt;A very pretty stop watch class&lt;/b&gt; **************
// ********** Code for PrettyStopwatch **************
function PrettyStopwatch() {}
//... &lt;/pre&gt;When I wrote that, I could not see an immediate purpose for the argument to &lt;code&gt;#libary()&lt;/code&gt;.  Now I know at least one: quality documentation in compiled Javascript.&lt;br /&gt;
&lt;br /&gt;
The other thing to note is that, in my Dart code, I &lt;code&gt;#source()&lt;/code&gt; the functions to be mixed in before the &lt;code&gt;main()&lt;/code&gt; code block:&lt;pre class="prettyprint"&gt;#import('dart:html');
#import('pretty_stopwatch.dart');
&lt;b&gt;#source('fib_printer.dart');&lt;/b&gt;
void main() {
  // ...
}&lt;/pre&gt;But in the resulting Javascript, the included functions, &lt;code&gt;fib_printer&lt;/code&gt; and &lt;code&gt;fib&lt;/code&gt;, are defined after the &lt;code&gt;main()&lt;/code&gt; function:&lt;pre class="prettyprint"&gt;// ********** Code for top level **************
//  ********** Library main **************
// ********** Code for top level **************
function main() {
  // ...
}
&lt;b&gt;function fib_printer(i) {
  // ...
}
function fib(i) {
  // ...
}&lt;/b&gt;&lt;/pre&gt;I cannot think of a reason that this might really matter, but thought it interesting nonetheless.&lt;br /&gt;
&lt;br /&gt;
Last of note is the difference between the Dart Fibonacci function:&lt;pre class="prettyprint"&gt;fib(i) {
  if (i &amp;lt; 2) return i;
  return fib(i-2) + fib(i-1);
}&lt;/pre&gt;And the Javascript equivalent:&lt;pre class="prettyprint"&gt;function fib(i) {
  if (i &amp;lt; 2) return i;
  return fib(i - 2) + fib(i - 1);
}&lt;/pre&gt;As I noted in my presentation last night to &lt;a href="http://bmoreonrails.org"&gt;B'more on Rails&lt;/a&gt;, Dart definitely feels familiar!&lt;br /&gt;
&lt;br /&gt;
The only thing left at this point is to run the app in a "normal" browser, which works brilliantly:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-5MQR63b0EOc/Tw5ZTTcx0aI/AAAAAAAAC9k/H4J-NuQ23aU/s1600/02-compiled_to_js.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="324" width="400" src="http://3.bp.blogspot.com/-5MQR63b0EOc/Tw5ZTTcx0aI/AAAAAAAAC9k/H4J-NuQ23aU/s400/02-compiled_to_js.png" /&gt;&lt;/a&gt;&lt;/div&gt;(&lt;a href="http://dart4hipsters.com/examples/timer/javascript.html"&gt;see for yourself&lt;/a&gt; on &lt;a href="http://dart4hipsters.com"&gt;Dart for Hipsters&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nice!  &lt;br /&gt;
&lt;br /&gt;
Having futzed with Dart for a couple of weeks, I can see myself growing to like it enough to build real apps in it and then compiling to Javascript.  Once &lt;code&gt;frogc&lt;/code&gt; improves to the point that the resultant Javascript is smaller (e.g. minified, core dart is hosted at google, etc), this could be very nice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #262&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-9220847472163675162?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rm0KwmLgwdwxyaLWlAQp-pP91VM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rm0KwmLgwdwxyaLWlAQp-pP91VM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rm0KwmLgwdwxyaLWlAQp-pP91VM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rm0KwmLgwdwxyaLWlAQp-pP91VM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/Biwo7N3uCik" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/9220847472163675162/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/converting-complex-dart-apps-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/9220847472163675162?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/9220847472163675162?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/Biwo7N3uCik/converting-complex-dart-apps-to.html" title="Converting Complex Dart Apps to Javascript" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-GDkDIYIAamo/Tw5HOD9ROqI/AAAAAAAAC9Y/J4Keaigrs4c/s72-c/01-dart_src.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/converting-complex-dart-apps-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IDQH47eyp7ImA9WhRVE0k.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-7458314127812981858</id><published>2012-01-10T23:59:00.001-05:00</published><updated>2012-01-11T23:12:51.003-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-11T23:12:51.003-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>#Import, #Include and Real Dart Pages</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/dart-isolates-for-speed.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/converting-complex-dart-apps-to.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
One of the more intriguing claims made by &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; 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 &lt;a href="http://requirejs.org"&gt;require.js&lt;/a&gt; to load libraries like a real language can.  I should be able to query and manipulate the DOM like jQuery.&lt;br /&gt;
&lt;br /&gt;
To Dartium!&lt;br /&gt;
&lt;br /&gt;
First, I need a web page.  I borrow my fibonacci solution from last night, but adopt it to work in a web page:&lt;pre class="prettyprint"&gt;&amp;lt;html&gt;
  &amp;lt;script&gt;{}&amp;lt;/script&gt;
  &amp;lt;body&gt;
    &amp;lt;h1&gt;Fibonacci!&amp;lt;/h1&gt;
    &amp;lt;div id="status"&gt;&amp;lt;/div&gt;
  &amp;lt;/body&gt;

  &amp;lt;script type="application/dart"&gt;
    #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 &amp;lt; 2) return i;
      return fib(i-2) + fib(i-1);
    }

  &amp;lt;/script&gt;
&amp;lt;/html&gt;&lt;/pre&gt;Starting from the top of that HTML, I need an empty script in current Dartium builds to ensure that Javascript / Dart engines are engaged:&lt;pre class="prettyprint"&gt;&amp;lt;script&gt;{}&amp;lt;/script&gt;&lt;/pre&gt;The following bit of HTML is fairly plain:&lt;pre class="prettyprint"&gt;&lt;code&gt;  &amp;lt;body&gt;
    &amp;lt;h1&gt;Fibonacci!&amp;lt;/h1&gt;
    &amp;lt;div id="status"&gt;&amp;lt;/div&gt;
  &amp;lt;/body&gt;&lt;/code&gt;&lt;/pre&gt;I will stick the results of my fibonacci lists into the &lt;code&gt;#status&lt;/code&gt; &lt;code&gt;&amp;lt;div&gt;&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Now comes the &lt;code&gt;&amp;lt;script type="application/dart"&gt;&lt;/code&gt; 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":&lt;pre class="prettyprint"&gt;&lt;code&gt;    #import('dart:html');
    #import('pretty_stopwatch.dart');&lt;/code&gt;&lt;/pre&gt;The important thing to note here is that &lt;code&gt;pretty_stopwatch.dart&lt;/code&gt; 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 &lt;code&gt;#import&lt;/code&gt; call. That is very modern indeed.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;main()&lt;/code&gt; 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:&lt;pre class="prettyprint"&gt;&lt;code&gt;    void main() {
      var list = [5, 40, 39, 32, 6, 41];

      var timer = new PrettyStopwatch.start();
      list.forEach(fib_printer);
      timer.stop();
    }&lt;/code&gt;&lt;/pre&gt;Of note in there is a little short-cut inside the &lt;code&gt;forEach&lt;/code&gt;.  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 &lt;code&gt;fib_printer&lt;/code&gt; where I could have used the wordier &lt;code&gt;(i) {fib_printer(i)}&lt;/code&gt;.  That is a nice little convenience that I plan on using quite a bit.&lt;br /&gt;
&lt;br /&gt;
Next, I make use of &lt;code&gt;dart:html&lt;/code&gt; to create a &lt;code&gt;&amp;lt;div&gt;&lt;/code&gt; tag, add the fibonacci answer to it, and add the whole thing to the list of nodes underneath the &lt;code&gt;#status&lt;/code&gt; element:&lt;pre class="prettyprint"&gt;&lt;code&gt;    fib_printer(i) {
      var answer = fib(i)
        , el = new Element.tag('div');

      el.innerHTML = "fib(${i}) = " + answer;
      document.query('#status').nodes.add(el);
    }&lt;/code&gt;&lt;/pre&gt;The remainder of the page is only last night's simple fibonacci calculator:&lt;pre class="prettyprint"&gt;&lt;code&gt;    fib(i) {
      if (i &amp;lt; 2) return i;
      return fib(i-2) + fib(i-1);
    }&lt;/code&gt;&lt;/pre&gt;And that's it! When I load the page, I see:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-iPTIJhny1AA/Tw0V-amAsvI/AAAAAAAAC9M/PFjItDYXEQQ/s1600/01-fibonacci_page.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="359" width="400" src="http://1.bp.blogspot.com/-iPTIJhny1AA/Tw0V-amAsvI/AAAAAAAAC9M/PFjItDYXEQQ/s400/01-fibonacci_page.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Last up tonight, I move those two fibonacci functions into their own Dart file:&lt;pre class="prettyprint"&gt;// 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 &amp;lt; 2) return i;
  return fib(i-2) + fib(i-1);
}&lt;/pre&gt;To get these in the original HTML, I need to "source" that library:&lt;pre class="prettyprint"&gt;&amp;lt;script type="application/dart"&gt;
    #import('dart:html');
    #import('pretty_stopwatch.dart');
&lt;b&gt;    #source('fib_printer.dart');&lt;/b&gt;
    void main() {
      var list = [5, 40, 39, 32, 6, 41];

      var timer = new PrettyStopwatch.start();
      list.forEach(fib_printer);
      timer.stop();
    }
  &amp;lt;/script&gt;
&lt;/pre&gt;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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #261&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-7458314127812981858?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mSa8zqktls8iIA3c8P3fS7UoYvw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mSa8zqktls8iIA3c8P3fS7UoYvw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mSa8zqktls8iIA3c8P3fS7UoYvw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mSa8zqktls8iIA3c8P3fS7UoYvw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/zetq_ZykZSQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/7458314127812981858/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/import-include-and-real-dart-pages.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7458314127812981858?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7458314127812981858?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/zetq_ZykZSQ/import-include-and-real-dart-pages.html" title="#Import, #Include and Real Dart Pages" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-iPTIJhny1AA/Tw0V-amAsvI/AAAAAAAAC9M/PFjItDYXEQQ/s72-c/01-fibonacci_page.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/import-include-and-real-dart-pages.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8AQnY4fyp7ImA9WhRVEkU.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-3762115608502832375</id><published>2012-01-09T23:59:00.002-05:00</published><updated>2012-01-11T08:17:23.837-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-11T08:17:23.837-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Dart Isolates for Speed</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/libraries-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/import-include-and-real-dart-pages.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Try as I might, I cannot avoid the dreaded fibonacci sequence example when working with &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; &lt;a href="http://api.dartlang.org/dart_core/Isolate.html"&gt;Isolates&lt;/a&gt;.  I need a function that is going to take a little while so that I can compare the timing of a long running series of calculations with and without isolates. &lt;br /&gt;
&lt;br /&gt;
So fibonacci, it is.  In Dart, this looks like:&lt;pre class="prettyprint"&gt;fib(i) {
  if (i &lt; 2) return i;
  return fib(i-2) + fib(i-1);
}&lt;/pre&gt;
That quite similar to just about every other fibonacci implemented in any other language.  Now to make use of it.  I take a series of six numbers, calculate the fibonnaci for each and print out the timing results:&lt;pre class="prettyprint"&gt;#import('pretty_stopwatch.dart');

main() {
  var list = [5, 40, 39, 32, 6, 41];

  var timer = new PrettyStopwatch.start();
  var answers = {};
  list.forEach((i) {
    answers[i] = fib(i);
    print("fib(" + i + ") = " + answers[i]);
  });
  timer.stop();
}

fib(i) {
  if (i &amp;lt; 2) return i;
  return fib(i-2) + fib(i-1);
}&lt;/pre&gt;(&lt;a href="http://try.dartlang.org/s/Qskm"&gt;try.dartlang.org&lt;/a&gt;)




The result is:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer06.dart
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 11337ms&lt;/pre&gt;11.3 seconds.  Pity my poor MacBook Air for not being faster.  But even my early model Air has two cores, which means that, if I split the work across two isolates, I ought to halve the time it takes to calculate all six.  

I am using some non-DRY code, but it should serve its purpose to generate some numbers:&lt;pre class="prettyprint"&gt;#import('pretty_stopwatch.dart');

main() {
  final fib_solver = new FibSolver();

  var list = [5, 40, 39, 32, 6, 41];

  // Spawn isolate #1 for the first 3 elements
  var timer1 = new PrettyStopwatch.start();
  fib_solver.spawn().then((port) {
    port.call(list.getRange(0,3)).receive((message, replyTo) {
      message.forEach((i, answer) {
        print("fib(" + i + ") = " + answer);
      });
      timer1.stop();
    });
  });

  // Spawn isolate #2 for the last 3 elements
  var timer2 = new PrettyStopwatch.start();
  fib_solver.spawn().then((port) {
    port.call(list.getRange(3,3)).receive((message, replyTo) {
      message.forEach((i, answer) {
        print("fib(" + i + ") = " + answer);
      });
      timer2.stop();
    });
  });
}

// Isolate class for solving lists of fibonacci numbers
class FibSolver extends Isolate {
  main() {
    var answers = {};

    port.receive((message, replyTo) {
      message.forEach((i) {
        answers[i] = fib(i);
        // print("fib(" + i + ") = " + answers[i]);
      });

      replyTo.send(answers);
    });
  }
}

fib(i) {
  if (i &amp;lt; 2) return i;
  return fib(i-2) + fib(i-1);
}&lt;/pre&gt;This results in:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer07.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
Elapsed time: 6554ms
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 6856ms&lt;/pre&gt;It looks like both complete in around 6.8 seconds.

Rather than run the time for each isolate individually, I would like to know when both have completed.  Since I am not DRYing my code well here, I need two booleans—one to track each of the two isolates.  When both have completed, I mark a timer Completer as complete, triggering the timer to stop and print out the results:&lt;pre class="prettyprint"&gt;main() {
  final fib_solver = new FibSolver();

  var list = [5, 40, 39, 32, 6, 41];

  var timer = new PrettyStopwatch.start()
    , completer = new Completer();

&lt;b&gt;  completer.future.then((args) {
    timer.stop();
  });

  var done1 = false
    , done2 = false;&lt;/b&gt;

  fib_solver.spawn().then((port) {
    port.call(list.getRange(0,3)).receive((message, replyTo) {
      message.forEach((i, answer) {
        print("fib(" + i + ") = " + answer);
      });
&lt;b&gt;      done1 = true;
      if (done2) completer.complete(true);&lt;/b&gt;
    });
  });


  fib_solver.spawn().then((port) {
    port.call(list.getRange(3,3)).receive((message, replyTo) {
      message.forEach((i, answer) {
        print("fib(" + i + ") = " + answer);
      });
&lt;b&gt;      done2 = true;
      if (done1) completer.complete(true);&lt;/b&gt;
    });
  });
}&lt;/pre&gt;(&lt;a href="http://try.dartlang.org/s/424n"&gt;try.dartlang.org&lt;/a&gt;)

I won't win any style points for that, but it does the trick, I now have accurate timing information for splitting the sequence of calculations across two isolates (each of which gets a core on my Air).  The results:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer08.dart
fib(32) = 2178309
fib(6) = 8
fib(41) = 165580141
fib(5) = 5
fib(40) = 102334155
fib(39) = 63245986
Elapsed time: 6375ms&lt;/pre&gt;6.4 seconds.  Not quite half, but that is to be expected since it was not an exact divide of calculations and there is some overhead involved in building isolates.

If nothing else, I finally have a decent measure of how useful Isolates can be.

&lt;span style="color: #ccc"&gt;Day #260&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-3762115608502832375?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ecu89tjpv6Lffoq_hVQ7pgzHmu4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ecu89tjpv6Lffoq_hVQ7pgzHmu4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ecu89tjpv6Lffoq_hVQ7pgzHmu4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ecu89tjpv6Lffoq_hVQ7pgzHmu4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/gHlRi0vyfAs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/3762115608502832375/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/dart-isolates-for-speed.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/3762115608502832375?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/3762115608502832375?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/gHlRi0vyfAs/dart-isolates-for-speed.html" title="Dart Isolates for Speed" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>7</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/dart-isolates-for-speed.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcGR3c_eip7ImA9WhRVEUo.&quot;"><id>tag:blogger.com,1999:blog-581197352358126527.post-7025618640577800737</id><published>2012-01-08T23:51:00.001-05:00</published><updated>2012-01-10T00:23:46.942-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-10T00:23:46.942-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dartlang" /><category scheme="http://www.blogger.com/atom/ns#" term="chain" /><title>Libraries in Dart</title><content type="html">&lt;a href="http://japhr.blogspot.com/2012/01/classes-names-and-stopwatches-in-dart.html"&gt;&amp;lsaquo;prev&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2011/12/why-dart.html"&gt;My Chain&lt;/a&gt; | &lt;a href="http://japhr.blogspot.com/2012/01/dart-isolates-for-speed.html"&gt;next&amp;rsaquo;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I built myself a sweet little &lt;a href="http://dartlang.org"&gt;Dart&lt;/a&gt; code timer class last night. Tonight, I am going to make use of it to see how over-isolating things in Dart affects process speed.  But first up, I need to move my class timer out into a library that can be included in subsequent iterations as I try to improve my time.&lt;br /&gt;
&lt;br /&gt;
Reading through the &lt;a href="http://www.dartlang.org/docs/spec/index.html"&gt;spec&lt;/a&gt;, it seems like a Dart library is a simple enough thing.  I only need create a separate file with a top level class (or similar declaration) and then &lt;code&gt;#import()&lt;/code&gt; it.  So, the separate file is:&lt;pre class="prettyprint"&gt;// pretty_stop_watch.dart
class PrettyStopwatch {
  // last night's code here...
}&lt;/pre&gt;Then, in my main dart file:&lt;pre class="prettyprint"&gt;// timer03.dart
#import('pretty_stop_watch.dart');&lt;/pre&gt;However, when I run this, I am greeted with:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer03.dart
'/home/cstrom/repos/dart-site/examples/command_line/timer03.dart': Error: line 1 pos 1: library handler failed: '/home/cstrom/repos/dart-site/examples/command_line/pretty_stop_watch.dart': Error: line 1 pos 1: '#library' expected
class PrettyStopwatch {
^

#import('pretty_stop_watch.dart');
^&lt;/pre&gt;OK.  It seems that I need a bit more than just a class declaration.  Let's try a &lt;code&gt;#library();&lt;/code&gt; declaration at the top of the library file.  I am not sure what to put in there, so I try the filename, minus the extension:&lt;pre class="prettyprint"&gt;#library('pretty_stop_watch');

class PrettyStopwatch {
  // last night's code here...
}&lt;/pre&gt;Now, when I try to run the main dart code, I get:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer03.dart
Unable to find entrypoint: static .main()&lt;/pre&gt;Ew. &lt;br /&gt;
&lt;br /&gt;
Well, if you want a static &lt;code&gt;main()&lt;/code&gt;, I can oblige:&lt;pre class="prettyprint"&gt;#library('pretty_stop_watch');

main() {}

class PrettyStopwatch {
  // last night's code here...
}&lt;/pre&gt;When I run the code now, I get now errors.  So that is progress.&lt;br /&gt;
&lt;br /&gt;
To actually use the &lt;code&gt;PrettyStopwatch&lt;/code&gt; class, I add the isolate-based doomsday solver into &lt;code&gt;timer03.dart&lt;/code&gt;:&lt;pre class="prettyprint"&gt;// timer03.dart
#import('pretty_stop_watch.dart');

main() {
  // spawn the isolate solver
}

class DoomsDay extends Isolate { /* ... */ }

class DoomsDayFinder extends Isolate { /* ... */ }&lt;/pre&gt;Unfortunately, now I get the following error when I try to time with my library:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer03.dart
'/home/cstrom/repos/dart-site/examples/command_line/timer03.dart': Error: line 3 pos 1: 'main' is already defined
main() {
^
&lt;/pre&gt;Well, of course main is already defined.  You insisted that I define it you stupid compiler!  Oh wait...&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Maybe&lt;/i&gt; the compiler was telling me that I needed a &lt;code&gt;main()&lt;/code&gt; method in my primary file, not in my library.  Duh.&lt;br /&gt;
&lt;br /&gt;
I leave the main &lt;code&gt;timer03.dart&lt;/code&gt; script as-is and remove the &lt;code&gt;main()&lt;/code&gt; method from &lt;code&gt;pretty_stop_watch.dart&lt;/code&gt;:&lt;pre class="prettyprint"&gt;#library('pretty_stop_watch');

class PrettyStopwatch {
  // last night's code here...
}&lt;/pre&gt;And that does it.  Now when I run the code, I am returned a list of all the years in the 21st century in which the &lt;a href="http://japhr.blogspot.com/2012/01/isolate-doomsday-in-dart.html"&gt;doomsday&lt;/a&gt; is a Wednesday, followed by timing information:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer03.dart
2001
2007
2012
2018
2029
2035
2040
2046
2057
2063
2068
2074
2085
2091
2096
Elapsed time: 2779ms&lt;/pre&gt;I have already broken Dart importing in a couple of different ways.  I wonder if there are other things I can break.  For instance, that string that I supplied to the &lt;code&gt;#library()&lt;/code&gt; call—what happens when I change that to something other than the filename?&lt;pre class="prettyprint"&gt;&lt;b&gt;#library('asdf');&lt;/b&gt;

class PrettyStopwatch {
 // ...
}&lt;/pre&gt;As it turns out, nothing.  The code still runs just fine.  &lt;br /&gt;
&lt;br /&gt;
In the end, I opt for a somewhat descriptive title for the library:&lt;pre class="prettyprint"&gt;#library('A very pretty stop watch class');
// ...&lt;/pre&gt;It seems silly to duplicate the classname or the filename here. I was able to find &lt;code&gt;#library()&lt;/code&gt; in the spec (scrolling helps), but it offers no suggestions for what to use here.&lt;br /&gt;
&lt;br /&gt;
One other thing that I try is uploading my pretty stop watch library to &lt;a href="https://raw.github.com/dart4hipsters/dart4hipsters.github.com/master/examples/lib/pretty_stopwatch.dart"&gt;github&lt;/a&gt; in the hopes of importing it over the network.  This, however does not work from the command line:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer04.dart
'/home/cstrom/repos/dart-site/examples/command_line/timer04.dart': Error: line 1 pos 1: library handler failed: Unable to open file: /home/cstrom/repos/dart-site/examples/command_line/https://raw.github.com/dart4hipsters/dart4hipsters.github.com/master/examples/lib/pretty_stopwatch.dart
#import('https://raw.github.com/dart4hipsters/dart4hipsters.github.com/master/examples/lib/pretty_stopwatch.dart');
^&lt;/pre&gt;Nor does it work on &lt;a href="http://try.dartlang.org/s/RHYn"&gt;try.dartlang.org&lt;/a&gt;.  I was none too sure about either (although it would have been cool if it had worked).  Hopefully it will work when I try this out in Dartium another day.&lt;br /&gt;
&lt;br /&gt;
Anyhow, I have my very excellent stop watch class factored out into a class library.  I also see that my isolate-intensive doomsday solver is taking 2.8 seconds.  Let's use my stopwatch class to time a non-isolate solution:&lt;pre class="prettyprint"&gt;#import('pretty_stopwatch.dart');

main() {
  var century = 2000
    , matching_years = [];

  var timer = new PrettyStopwatch.start();
  for (var i=0; i &amp;lt;100; i++) {
    var year = century + i
      , doomsday = find_doomsday_for(year);

    if (doomsday == 'Wed') matching_years.add(year);
  }
  for (var year in matching_years) print(year);
  timer.stop();
}

find_doomsday_for(year) {
  var march1 = new Date(year, 3, 1, 0, 0, 0, 0)
    , doom = march1.subtract(new Duration(1)).weekday
    , dow = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];

  return dow[doom];
}&lt;/pre&gt;(&lt;a href="http://try.dartlang.org/s/Hdsl"&gt;try.dartlang.org&lt;/a&gt; with PrettyStopwatch embedded)&lt;br /&gt;
&lt;br /&gt;
The result?  A complete denouncement of my isolate approach:&lt;pre class="prettyprint"&gt;➜  command_line git:(master) ✗ dart timer05.dart
2001
2007
2012
...
2091
2096
Elapsed time: 49ms&lt;/pre&gt;Admittedly, 49 milliseconds is slightly better than 2.8 seconds, but this is not an indictment of isolates, just an indictment of the appropriateness of using them to solve a fairly simple problem like this.&lt;br /&gt;
&lt;br /&gt;
This will do for a stopping point today.  Up tomorrow: hopefully finding a more appropriate use of Isolates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: #ccc"&gt;Day #259&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/581197352358126527-7025618640577800737?l=japhr.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/h75qcNdKKZuh3hm7029fz1YPOic/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/h75qcNdKKZuh3hm7029fz1YPOic/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/h75qcNdKKZuh3hm7029fz1YPOic/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/h75qcNdKKZuh3hm7029fz1YPOic/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JaphrByChrisStrom/~4/l-RhVeSZ8Cw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://japhr.blogspot.com/feeds/7025618640577800737/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://japhr.blogspot.com/2012/01/libraries-in-dart.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7025618640577800737?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/581197352358126527/posts/default/7025618640577800737?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JaphrByChrisStrom/~3/l-RhVeSZ8Cw/libraries-in-dart.html" title="Libraries in Dart" /><author><name>Chris Strom</name><uri>https://profiles.google.com/117928918793969810642</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-Eqo-OrmZumI/AAAAAAAAAAI/AAAAAAAABmU/rmOK5v87M5w/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://japhr.blogspot.com/2012/01/libraries-in-dart.html</feedburner:origLink></entry></feed>

