Bob Nystrom’s article Improving the DOM introduces a jQuery-like syntax for Dart, but you still have to write out document.query(…). Can anything be done to shorten it? It turns out that $ is a valid function name in Dart, so, as suggested by Jacob Richmann on misc@dartlang.org, you can define a utility function like this:
ElementList $(String query) => document.queryAll(query);
Now in your UI code, you can write simply
$('h2').first.text = 'Heading 2';
This got me thinking. What if you wanted to emulate jQuery even further, like:
$('h1').addClass('blue'); // call methods on matching elements
$('h1').each((Element e) => e.text = "Heading");
$('h1').onClick((Event v) => window.alert('hi'));
Here’s a tiny library that lets you do the above. It’s just a starter, but hopefully shows some of Dart’s potential for convenient DOM manipulation.
#library('dartQuery');
#import("dart:html");
typedef void ElementFunction(Element e);
/**
* jQuery-like syntax returns an ElementListWrapper on which methods can be called
*/
ElementListWrapper $(String query) => new ElementListWrapper(document.queryAll(query));
/**
* jQuery-like interface providing convenience methods which
* operate on multiple Elements returned by document.queryAll()
* A TODO in dart:html's Element.dart suggests that some methods
* may eventually make it into Dart's ElementList, possibly eliminating
* the need for a wrapper.
*/
class ElementListWrapper {
ElementList _elements;
ElementListWrapper(ElementList this._elements);
// invoke a function for each element
void each(ElementFunction f) => _elements.forEach(f);
// add a style classname to each element
void addClass(String className) {
each((Element e) => e.classes.add(className));
}
// add a click handler to each element
void onClick(EventListener h) {
each((Element e) => e.on.click.add(h, true));
}
// allows $('#id').first
Element get first() => _elements.first;
}
Warning: this was working earlier in frog and dartc, but something seems to have changed this afternoon. Either I broke it while reformatting for the blog or my Dart build is hosed. YMMV.