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.


No comments:

Post a Comment