Monday, January 30, 2012

Custom Events in Dart

‹prev | My Chain | next›

I have a deadline for the alpha release for Dart for Hipsters, 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.

Last night I got started breaking my Ajax based Dart application into real View classes (somewhat along the lines of Backbone.js). Today, I hope to extract collection code from my view into a proper collection class.

The heart of the collection, the fetching from the backend datastore, I can already do:
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);

    // How to tell the view that I'm done?
  }
}
But how can I communicate to my view that the collection has loaded new data?

I would like to instantiate a collection and a collection view something along the lines of:
  var my_comics_collection = new ComicsCollection()
    , comics_view = new ComicsCollectionView(
        el:'#comics-list',
        collection: my_comics_collection
      );

  my_comics_collection.fetch();
In the collection view, I could then subscribe to the collection view's on-load event:
  ComicsCollectionView([el, collection]) {
    this.el = document.query(el);
    this.collection = collection;

    collection.on.load.add((event) {
      render();
    });
  });
To get that to work, I will at least need an on getter in the Collection:
class ComicsCollection {
  var list;
  var get on;

  ComicsCollection() {
    on = new CollectionEvents();
  }
}
I could probably re-use one of the DOM Events classes here, but it is not too hard to define my own:
class CollectionEvents implements Events {
  var load_list;

  CollectionEvents() {
    load_list = new CollectionEventList();
  }

  get load() {
    return load_list;
  }
}
I defined a load getter that returns an EventList object. This CollectionEventList class that I define will be the thing that holds event listeners. It needs to define two methods: add() to add listeners and dispatch() to send events to all listeners:
class CollectionEventList implements EventListenerList {
  var listeners;

  CollectionEventList() {
    listeners = [];
  }

  add(fn) {
    listeners.add(fn);
  }

  bool dispatch(Event event) {
    listeners.forEach((fn) {fn(event);});
    return true;
  }
}
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:
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();
    });

    collection.on.load.add((event) {
      print("This really did fire in response to a custom event");
    });

    _attachUiHandlers();
  }

  // ...
}
And indeed, it does work:


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.


Day #282

Psuedo View Classes in Dart

‹prev | My Chain | next›

Today, I think, I am in need of some code re-organization. Currently my simple CRUD-over-XHR Dart application looks like:
#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]) { /* ... */ }
That's quite a mess that I have made for myself.

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 load_comics() entry point in main():
main() {
  load_comics();
}
I replace that, because I lack imagination, with a very Backbone looking object:
main() {
  var comics = new ComicsCollectionView('#comics-list');
  comics.render();
}
Now to make that work...

I am going to do this entirely in a separate class library, so I make a ComicsCollectionView.dart file with the following contents:
#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);
  }
}
I declare my el 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 'dart:html'). Then I expose a simple render() method that serves as tracer bullets for where I need to go next.

Loading it up in the browser, I see that I am in OK shape so far:


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:
class ComicsCollectionView {
  var get el;
  var get collection;

  ComicsCollectionView(target_el) {
    el = document.query(target_el);
    collection = [];
  }

  render() { /* ... */ }
}
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:
  render() {
    _ensureCollectionLoaded();
    el.innerHTML = template(collection);
  }
The template() method is taken directly from the old procedural code:
  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 """
      <li id="${comic['id']}">
        ${comic['title']}
        (${comic['author']})
        <a href="#" class="delete">[delete]</a>
      </li>
    """;
  }
As for the _ensureCollectionLoaded() method, I again adopt the procedural code, but add a guard clause to prevent calling the method if it has already been loaded:

  var _load_requested = false;

  _ensureCollectionLoaded() {
    if (_load_requested) return;
    _load_requested = true;

    var req = new XMLHttpRequest();

    req.on.load.add(_handleOnLoad);
    req.open('get', '/comics', true);
    req.send();
  }
And lastly, I define the _handleOnLoad() callback method. In here, I finally assign the collection to a non-empty array:
  _handleOnLoad(event) {
    var request = event.target;

    // TODO trigger an event for which the view can listen and render
    collection = JSON.parse(request.responseText);

    render();
  }
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.

Once I have the collection, I re-invoke render. This will by-pass _ensureCollectionLoaded() 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:


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.


Day #281

Sunday, January 29, 2012

Removing DOM Elements with Dart (A Tale of Null)

‹prev | My Chain | next›

For the next couple of days, I hope to keep it simple as I push toward a usable alpha release for Dart for Hipsters. While mucking about with my Dart sample application, I notice that cancelling the create form was not removing the form element from the page.

To remove the element, I had been:
if (form_div) form_div.remove();
That is not how the removeChild() works in Javascript (operates on a parent node, removing the specified child). I had tried working off of the API reference for Dart's remove(), which does not require an argument.

It may not require an argument, but it does state that it renames removeChild(), which would seem to indicate that it does operate on the parent. So I give it a try:
if (form_div) form_div.parent.remove(form_div);
But that fails to work as well.

