Is there a general best practice for creating somewhat complex HTML elements in jQuery? I\'ve tried a few different ways.
First I tried using createElement and chaining
John Resig (creator of jQuery) suggested using this templating method back in 2008. It's actually got some pretty cool features:
<script type="text/html" id="item_tmpl">
<div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>">
<div class="grid_1 alpha right">
<img class="righted" src="<%=profile_image_url%>"/>
</div>
<div class="grid_6 omega contents">
<p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p>
</div>
</div>
</script>
then retrieving it using...
var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);
See here for full details:
http://ejohn.org/blog/javascript-micro-templating/
It is more readable and maintainable if the JavaScript code resembles the HTML tag structure. You can go the official jQuery route using $('div', { 'class': 'etc'})...
Here is a slightly different approach using a function $$ to make each element an editable jQuery object. It should be pretty fast as there is no html parsing taking place.
$$('div', {'id':'container'},
$$('div', {'id':'my_div'},
$$('h1',{'class':'my_header'},
$$('a',{'href':'/test/', 'class':'my_a_class'}, 'teststring'))));
This makes the approach more flexible and you can add event handlers, data etc. to the nested jQuery objects using chaining quite easily e.g.
$$('div', {'id':'container'},
$$('div', {'id':'my_div'},
$$('h1',{'class':'my_header'},
$$('a', { 'href': '/test/', 'class': 'my_a_class' }, 'teststring')
).click(function() { alert('clicking on the header'); })
).data('data for the div')
).hide();
The code is more readable than if one were to use the official jQuery approach of doing it with separate calls to .append(), .text(), .html() etc. or by feeding the jQuery $ a concatenated HTML string.
Reference function $$:
function $$(tagName, attrTextOrElems) {
// Get the arguments coming after the params argument
var children = [];
for (var _i = 0; _i < (arguments.length - 2) ; _i++) {
children[_i] = arguments[_i + 2];
}
// Quick way of creating a javascript element without JQuery parsing a string and creating the element
var elem = document.createElement(tagName);
var $elem = $(elem);
// Add any text, nested jQuery elements or attributes
if (attrTextOrElems) {
if (typeof attrTextOrElems === "string") { // text
var text = document.createTextNode(attrTextOrElems);
elem.appendChild(text);
}
else if (attrTextOrElems instanceof jQuery) { // JQuery elem
$elem.append(attrTextOrElems);
}
else // Otherwise an object specifying attributes e.g. { 'class': 'someClass' }
{
for (var key in attrTextOrElems) {
var val = attrTextOrElems[key];
if (val) {
elem.setAttribute(key, val);
}
}
}
}
// Add any further child elements or text
if (children) {
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (typeof child === "string") { // text
var text = document.createTextNode(child);
elem.appendChild(text);
} else { // JQuery elem
$elem.append(child);
}
}
}
return $elem;
}
I'd be inclined to look at one of the templating engines for jquery like jQote
With jQuery 1.4, you can create HTML elements like so:
// create an element with an object literal, defining properties
var e = $("<a />", {
href: "#",
"class": "a-class another-class", // you need to quote "class" since it's a reserved keyword
title: "..."
});
// add the element to the body
$("body").append(e);
Here's a link to the documentation.
I'm not sure that this approach is faster than using the html()
function of jQuery. Or faster than skipping jQuery all together and use the innerHTML
property on an element. But as far as readability goes; the jQuery-approach is my favorite. And in most cases the performance-gain of using innerHTML
is marginal.
The way I am doing is shown bellow. I am not sure if u should create so many divs but it worked pretty well with me.
var div1 = $('<div class="colwrap_fof"></div>'); //THE COMPLEX DIV ITSELF
var div2 = $('<div class="homeimg"></div>');
var div21 = $('<div id="backImageDiv'+fof_index+'" class="backDiv"></div>');
var div22 = $('<div id="frontImageDiv'+fof_index+'" class="frontDiv"></div>');
div2.append(div21);
div2.append(div22);
div1.append(div2);
$("#df_background").append(div1); // ADDING the complex div to the right place
Cheers,
I personally think that it's more important for the code to be readable and editable than performant. Whichever one you find easier to look at and make changes to without breaking it should be the one you choose.