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

No comments:

Post a Comment