OK, this is getting a bit annoying. When annoying, break it down to simplest case, I add a test_remove() method:
main() {
  test_remove();
  // ...
}

test_remove() {
  var test_div = new Element.html('<div id="test"/>');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
  test_div.parent.remove(test_div);
}
For that, I get a not-too-helpful backtrace:
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
So there is no remove() 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:
test_remove() {
  var test_div = new Element.html('<div id="test"/>');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
  test_div.remove();
}
And, indeed that does work. But wait, why did that fail to remove an element in my original version?
if (form_div) form_div.remove();
Ah, dang it. I have a conditional in there. Sure enough, if I switch my test case to include that conditional:
test_remove() {
  var test_div = new Element.html('<div id="test"/>');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
  if (test_div) test_div.remove();
}
Then the test DIV is not removed:


It turns out that Dart very much wants a boolean in its conditionals. Lacking a conditional, it would appear to assume false. I cannot say that I am a fan of this, especially since the only resolution seems to be comparing to null:
test_remove() {
  var test_div = new Element.html('<div id="test"/>');
  document.body.nodes.add(test_div);

  test_div = document.query('#test');
  if (test_div != null) test_div.remove();
}
Ew. Not even the old !!test_div trick works. I seem to be stuck with this less than desirable null comparison.

I may not like this conditional structure (hopefully that can change), but I do much prefer the simple remove() in Dart to the traditional child.parent.removeChild(child) dance. All-in-all, I am willing to call this a net win for Dart. But it's a narrow win.

Day #280

Saturday, January 28, 2012

Dart HTML Templates and insertAdjacentElement

‹prev | My Chain | next›

Picking back up with my web app now that my laptop is back (yay!), tonight I would like to get back to my Dart web application. I hope to figure out how to handle checkbox elements in my form, but first, I need to get it displaying (again).

The form is now in a template method:
form_template([graphic_novel]) {
  return """
<form action="comics" id="new-comic-form">
<p>
<label>Title<br/>
<input type="text" name="title" id="comic-title"/>
</label></p>

<p>
<label>Author<br/>
<input type="text" name="author" id="comic-author"/>
</label></p>

<p>Format
<p>
<label>
<input type="checkbox" name="format" value="tablet" id="comic-table"/>
Tablet</label></p>
<p>
<label>
<input type="checkbox" name="format" value="dead-tree" id="comic-dead-tree"/>
Dead Tree</label></p>
</p>

<p>
<input type="submit" value="Bazinga!"/></p>

</form>
""";
}
To insert that into that DOM, I need the Dart equivalent of jQuery's prepend(), append(), before(), or after(). Looking through the API reference for Element, however, I do not see anything of the sort. I do come across an odd little beastie named insertAdjacentElement.

I had never heard of that one, but apparently insertAdjacentElement is an Internet Explorer thing. Instead of invoking before(), after, etc. on an element, I am supposed to invoke insertAdjacentElement() with the first argument of "beforeBegin", "afterBegin", "beforeEnd", or "afterEnd". Ew.

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:
enable_add_form(event) {
  final form_div = _ensure_add_form('#add-comic-form');

  // effect and handlers here
}
Then, I create a new <div> tag with that selector and insert the result of the form template:
_ensure_add_form(id_selector) {
  var form_div = document.query(id_selector);
  if (form_div) form_div.remove();

  form_div = new Element.html("""
<div id="$id_selector">
${form_template()}
</div>
""");

  document.body.insertAdjacentElement('beforeEnd', form_div);

  return form_div;
}
I do rather like the string interpolation that is possible in Dart. It is wonderful for working with strings.

I really do not care for that instertAdjacentElement() method. It is way too long which does not lend itself to clear intent. It does work, but... no.

So instead, I stick with the add() method available to nodeList objects:
_ensure_add_form(id_selector) {
  var form_div = document.query(id_selector);
  if (form_div) form_div.remove();

  form_div = new Element.html("""
<div id="$id_selector">
${form_template()}
</div>
""");

  document.body.nodes.add(form_div);

  return form_div;
}
Hopefully the HTML API will continue to evolve. That insertAjacentElement() is just crazy noisy. Fortunately, the add() method covers the primary use-case of the various jQuery DOM manipulation methods.

Regardless, the ability to perform string interpolation and the support for multi-line strings in Dart is a big win.


Day #279

Friday, January 27, 2012

Regular Expressions in Dart

‹prev | My Chain | next›

Up tonight, I am going to explore regular expressions in Dart. 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 matches() or test() is a string method or a regular expression method.

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.

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:
  set greeting(greeting) {
    var parts = greeting.split(',');

    if (parts.length == 2) {
      _greeting_opening = parts[0];
      name = parts[1].replaceAll(' ', '').replaceAll('!', '');
    }
    else {
      _full_greeting = greeting;
    }
  }
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 _greeting_opening and name to the two parts. The second part, in particular is painful since I have to strip spaces and punctuation.

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.

