
Better than templates, building highly dynamic web pages - robmueller
http://blog.fastmail.fm/2012/02/20/building-the-new-ajax-mail-ui-part-2-better-than-templates-building-highly-dynamic-web-pages/
======
tmanderson
This is, in my opinion, even worse than writing straight HTML in JavaScript.
Before I get into anything, I just want to point out that with jQuery, you can
do the same thing:

$('<div id="foo"><span>bar</span></div>').appendTo('.baz');

I'm not one to condone the over-use of the bloated jQuery, but in this case I
sure would.

Anyways, my biggest gripe with this whole thing is the fact that writing any
markup in your JS, or anywhere other than an HTML file, is just plain ugly.
Beyond that, it's a pain to manage, and totally screws up the whole
"separation of duties" paradigm that the web community seems to be quickly
forgetting as of late.

Keep your markup where it should be, in your HTML files, because as we all
know, HTML is XML and XML is meant to give semantic meaning to data.
JavaScript should be a means of transport for data to its relevant structure,
not means of giving visual structure to data. Leave that to the HTML and CSS.

Even templating doesn't do it for me 100% of the time and there are better
ways. I'm a heavy believer in separation of duties, and any JS programmer
should be too. Every time I come across any heavy-handed DOM manipulation in
JS I cringe.

As for this article, there's 523637483723526334632 other
libraries/frameworks/micro-frameworks that do this same thing, and if you're
going to do it, just use what you're already probably using: jQuery. You're
probably already abusing it anyways.

~~~
MatthewPhillips
That jQuery snippet is the best possible way to make your site sluggish.

~~~
tmanderson
<http://jsperf.com/tmandersondomtest>

The best possible way? Well, that's not true at all. In fact, that was even
faster* than whatever method this article was talking about (genDom).

Either way, my point wasn't to say 'just toss it all over to jQuery!' My point
was, if you think this technique is cool, you're probably using jQuery and you
could've been doing this for years. Years!

Anyhow, this is a huge deflection from what I was really trying to convey.
Basically, I don't think this (the 'sugared dom' method from the article) is
solving anything. HTML should define your markup and JS should just be filling
in the blanks (and not creating them).

*Please note that I do realize my DOM creation was particularly minimal (however, hardly differing from the 'sugared dom' test mentioned in the article) and is hardly a sufficient test. Really, I just wanted to show that you'd have to be doing a ridiculous amount of DOM manipulation to see any significant drop in performance.

------
starfox
My browser does 10,000 operations / second with innerHTML, and 15,000
operations / second with DOM. In every ajax application I've ever made, this
is negligible, compared to latency, server processing time, and downloading
time.

I guess this saves you 1ms for every 30 elements you create? I'm sure there
are some cases I'm missing where this might make more of an impact, but from
my understanding of the article, this looks like a pretty small improvement.

~~~
bigiain
Keep in mind, not everybody is running a desktop browser with that sort of cpu
horsepower behind it.

Half of the iPhones ever sold - something like 80 million devices - are pre
iPhone 4. There are a lot of low end Android devices on the market _right now_
with worse browser performance than an iPhone 3 (I've got a <6month old Huawei
U8110 here as an example). Sure, top-end Android devices compare well against
an iPhone4S (I'm pretty impressed with the Galaxy SII I've got here), but the
bulk of Android devices in the wild are not late-model-top-end devices.

I had to drop an entire development branch from a project late last year due
to insufficient performance of mobile device on-handset ajax. (We fell back to
on-server html rendering and innerHTML updates, and even _that_ is annoyingly
slow to me on low-end phones.)

