My findings about the web

...and probably other stuff too

Creating "designer friendly" dynamic html lists

, , , ,

This post is about a different approach for populating dynamic lists. I usually see people creating list entries using plain javascript code like this:
<div id="list">
</div>
var container = $('list');

for ( var i = 0, e; e = elem[i]; i++ ) {
    var div = document.createElement('div');
    div.className = 'entry';
    
    var img = document.createElement('div');
    img.className = 'image';
    img.src = e.image;
    div.appendChild(img);
    
    var span = document.createElement('span');
    span.className = 'name';
    span.textContent = e.name;
    div.appendChild(img);
    
    var div2 = document.createElement('div');
    div2.className = 'status';
    
    var statusImg = document.createElement('img');
    statusImg.className = 'statusImg';
    statusImg.src = e.status_img;
    div2.appendChild(statusImg);
    
    var statusText = document.createElement('span');
    statusText.className = 'statusText';
    statusText.textContent = e.status_text;
    div2.appendChild(statusText);
    
    div.appendChild(div2);
    container.appendChild(div);
}
One of the main problems with this code is that you can't quite understand what the hell is happening there unless you take a close look to all those createElement and appendChild, even though, it can be quite painful to construct a mental image of the resulting html. My approach to this problem is to create an html template where we can instantly experiment the design we want, without having to write lots of js code just to create and position an element. Then, on the js side, we clone the html template, fill the necessary fields with data and append it to the end of the list. The html template:
<div id="list">
    <div id="entryTemplate" class="entry">
        <img class="image"/>
        <div class="status">
            <img class="statusImg"/>
            <div class="statusText"></div>
        </div>
    </div>
</div>
And the js code:
var container = $('list');
var template = $('entryTemplate');
for ( var i = 0, e; e = elem[i]; i++ ) {
    var entry = template.cloneNode(true);
    entry.id = 'elem' + i;
    
    entry.getElementsByClassName('image')[0].src = e.image;
    entry.getElementsByClassName('statusImg')[0].src = e.status_image;
    entry.getElementsByClassName('statusText')[0].textContent = e.status_text;
    
    container.appendChild(entry);
}
We have considerably less code and we can easly understand what is the structure of each list entry. Another cool thing is the ability to add/remove/edit html elements on the template without having to mess with the js code, it also makes the designers happy because they can change whatever they want directly on the html structure. And if you want to you can also create a function to eliminate the "getElementsByClassName('image')[0]" ugly thing. UPDATE: Both runeh and p01 told me that ul and li was the really true way to code the lists, instead of using plain div's, and with the li template you even get correct html as a bonus since there must be at least one li child inside the ul.

Open Web Podcast

Comments

Yoan Blancgreut Thursday, December 18, 2008 8:35:17 AM

I'm sure, you can come up with something simpler and more like to be used (without copy and paste ;-)

<ul id="entries"></ul>

...

<div style="display:none">
 <ul>
  <li id="entry">
   <img alt="" class="avatar">
   <span class="fn"<>/span>
  </li>
 </ul>
</div>


and somewhere else:

var list = document.getElementById("entries");
var entries = template("entry", [
 {
  avatar: {
   src: "/foo.png",
   alt: "Picture of Foo",
   title: "Mah title"
  },
  fn: {
   innerText: "Foo"
  }
 },
 {
  avatar: null,
  fn: {
   lang: "fr",
   innerHTML: "<strong>éh éh</strong>"
  }
 }
]);

for(var i=0; i<nodes.length; i++) {
 list.appendChild(nodes);
}


By the way, it's always good to separate the normal work and the work on the DOM. Touching the document is quite heavy for the browser.

Yoan Blancgreut Monday, November 30, 2009 5:00:25 PM

Right, there must be one li :-)

Write a comment

New comments have been disabled for this post.