The regular expression that ought to cover both cases is: /^(.+)\s*,\s*([\w\s]+)\W?$/. 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 (^) all the way up to the last comma, ignoring any space around the comma (\s*,\s*). The period in (.+) matches any character and the plus indicates one or more of them.

The second part of the string in which I am interested starts after the comma and any spaces (\s*,\s*). Here I try to match one or more characters or spaces: ([\w\s]+). I match any number of those characters until the end of the string ($) with the exception of a possible non-alphanumeric at the end of the line (\W?).

So let's see how this works in Dart. Regular expressions in Dart are built with the RegExp class. I try this against my default case:
main() {
  var matcher = new RegExp('^(.+)\s*,\s*([\w\s]+)\W?$');

  matcher.allMatches("Howdy, Bob!").forEach((m) {
    print(m[0]);
  });
}
I am not quite sure about the allMatches() usage--I am just trying that as my first attempt. It hardly matters because I am greeted by:
$ 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?$');
                                                     ^
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.

The API reference for RegExp puts an at sign before strings in RegExp's. Perhaps that prevents interpolation? There is one way to find out:
main() {
  var matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  matcher.allMatches("Howdy, Bob!").forEach((m) {
    print(m[0]);
  });
}
That does appear to prevent interpolation because I now get output:
$ dart regexp.dart
Howdy, Bob!
Aha! I get allMatches() 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 firstMatch. 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:
main() {
  var matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  matcher.firstMatch("Howdy, Bob!").tap((m) {
    print(m[1]);
    print(m[2]);
  });
}
This results in:
$ 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
Aw, man! No tap() in Dart? Say it ain't so!

Ah well, I can manage with:
main() {
  final matcher = new RegExp(@'^(.+)\s*,\s*([\w\s]+)\W?$');

  var m = matcher.firstMatch("Howdy, Bob!");
  print(m[1]);
  print(m[2]);
}
This results in:
$ dart regexp.dart
Howdy
Bob
Trying this out against the very challenging "Yo, yo, yo, Alice!":
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]);
}
I find:
$ dart regexp.dart                                  ~/repos/dart-book/samples
Howdy
Bob
Yo, Yo, Yo
Alice
Hunh. I think I might like that. That makes sense and I can definitely see myself remembering how to use those.

What about the match vs. test from Javascript? It seems that Dart improves on that. Instead of test, Dart uses contains. It still uses the matches() method on regular expressions. I try this out with a generalized version of my regular expression exploration code:
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('');
}
I have also added a new string, "Hey. You.", which should not match. And indeed it does not:
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
(try.dartlang.org)


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 contains() method, which is analogous to the silly test()). It may not be Perl, and it would be nice if there were regular expression literals, but this is pretty darn nice.

Day #278

Thursday, January 26, 2012

Dart Setters and Getters

‹prev | My Chain | next›

I remain stuck without a proper web development environment (c'mon Apple geniuses!), so tonight I continue to explore some Dart 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.

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:
var bob = new Person("Bob");
bob.greeting(); // => "Howdy, Bob!"
In Dart, we should be able to do something like:
var bob = Person.new("Bob");
bob.greeting; // => "Howdy, Bob!"
It is a simple enough thing, but over the long haul, removing parenthesis can only help with readability / maintainability.

So let's see if I know how to do this:
class Person {
  var name;
  var _greeting_opening = "Howdy";

  Person(this.name);

  get greeting() => "${_greeting_opening}, ${name}!";
}
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.

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 () => function syntax.

To use this class, I print out the greeting to two different people:
main() {
  var bob = new Person("Bob")
    , alice = new Person("Alice");

  print(bob.greeting);
  print(alice.greeting);
}
Running this results in:
$ dart setters_getters.dart
Howdy, Bob!
Howdy, Alice!
What I really like about this is that I do not have to follow a convention for these beasties (e.g. getGreeting, setGreeting). I never stick with whatever convention I start and end up with way too much confusion over a simple thing.

Setting things is similarly easy in Dart. In the class defintion, I need to use set instead of get. The usage of setters looks like any other property being assigned:
bob.greeting = "Yo, Bob!";
To make this work, the class would then need the set method:
class Person {
  var name;
  var _greeting_opening = "Howdy"
    , _full_greeting;

  Person(this.name);

  get greeting() {
    (_full_greeting != null) ?
      _full_greeting :
      "${_greeting_opening}, ${name}!";
  }
  set greeting(greeting) {
    _full_greeting = greeting;
  }
}
I have introduced a new, private instance variable _full_greeting. If set, the greeting getting will use this as the return value, otherwise it will stick with the regular "Howdy <<your name here>>!" version.

When I run this code:
main() {
  var bob = new Person("Bob")
    , alice = new Person("Alice");

  print(bob.greeting);
  print(alice.greeting);

  bob.greeting = "Yo, Bob!";
  print(bob.greeting);
}
I am greeted with:
null
null
null
Ah. I missed a return statement:
class Person {
  var name;
  var _greeting_opening = "Howdy"
    , _full_greeting;

  Person(this.name);

  get greeting() {
    return (_full_greeting != null) ?
      _full_greeting :
      "${_greeting_opening}, ${name}!";
  }
  set greeting(greeting) {
    _full_greeting = greeting;
  }
}
Now, I get:
Howdy, Bob!
Howdy, Alice!
Yo, Bob!
Of course, the real fun starts when you begin making calculations based on setters:
  set greeting(greeting) {
    var parts = greeting.split(',');

    if (parts.length == 2) {
      _greeting_opening = parts[0];
      name = parts[1].replaceAll(' ', '').replaceAll('!', '');
    }
    else {
      _full_greeting = greeting;
    }
  }
Running the following:
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);
}
Results in:
Howdy, Bob!
Howdy, Alice!
Yo, Fred!
Fred
Yo, yo, yo, Alice!
Alice
(try.dartlang.org)