And unless you have gathered data showing otherwise, this _probably_ really
does apply to you. I was collecting some mobile use data last week - across
~70 websites that I've got Google Analytics access to, the average mobile
visits was 14%, and the peak was just over 28%. This was across a range of
markets and a variety of levels of "mobile friendliness" of the web design.
(Biggest and probably most obvious takeaways from that exercise: B2B sites are
a standard deviation or more below average for mobile visits, personal/leisure
B2C sites up to one or two SD's above average. 80+% of mobile visits exit on a
page with contact details - a phone# or address.)

------
jacques_chester
I remember back in the late 90s that generating content on the browser using
javascript was the new and greatest thing.

Personally it bugs me. But I'm 31, a total fuddy duddy.

~~~
jordhy
Those were the days. I remember coding in Livescript and debating between
implementing stuff in VBScript vs Javascript.

------
beernutz
I have a problem with this, as it appears to break the separation of concerns.

Don't the programing guru's tell us over and over NOT to mix markup into code
and vice-versa?

~~~
emilis_info
Try for yourself. What the guru's tell you is a heuristic.

When this heuristic fails, you waste lots of time mangling data to fit it into
dumb markup instead of writing a simple loop with a couple of ifs.

------
tiglionabbit
I thought this was going to be about a data binding template system like
AngularJS or Knockout. Those are truly "better than templates", whereas this
one is questionable.

------
insin
I have a library for this sort of thing (but without the HAML-style # and .
niceties :-/) which can also output DOM Elements or HTML (escaped by default)
from the same code by flipping its output mode:
<https://github.com/insin/DOMBuilder>

The output modes are implemented as plugins, so you can also add other sorts
of things, like the template mode I'm in the progress of writing, with
template inheritance and the like.

Bretthopper's comment about the readability is spot on, though - you have to
start using comma-first pretty quickly or you will go mad getting commas in
the right places, and you're never going to get a designer writing these
things.

The good thing about it is that since your templates are written in code, it's
trivial to share them between client and server - this example app can also be
clones and run on Node.js, which uses the same templates to serve full pages
when you hit any URL and works as a forms 'n links webapp if you disable
JavaScript in your browser:
[http://jonathan.buchanan153.users.btopenworld.com/sacrum/fra...](http://jonathan.buchanan153.users.btopenworld.com/sacrum/fragile/fragile.html)

~~~
MatthewPhillips
That looks pretty cool, but I have to ask... you're using with? Really?

~~~
insin
Yes, it's perfect for building templates in code based on an object defining
your templating API - code which is run once at startup with little or no
assignment and no ambiguity between the contents of the context object and
anything else, e.g.:
[https://github.com/insin/sacrum/blob/master/fragile/lib/frag...](https://github.com/insin/sacrum/blob/master/fragile/lib/fragile.js#L450-482)

You could easily go back and plug in use of a single-letter variable instead
of the implicit context object after the fact, but it's nicer to work with
while you're building stuff up.

------
lootsauce
Hey man I think its pretty cool, I'm using it to replace my default shorthand
to document.createElement. Added a handy dandy outputStrings mode so i can run
it in node.js without a dom. Check it out $el is it, plus uses $node for the
string output mode <https://github.com/andrewluetgers/loot>

------
jarek-foksa
The idea that CSS selectors could be used for element creation is awesome. It
would be so convenient to write:

    
    
        var link = el("a#top.link[src='http://google.com'][data-external='true']")
    

Instead of:

    
    
        var link = document.createElement('a');
        link.setAttribute('id', 'top');
        link.setAttribute('class', 'link'); 
        link.setAttribute('src', 'http://google.com');
        link.dataset.external = 'true'
    

Someone needs to bring it to W3C forums, otherwise we might end up with this
[http://lists.w3.org/Archives/Public/www-
dom/2011OctDec/0020....](http://lists.w3.org/Archives/Public/www-
dom/2011OctDec/0020.html)

~~~
Bockit
I get that what you're trying to do is keep it syntactically correct
javascript, but just in case, have you looked at HAML [1] and/or Jade[2]? Both
templating languages that allow you to write HTML in that kind of way. Even
less syntax than what you're writing there.

I guess you have the overhead of the template language and rendering them
though still.

[1] <http://haml-lang.com/>

[2] <http://jade-lang.com/>

EDIT: Added links.

~~~
jarek-foksa
What I'm looking for is a way to easily create single DOM nodes, not a full
templating language.

HAML and Jade assume that you have static pseudo-markup defined upfront and
you just fill it with data, this approach is not suitable for apps that are
doing heavy DOM manipulations (e.g. SVG editor, text editor, sophisticated
widget toolkit).

------
donut
The syntax looks very similar to JSONML, which has its own templating thing
JSONML BST:

<http://jsonml.org/>
([http://webcache.googleusercontent.com/search?q=cache:http://...](http://webcache.googleusercontent.com/search?q=cache:http://jsonml.org/))

<http://jsonml.org/bst/>
([http://webcache.googleusercontent.com/search?q=cache:http://...](http://webcache.googleusercontent.com/search?q=cache:http://jsonml.org/BST/))

------
bretthopper
This is an interesting approach. One downside is that it's much less readable
than the Handlebars template. Using Coffeescript for the "templating"
functions would actually clean it up a lot.

~~~
perfunctory
Would you mind posting a Coffeescript snippet to demonstrate that?

~~~
jacobr

      items = [ 1, 2, 3, 4 ]
      el 'div#message', [
        el 'a.biglink', href: 'http://www.google.com', [ 'A link to Google' ]
        el 'ul',
          el 'li.item', [ "#{item}. Item" ] for item in items
        'There are lots of items'.localise() + '. ' if items.length > 1
        'This is just plain text. <script>I have no effect</script>' ]

------
rickette
What concerns me about generating HTML clientside is the impact on
accessibility (WACG and the likes). How would screenreaders handle these
techniques?

------
tchvil
The DOM is a live object while a string can be sliced and compiled in a
function.

If you run a template once, either to generate a form or a simple list, the
DOM is faster than innerHTML.

But if you need to repeat a template(loop), use partials or recurse,
interpreted DOM manipulations will become a degree of magnitude slower than a
compiled function concatenating strings.

Quickly slow enough to loose the snappy effect of client templating.

~~~
MatthewPhillips
A compiled function only gives you a really fast string creator. It doesn't
make the innerHTML call any faster than it is (which is really fast, but
slower than the DOM).

You can also use cloneNode to cache frequently reused DOM snippets.

~~~
tchvil
The creation of a complex DOM tree(nested loop, partials, recursion) is what
is slow compared to string concatenation. The injection time of the string
need parsing, and will take a bit longer. But in total less time than DOM
manipulations.

I'm trying for a few months now to remove the last innerHTML bits of pure.js
and haven't figured out a way yet to make it as fast.

------
gryzzly
On mobile, if performance is really so good, it might make sense – I
especially like having references in place – might be quite handy.

------
grayrest
When I do this, I do it with Kris Zyp's put selector [1]. Creates new
elements, modifies existing ones. It's the only DOM manipulation API I like
besides jQuery.

[1] <https://github.com/kriszyp/put-selector>

That said, I don't do this very often because the designers I work with prefer
templated markup.

------
tmeasday
This reminds me of HAML. I've never really seen the benefit of adding a layer
that doesn't really add much onto something that is well-known and thus easily
maintainable.

Performance benefits seem mostly irrelevant, as pointed out by others.

~~~
te_chris
I didn't see the point of HAML - until I used it. I'm a complete convert now:
the syntax is just so superior to being productive in markup for me. In my
current app I'm including a small ember app, having to write straight markup
for handlebars (hamlbars is a bit awkward) is painful compared to how quickly
you can produce markup with HAML.

Personal preference of course, but to me the difference is night and day in
terms of my productivity with producing markup.

~~~
tmeasday
I guess the thing for me is that my HTML is usually simple enough that there
isn't significant time spent writing it.

So I can see there could be productivity gains, but I don't see they would be
sufficient to justify the technical debt in introducing a new syntax.

~~~
te_chris
I seriously think you're overstating the technical debt incurred by HAML. The
docs aren't the best - they cover stuff, but are hard to navigate sometimes -
but the actual language has a very shallow learning curve in my experience
picking it up myself and bringing front-enders up to speed with it when I work
with them on projects.

~~~
tmeasday
Oh, sure, learning it is pretty trivial if you know CSS. But there are a lot
of hidden things, like cutting + pasting snippets of code from the Text Editor
to/from the browser/jsfiddle/wherever, providing code samples on Stack
Overflow, etc etc etc etc.

I think they made the right call when they went SASS -> SCSS for these kind of
reasons. I know that coverting CSS blocks into the equivalent SASS was one of
my least favourite things :)

------
eaurouge
It's worth mentioning that CoffeeKup lets you write HTML templates in
CoffeeScript: <http://coffeekup.org/>

------
nathansobo
I have a prettier implementation: <https://github.com/nathansobo/space-pen>

------
gyaresu
I'm just excited to have ajax on <https://beta.fastmail.fm> now.

------
tomelders
That code smells funny.

------
AdrianRossouw
i distrust any 'template system' that involves in putting a html tag name,
classname or id in the code I use to drive it.

