Re: Simplifying element creation

On Tue, Nov 15, 2011 at 11:06 AM, Aryeh Gregor <ayg@aryeh.name> wrote:

> On Mon, Nov 14, 2011 at 7:04 PM, Ojan Vafai <ojan@chromium.org> wrote:
> > With a browser-provided html quasi-literal, this could be:
> > var table = html'<table><tbody></tbody></table>';
> > for (var i = 0; i < labels.length; i++) {
> >     table.childNodes[0].append(html'<tr>
> >         <td>${labels[i]}</td>
> >         <td>
> >             <span class="bar" style="width:${some expression}%"></span>
> >             <span class="value-container">${values[i]}</span>
> >         </td>
> >     </tr>');
> > }
> > element.append(table);
>
> This seems like it's clearly the best solution proposed so far.  It's
> hard to come up with a syntax for DOMs that's more concise or familiar
> than HTML.  It's worth pointing out that if this returns a
> DocumentFragment, it's actually impossible for authors to use string
> concatenation -- the *only* way for them to embed variable quantities
> is by the ${} syntax, which will auto-escape.  So this would really be
> superb for preventing XSS.
>

I believe preventing XSS was one of the primary use-cases driving the
quasis spec.


> It's also worth pointing out that sadly, running an HTML parser on
> <tr> with no context node will simply make the <tr> disappear, so this
> particular case would completely fail.  If the html quasi-function
> uses the existing HTML parser without adjustment, you'll append a
> bunch of spans and text nodes directly to the <tbody>, with no <tr> or
> <td>.  There's discussion in another thread (I can't remember which
> list) about how best to handle this for DocumentFragment.innerHTML,
> which is relevant here.  It's not so simple to add a new magic
> insertion mode that picks the right insertion context automatically,
> particularly when you mix in SVG.
>

Yes. I agree with Jonas on the other thread, we just need to define this
and make it work in as sane a way as possible. Heh "just" :) To avoid
splitting that part of the discussion on two threads, I was just assuming
that the other thread would resolve how to make it work. :)


> But I think this syntax is far more concise and readable than anything
> else proposed so far, and it's also likely to be the most efficient
> (only one function call).  This is the only kind of syntax that will
> actually displace innerHTML and all its XSS problems.
>

Agreed. Although, I share Ryosuke's sadness that it encourages having lots
of whitespace textnodes everywhere in your DOM. Not sure what we could do
about that.


> (There is one aspect in which innerHTML might be better: if you're
> adding hundreds of thousands of rows, it's going to be much faster to
> run the HTML parser once instead of hundreds of thousands of times.
> Is the idea that it's also possible to call the html quasi-function on
> an arbitrary string you build, so you can resort to string
> concatenation if you really need to?)
>

Kind of. The html is actually just a javascript function. So you could call
it explicitly with the right object. You could write a simple function that
would construct the right arguments for the html quasi function argument
given an HTML string.

So the following:
var b = 0, d = 1;
html`aaaa${b}cc\nc${d}eee`

Desugars to:
var $__0 = Object.freeze({
    raw: Object.freeze(["aaaa", "cc\\nc", "eee"]),
    cooked: Object.freeze(["aaaa", "cc\nc", "eee"])
});
var b = 0, d = 1, f = function() { };
html($__0, b, d);

And b and d are interleaved between the items in the array.

Received on Tuesday, 15 November 2011 19:33:44 UTC