There is some definite power there.


Day #276

Wednesday, January 25, 2012

Singletons via Factories in Dart

‹prev | My Chain | next›

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 Dart internals. Specifically, I am going to play with factory constructors.

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.

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 Foo with a property of bar. If I create two instances of the singleton Foo, then both should have the same value for bar.

In other words, both of the following statements should have the same value for bar:
main() {
  final foo1 = new Foo("bar1")
      , foo2 = new Foo("bar2");

  print("foo1 is: ${foo1.bar}");
  print("foo2 is: ${foo2.bar}");
}
If I implement the Foo class correctly, then the output should be:
foo1 is: bar2
foo2 is: bar2
So let's take a look at the factory constructor for this beast:
class Foo {
  var bar;
  static Foo instance;

  factory Foo(name) {
    if (instance == null) {
      instance = new Foo._internal(name);
    }
    return instance;
  }

  Foo._internal(this.bar);
}
Starting from the bottom, the Foo._internal(this.bar) line is a constructor. The underscore in the name is a convention for a private constructor. By using this.bar as the argument in the constructor, I am saying that any arguments supplied should be used to set the this.bar property.

That is, the following:
var internal = new Foo._internal("internal");
print("internal is: ${internal.bar}");
Should produce:
internal is: internal
Moving up in the class, the factory is defined as:
  factory Foo(name) {
    if (instance == null) {
      instance = new Foo._internal(name);
    }
    return instance;
  }
Just as with my internal construtor, I accept a single argument which will be used to set the bar property. If the static/class property instance 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.

When I run the following:
main() {
  final bar1 = new Foo("bar1")
      , bar2 = new Foo("bar2");

  print("bar1 is: ${bar1.bar}");
  print("bar2 is: ${bar2.bar}");
}
I get the following output:
bar1 is: bar1
bar2 is: bar1
So indeed, I do have my Singleton factory working as desired. Nice.

Day #276

Tuesday, January 24, 2012

How Not to Modify Dart Classes

‹prev | My Chain | next›

Yesterday, I was able to make a a decent start at a delegating event listener. The format
the listener ended up looking like:
  attach_handler(list_el, 'click .delete', (event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });
As with jQuery delegated events, that is a fairly compact, literate
syntax. Under the list element (list_el), I establish a listener for click
events on '.delete' elements. Since this is a delegated listener, this works for '.delete'
elements present now as well as any added later. The actual callback fired when the 'click
.delete' event is seen is a call to my XHR delete that, upon success, removes the parent LI
element.

That works, but it is a procedural approach. Ideally, I would like to add a delegated
listener something like:
  list_el.on['click .delete'].add((event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });
If this were Ruby, I could re-open the Events class and redefine the
on getter:
class Events {
  EventListenerList operator [](String type) {
    document.query
}
I cannot even compile that, however, without getting a redefinition error.

Hrm.. perhaps if I try with the implementation?
class EventsImplementation {
  EventListenerList operator [](String type) {
    document.query('#status').innerHTML = 'foo';
  }
}
Well, that compiles, but it has no effect. The default implementation of the on[] operator still kicks in.

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() directly on the EventsImplementation class:
class EventsImplementation {
  attach_handler(event_handler, fn) {
    document.query('#status').innerHTML = 'foo';
  }
}
Then, I invoke this with:
list_el.on.attach_handler('click .delete', (event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });
Unfortunately, that compiles, but crashes in the browser.

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.


Day #

Monday, January 23, 2012

Better Delegated Events

‹prev | My Chain | next›

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...

Last night, I was able to fake delegated events in Dart with event listeners along the lines of:
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();
  });
}
In there, I have conflated delegating the event (the queryAll selector) with firing the event handler (the call to the delete() method. What I would like, is something like:
attach_handler('click', '.delete', (event) {
  // handle event
})
That might be difficult to implement if I were stuck with the parent.on.click mechanism for accessing a list of event listeners. Fortunately, the on getter also supports a lookup format like on['click'], which ought to allow me to pass in all of the information that I need.

Starting with baby steps, I convert the on getting:
attach_delete_handlers(parent) {
  parent.on['click'].add((event) {
    // ...
  });
}
That still works, so I get a bit more ambitious:
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();
  });
}
Which I can then use thusly:
  attach_handler(list_el, 'click',  '.delete', (event) {
    print("[delete] ${event.target.parent.id}");
    delete(event.target.parent.id, callback:() {
      event.target.parent.remove();
    });
  });
