Is there a best practice for generating html with javascript

Is there a best practice for generating html with javascript

I’m calling a web service that returns an array of objects in JSON. I want to take those objects and populate a div with HTML. Let’s say each object contains a url and a name.
If I wanted to generate the following HTML for each object:

the name

Is there a best practice for this? I can see a few ways of doing it:

Concatenate strings
Create elements
Use a templating plugin
Generate the html on the server, then serve up via JSON.

Solutions/Answers:

Solution 1:

Options #1 and #2 are going to be your most immediate straight forward options, however, for both options, you’re going to feel the performance and maintenance impact by either building strings or creating DOM objects.

Templating isn’t all that immature, and you’re seeing it popup in most of the major Javascript frameworks.

Here’s an example in JQuery Template Plugin that will save you the performance hit, and is really, really straightforward:

var t = $.template('<div><img src="${url}" />${name}</div>');

$(selector).append( t , {
     url: jsonObj.url,
     name: jsonObj.name
});

I say go the cool route (and better performing, more maintainable), and use templating.

Solution 2:

If you absolutely have to concatenate strings, instead of the normal :

var s="";
for (var i=0; i < 200; ++i) {s += "testing"; }

use a temporary array:

var s=[];
for (var i=0; i < 200; ++i) { s.push("testing"); }
s = s.join("");

Using arrays is much faster, especially in IE. I did some testing with strings a while ago with IE7, Opera and FF. Opera took only 0.4s to perform the test, but IE7 hadn’t finished after 20 MINUTES !!!! ( No, I am not kidding. ) With array IE was very fast.

Solution 3:

Either of the first two options is both common and acceptable.

I’ll give examples of each one in Prototype.

// assuming JSON looks like this:
// { 'src': 'foo/bar.jpg', 'name': 'Lorem ipsum' }

Approach #1:

var html = "<div><img src='#{src}' /> #{name}</div>".interpolate(json);
$('container').insert(html); // inserts at bottom

Approach #2:

var div = new Element('div');
div.insert( new Element('img', { src: json.src }) );
div.insert(" " + json.name);
$('container').insert(div); // inserts at bottom

Solution 4:

Here’s an example, using my Simple Templates plug-in for jQuery:

var tmpl = '<div class="#{classname}">#{content}</div>';
var vals = {
    classname : 'my-class',
    content   : 'This is my content.'
};
var html = $.tmpl(tmpl, vals);

Solution 5:

Perhaps a more modern approach is to use a templating language such as Mustache, which has implementations in many languages, including javascript. For example:

var view = {
  url: "/hello",
  name: function () {
    return 'Jo' + 'hn';
  }
};

var output = Mustache.render('<div><img src="{{url}}" />{{name}}</div>', view);

You even get an added benefit – you can reuse the same templates in other places, such as the server side.

If you need more complicated templates (if statements, loops, etc.), you can use Handlebars which has more features, and is compatible with Mustache.

Solution 6:

You could add the template HTML to your page in a hidden div and then use cloneNode and your favorite library’s querying facilities to populate it

/* CSS */
.template {display:none;}

<!--HTML-->
<div class="template">
  <div class="container">
    <h1></h1>
    <img src="" alt="" />
  </div>
</div>

/*Javascript (using Prototype)*/
var copy = $$(".template .container")[0].cloneNode(true);
myElement.appendChild(copy);
$(copy).select("h1").each(function(e) {/*do stuff to h1*/})
$(copy).select("img").each(function(e) {/*do stuff to img*/})