And that still works. Nice.

OK, I really should not do this, but, the Backbone.js convention with these delgated events is to describe the event type and the selector in the same string (e.g. "click .delete"). Let's see if I can figure that out in time to post.

Ultimately, I think I would prefer a regular expression, but this will do:
attach_handler(parent, event_selector, callback) {
  var index = event_selector.indexOf(' ')
    , event_type = event_selector.substring(0,index)
    , selector = event_selector.substring(index+1);

  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();
  });
}
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.


Sunday, January 22, 2012

Delegated Events in Dart

‹prev | My Chain | next›

I do not believe that Dart has an equivalent to jQuery's delegated events, 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 Backbone.js that I especially came to know and love delegated events, hence the desire for them in Dart.

In my comic book application, I am inserting a list of comic books into a static page via XHR:


After list is inserted, I attach delete handlers to each of those Delete links:
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);
    attach_delete_handlers(list_el);
  });

  req.send();
}
What I would like to do is move that attach_delete_handers() function before the XHR request:
load_comics() {
  var list_el = document.query('#comics-list')
    , req = new XMLHttpRequest();

  attach_delete_handlers(list_el);

  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();
}
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 <a> tags—in this case requesting the current resource with a hash tag:


The reason that I do not believe that Dart supports this is the manner in which event handlers are added. All elements have an on getter, which returns an ElementEvents. Since on does not support any arguments, there is no mechanism to record a selector that might put the listener into delegate mode. The ElementEvents object exposes a series of EventListenerList getters (e.g. click, mouseOver, etc) to which event listeners can be added. I see no room for delegation anywhere.

This can be seen in my attach_delete_handlers() function, which iterates through each existing Delete link of the supplied UL list, attaching he same event listener to each:
attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
      delete(event.target.parent.id, callback:() {
        print("[delete] ${event.target.parent.id}");
        event.target.parent.remove();
      });
      event.preventDefault();
    });
  });
}
If I call attach_delete_handlers before the XHR request, then the queryAll('.delete') call will return an empty list and thus no handlers are attached.

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 .delete links and handle the event if the event target is on of those:
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();
  });
}
Sadly, when I click the delete link, I get the following:
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
Dang it. OK it is a new language. Things like that are bound to happen. Perhaps some() will work where indexOf() did not:
attach_delete_handlers(parent) {
  parent.on.click.add((event) {
    if (parent.queryAll('.delete').some((el) { el == event.target;})) return;

    print(event.target.parent.id);
    event.preventDefault();
  });
}
Now when I click a Delete link I get:
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
Shakes fist at jacobr!

So indexOf does not work, nor does some. I know that forEach() works for certain, so...
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);
    event.preventDefault();
  });
}
Not the prettiest code, but I can live with it until jacobr implements cleaner iterator methods.

With that working, I can add my XHR delete call to this psuedo-delegated event handler:
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();
  });
}
And, now I can delete comics again:


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...

Day #273

Saturday, January 21, 2012

Supporting Both Dart and Javascript

‹prev | My Chain | next›

Tonight I would like to get my Dart 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.

Currently, the Dart in my web application is loaded via a <script> tag:
<!DOCTYPE html>
<html>
<head>
  <title>Dart Comics</title>
  <link rel="stylesheet" href="/stylesheets/style.css">

  <!-- Force Dartium to start the script engine -->
  <script>{}</script>
  <script src="/scripts/comics.dart" type="application/dart"></script>
</head>

<body>
<!-- ... -->
</body>
</html>
When I compile this dart into Javascript with the frogc (I still don't get the name), it produces a file named comics.dart.js. I would almost like one of those old timey IE conditional comments to load in that Javascript file:
<!--[if Dart]>
  <script src="/scripts/comics.dart" type="application/dart"></script>
<![endif]-->
<!--[if !Dart]>
  <script src="/scripts/comics.dart.js" type="text/javasript"></script>
<![endif]-->
But I don't really want that. It sucks. Besides, I am duplicating the basename of /scripts/comics.dart in both <script> tags.

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 <script src="/scripts/comics.dart"> from being evaluated?

In other browsers, I would like a simple, unobtrusive fallback to the Javascript.

There are plans to use Isolates 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:
<script type="application/dart">
  #import('dart:html');
  main() {
    var el = new Element.html('<div id="_is-dart-enabled"/>');
    document.nodes.add(el);
  }
</script>
If Dart is enabled, that bit of code will insert a <div> tag into the DOM with an ID of _is-dart-enabled. I should then be able to to query for the presence of that tag from Javascript:
<script>
  if (document.getElementById('_is-dart-enabled') == null) {
    console.log('Not Dart enabled.');
  }
</script>
Only that does not work. I always see that console.log() output—even in Dartium which does add the _is_dart-enabled tag as expected.

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.

To get around this, at least for now, I add a setTimeout:
<script>
  setTimeout(function() {
    if (document.getElementById('_is-dart-enabled') == null) {
      console.log('Not Dart enabled.');
    }
  }, 50);
</script>
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 noDart() function that takes a callback and arguments to be invoked when there is no Dart available:
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);
}
With that, I can say that, in cases when there is no Dart, I should load the Javascript equivalents:
notDart(loadJsEquivalentScripts);

function loadJsEquivalentScripts() {
  var scripts = document.getElementsByTagName('script');
  for (var i=0; i<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);
}
And, with that, I have Firefox loading my Dart application:


And it still works in Dartium (with no console message about Dart not being enabled):

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.

Day #272

Friday, January 20, 2012

Dart Animation

‹prev | My Chain | next›

My sweet comic book application written entirely in Dart is starting to come together:


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!

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...

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:
.faded {
  opacity: 0;
  -webkit-transition: opacity 1s ease-in-out;
}
To get my fade animation, I make the opacity as a "-webkit-transition" property with a duration of 1 second. The ease-in-out 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:
.fade-in {
  opacity: 1;
}

.fade-out {
  opacity: 0;
}
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:
main() {
  load_comics();
  attach_add_handler();
}
The appropriate action when clicking the add text is to enable the add-form. So I add enable_add_form as a click handler:
attach_add_handler() {
  document.
    query('#add-comic').
    on.
    click.
    add(enable_add_form);
}
(yes, I hate horizontal code that much)

To enable the form, I merely need to add the fade-in class to my form:
enable_add_form(event) {
  final form_div = document.query('#add-comic-form');

  form_div.classes.remove('fade-out');
  form_div.classes.add('fade-in');

  form_div.queryAll('a').forEach((el) {
    el.on.click.add(disable_add_form);
    event.preventDefault();
  });
}
For good measure, I also remove the fade-out class (if present). I also add the disable_add_form handler as a click handler to all child <a> tags (e.g. Cancel links).

The disable_add_form handler is, of course, the inverse of enable_add_form:
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();
  });
}
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:

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:
enable_add_form(event) {
  final form_div = document.query('#add-comic-form');

  var start = new Date.now();
  step(timestamp) {
    var progress = timestamp - start.value
      , opacity = "${progress/1000}";

    form_div.style.opacity = opacity;
    if (progress < 1000) window.webkitRequestAnimationFrame(step, form_div);
    true;
  }
  window.webkitRequestAnimationFrame(step, form_div);
}
Hooking in to this animation stuff is cool, but it is overkill for simple animations.

Happily, while rooting through documentation, I found that CSSStyleDeclaration supports setting animation properties rather easily:
enable_add_form(event) {
  final form_div = document.query('#add-comic-form');

  form_div.style.transition = 'opacity 1s ease-in-out';
  form_div.style.opacity = "1";

  form_div.queryAll('a').forEach((el) {
    el.on.click.add(disable_add_form);
    event.preventDefault();
  });
}
That is pretty darn nice.

Day #271

Thursday, January 19, 2012

Delete (XHR and DOM) in Dart

‹prev | My Chain | next›

As of last night, I have my little comic book Dart application querying the data store over REST and populating the web page thusly:


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.

First up I attach the delete handlers after the comic books have been loaded and populated on the page:
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);
    attach_delete_handlers(list_el);
  });

  req.send();
}
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.

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:
attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
      print("id: " + event.target.parent.id);
      event.preventDefault();
    });
  });
}
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.

And that works. Clicking the delete links prints out the IDs of the comic books in question:


In my express.js + node-dirty backend, I have a simple delete route:
app.delete('/comics/:id', function(req, res) {
  db.rm(req.params.id);
  res.send('{}');
});
With that, I update the delete handlers to call a new delete() function:
attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
      delete(event.target.parent.id);
      event.preventDefault();
    });
  });
}
In the delete() function, I open an Ajax request with the delete HTTP verb and the proper ID:
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();
}
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 default_callback() is invoked.

Except it isn't. When I try this out, I am greeted by:
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
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.

What it is telling this time, it turns out, is that the result of (callback || default_callback) 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:
delete(id, [callback]) {
  var req = new XMLHttpRequest()
    , default_callback = () { print("[delete] $id"); };

  req.on.load.add((res) {
    (callback != null ? callback : default_callback)();
  });

  req.open('delete', '/comics/$id', true);
  req.send();
}
That does work as I hope as I see my default [delete] message logged to the console:


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 callback parameter of delete() comes in handy.

I specify the optional callback 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:
attach_delete_handlers(parent) {
  parent.queryAll('.delete').forEach((el) {
    el.on.click.add((event) {
      delete(event.target.parent.id, callback:() {
        print("[delete] ${event.target.parent.id}");
        event.target.parent.remove();
      });
      event.preventDefault();
    });
  });
}
I am just guessing on the remove() 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.

And it works! Not only is the item removed from the backend, but it is also removed from the UI:


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.


Day #270

Wednesday, January 18, 2012

Simple Ajax GETs and JSON Parsing in Dart

‹prev | My Chain | next›

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.

The first thing I need is a REST-like listing resource for my /comics. With express.js and node-dirty, that can be written as:
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));
});
I am going to populate the listing page almost entirely with Dart, so the initial view is breathtakingly simple:
<script src="scripts/comics.dart" type="application/dart"></script>

<h1>Dart Comics</h1>

<p>Welcome to Dart Comics</p>

<ul id="comics-list"></ul>
As for my comics.dart Dart code, I start with a small XHR to GET the /comics resource and print the results in the console:
#import('dart:html');

main() {
  var req = new XMLHttpRequest();
  req.open('get', '/comics', true);

  req.on.load.add((res) {
    print(req.responseText);
  });

  req.send();
}
I have to import the dart:html library to gain access to the XMLHttpRequest object, which is kinda important for Ajax.

Sending the request is a simple matter of calling open() with the appropriate HTTP verb and URL, and then instructing my XHR request to send() itself to the server. I pass in true as the third argument open to make this an asynchronous call so that this code will not block the browser while waiting on a response.

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 req.on.load.add syntax to add my callback that simply prints out the response.

The result, after loading the page, is:
[
  {"title":"Watchmen","author":"Alan Moore","id":"a1f9bcaa4e9939019ec9e4c36fa7a97e"},
  {"title":"Watchmen","author":"Alan Moore","id":"12e5c6c33b16399f778bad86fc6bc082"}
]
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.

For this, I iterate through each of the returned comic books, building up an HTML string along the way:
#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 +=
        "<li id='${graphic_novel['id']}'>" +
        "${graphic_novel['title']}" +
        " " +
        "<a href='#'>[delete]</a>" +
        "</li>";
    });
  req.send();
}
Which results in:

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).

Satisfied with my progress so far, I will pick back up tomorrow adding event handlers to the delete links.

Day #269

Tuesday, January 17, 2012

Dart Ajax Take Two

‹prev | My Chain | next›

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 last night's comments.

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 send() is not implemented, but fingers crossed. In yesterday's comic book application, I now specify that I am passing application/json:
    var data = {'title':title.value, 'author':author.value}
      , json = JSON.stringify(data);

    print(json);

    var req = new XMLHttpRequest();
    req.open('post', '/comics', true);
    req.setRequestHeader('Content-type', 'application/json');
    req.send(json);
    print(req.responseText);
Unfortunately, but not too surprisingly, I am still greeted with a not-implemented exception when I trigger the XHR send by submitting the form:
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
Bummer.

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:
#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);
  });
}
Unfortunately, that also fails to work. It seems that the command-line version of Dart lacks the dom, html, and json libaries:
➜  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');
^
Again bummer.

The last thing that I can try is compiling the Dart code into Javascript:
scripts git:(master) ✗ frogc comic_put.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 = {};
                    ^^^^^^
➜  scripts git:(master) ✗ ls -1
comic_put.dart
comic_put.dart.js
That warning message is a bit weird, but seems to be ignorable.

After switching my web page to use the compiled Javascript instead of the pure Dart:
<script src="scripts/comic_put.dart.js" type="application/javascript"></script>
Then things work. My express.js + node-dirty backend responds with:
{"title":"Watchmen","author":"Alan Moore","id":"12e5c6c33b16399f778bad86fc6bc082"}
And, indeed, checking the node-dirty store, my new record is indeed in place:
➜  comix git:(master) ✗ node
> db = require('dirty')('comix.db')
> db.get('12e5c6c33b16399f778bad86fc6bc082')
{ title: 'Watchmen',
  author: 'Alan Moore',
  id: '12e5c6c33b16399f778bad86fc6bc082' }
For the sake of completeness, the POST route in my express.js backend looks like:
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));
});
And yes, externally they might look like comic books, but I will always think of them internally as graphic novels. ANYhow...

One caveat with the compiled Javascript is that it is not executed on DOM-ready like the equivalent Dart code. With the Dart version, I could put the <script> tag before the form HTML. Once I converted to the compiled Javascript, I had to move the <script> tag after the HTML—otherwise the attempt to add an on-submit event handler failed because the Javascript could not find the form element.

I am a bit surprised that the version of Dartium that I have does not support XHR send() with a data argument. The frogc 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.

In the end, a few NotImplemented exceptions are to be expected for such a hipsterish 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.


Day #268

Monday, January 16, 2012

Submitting Forms via Ajax in Dart

‹prev | My Chain | next›

I had a pleasant time messing about with DartBox2D for the past couple of days. I set that aside, for the time being, to investigate writing more typical web applications with Dart..

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.

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 express.js application server with a node-dirty store embedded.

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:
➜  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 . && npm install
I update the generated package.json to include node-dirty (a simple, nosql backend store):
{
    "name": "comic-power"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.5.2"
    , "jade": ">= 0.0.1"
    , "dirty": "0.9.5"
    , "dirty-uuid": ">= 0.0.1"
  }
}
With that, I can the use npm to install all of the dependencies for my application:
➜  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
I then proceed to create a simple form to collect comic book information:


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:
<script>{}</script>
<script src="scripts/comic_put.dart" type="application/dart"></script>
To query the form, I import "dart:html" and employ the query method to find and attach an event listener to the form element:
#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();
  });
}
This results in the following console output:


I will worry about the checkboxes another day. For now, I would dearly love to submit that data to the backend. Unfortunately, the following:
    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);
Ends up causing a not-implemented error:


If I change the req.send(JSON.stringify(data)) call to just req.send(), then the request is sent... only without the data that is the whole point.

Thwarted for the moment, I call it an evening. I do very much like the query() 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.


Day #267

Sunday, January 15, 2012

Simple Physics with DartBox2D

‹prev | My Chain | next›

Last night, I got started with DartBox2D, the Dart version of Box2D. 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 Box2D Manual and see if I can get it working in Dart.

From the manual, the first thing to do is create the world:
b2Vec2 gravity(0.0f, -10.0f);
bool doSleep = true;
b2World world(gravity, doSleep);
The stuff that I already copied from the DartBox2D demo into my Simple2D constructor covers just this:
  Simple2d() {
    // Setup the World.
    final gravity = new Vector(0, GRAVITY);
    bool doSleep = true;
    world = new World(gravity, doSleep, new DefaultWorldPool());
  }
The only significant difference between the two is the third argument to the world constructor, DefaultWorldPool. From the DartBox2D documentation the DefaultWorldPool:
Provides object pooling for some objects used in the engine. Objects retrieved from here should only be used temporarily.
That does not provide much illumination for me, but, looking that the World code, it definitely requires a third argument.

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.

From the tutorial, the ground box looks like:
// Create the body & add it to the world
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef);

// Fixture with width 100 and height 10
b2PolygonShape groundBox;
groundBox.SetAsBox(50.0f, 10.0f)

// Bind shape to body
groundBody->CreateFixture(&groundBox, 0.0f);
The equivalent DartBox2D takes place (adapted from the demo code) in the initialize() method:
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);
    }
  }
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):
// Body definition
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&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 = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3
body->CreateFixture(&fixtureDef);
I add the equivalent Dart code to the initialize() block:
  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);
    }
  }
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).

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 initializeAnimation() method:
  /**
   * 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);
  }

And a runAnimation() method:
  /**
   * 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);
  }
I find the box a little odd, so I switch it to a ball:
    Body body;
    {
      // ...

      CircleShape circle = new CircleShape();
      circle.radius = 2.0;

      FixtureDef fixtureDef = new FixtureDef();
      fixtureDef.shape = circle;
      fixtureDef.density = 0.8;
      fixtureDef.friction = 0.0;
      fixtureDef.restitution = 0.5;

      body.createFixture(fixtureDef);
    }
I also give the body an initial velocity:
    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);
      //...
    }
With some bounding box shapes, I have me a nice animation (actually starts ~6 second mark):

video

That's a fun little library. Wish I knew about this sooner.


Day #266

Saturday, January 14, 2012

Getting Started with DartBox2D

‹prev | My Chain | next›

I have played about with the internals of Dart 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 DartBox2D port of Box2D, a two dimensional physics engine.

First up, I clone the repository:
➜  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.
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:


Looking through the code, I see:
        if(getQueryVariable('native') && 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);
Ah, so I need to manually specify a native=1 query parameter to get native detection to work. With that, DartBox2d admits that I do have Dart:


And, more importantly, I get nice demos like a bouncing ball in the "Ball Cage":


And "Circle Stress":


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.

I create myself an HTML document to hold my test:
<!DOCTYPE html>
<html>
  <head>
    <title>Simple DartBox2D</title>
    <script>{}</script>
    <script type="application/dart" src="simple.dart"></script>
  </head>
  <body>
    <h1>Simple DartBox2D</h1>
  </body>
</html>
And, in the simple.dart file, I copy the skeleton of the board from the blob test:
#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();
}
All in all, there is quite a bit of setup required just to draw the board. But it works.


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.

Day #265