Christian Heilmann

Shorter DOMscript via cloning vs. generating elements

Thursday, December 8th, 2005 at 4:19 pm

cloned sheepI just looked through some of my older scripts and other people’s code and realised that a lot of time we bloat our methods by repeating the same functionality.

This is especially true when it comes to generating a lot of HTML via the DOM.

We keep repeating the same document.createElement and setAttribute lines over and over. Wouldn’t it be more efficient to create those once when initialising our script and then cloning them?

Say for example we need to generate three links that are dependent on JavaScript (and we should generate these via JS).

A normal method to do this would be:


// 30 lines of code
createLinks:function(){
var newul,newli,newa;
newul=document.createElement(‘ul’);
newli=document.createElement(‘li’)
// sheep #1
newa=document.createElement(‘a’);
newa.appendChild(document.createTextNode(‘baa#1’));
newa.href=’#’;
dolly.addEvent(newa,’click’,dolly.baa1);
newa.onlick=function(){return false;} // Hello Safari
newli.appendChild(newa);
newul.appendChild(newli);
// sheep #2
newli=document.createElement(‘li’)
newa=document.createElement(‘a’);
newa.appendChild(document.createTextNode(‘baa#2’));
newa.href=’#’;
dolly.addEvent(newa,’click’,dolly.baa2);
newa.onlick=function(){return false;} // Hello Safari
newli.appendChild(newa);
newul.appendChild(newli);
// sheep #3
newli=document.createElement(‘li’)
newa=document.createElement(‘a’);
newa.appendChild(document.createTextNode(‘baa#3’));
newa.href=’#’;
dolly.addEvent(newa,’click’,dolly.baa3);
newa.onlick=function(){return false;} // Hello Safari
newli.appendChild(newa);
newul.appendChild(newli);
// herd them
document.body.appendChild(newul);
},

Now, if part of the initialisation method would be to generate a dummy link inside an LI, we could reuse by cloning it:


makeClones:function(){
dolly.li=document.createElement(‘li’);
dolly.a=document.createElement(‘a’);
dolly.a.appendChild(document.createTextNode(‘baa!’));
dolly.a.setAttribute(‘href’,’#’);
dolly.li.appendChild(dolly.a);
},

By cloning this dummy li and referencing the link via firstChild and the link text via firstChild.firstChild we can save 9 lines of code, which still means a 4 line win if add the createClones method:


// 21 lines + 5 lines createClones
createFlock:function(){
var newli,newa,newul;
newul=document.createElement(‘ul’);
// sheep #1
newli=dolly.li.cloneNode(true);
dolly.addEvent(newli.firstChild,’click’,dolly.baa1);
newli.firstChild.onlick=function(){return false;} // Hello Safari
newli.firstChild.firstChild.nodeValue=’baa#1’;
newul.appendChild(newli);
// sheep #2
newli=dolly.li.cloneNode(true);
dolly.addEvent(newli.firstChild,’click’,dolly.baa2);
newli.firstChild.onlick=function(){return false;} // Hello Safari
newli.firstChild.firstChild.nodeValue=’baa#2’;
newul.appendChild(newli);
// sheep #3
newli=dolly.li.cloneNode(true);
dolly.addEvent(newli.firstChild,’click’,dolly.baa3);
newli.firstChild.onlick=function(){return false;} // Hello Safari
newli.firstChild.firstChild.nodeValue=’baa#3’;
newul.appendChild(newli);
// herd them
document.body.appendChild(newul);
},

Further reduction could be achieved by moving the event handling and text changing to another helper method:


dressClone:function(clone,func,name){
dolly.addEvent(clone.firstChild,’click’,func);
clone.firstChild.onlick=function(){return false;} // Hello Safari
clone.firstChild.firstChild.nodeValue=name;
},

Which means the main method for generating the links will be 23 lines in total (including the helper methods):


// 15 lines + 5 lines + 3 lines
createWoolyFlock:function(){
var newli,newa,newul;
newul=document.createElement(‘ul’);
// sheep #1
newli=dolly.li.cloneNode(true);
dolly.dressClone(newli,dolly.baa1,’baa#1’);
newul.appendChild(newli);
// sheep #2
newli=dolly.li.cloneNode(true);
dolly.dressClone(newli,dolly.baa2,’baa#2’);
newul.appendChild(newli);
// sheep #3
newli=dolly.li.cloneNode(true);
dolly.dressClone(newli,dolly.baa3,’baa#3’);
newul.appendChild(newli);
// herd them
document.body.appendChild(newul);
},

The benefits are the following:

  • We have one centralised spot for defining the links initially – if for example we needed to add a class at a later state we’d do it in one method instead of scanning the whole object of where to apply the changes
  • Generating a new LI is now 3 lines of code instead of 7, which multiplies with the amount of links
  • We don’t need to re-define a lot of variables or create new ones every time we add a link.

The example script of cloning vs. generating works on MSIE 6, Firefox, Opera 8 and Safari.

Is there any problem or bad effect I am overlooking? How is the performance of cloning vs. generating anew every time we need a link?

Share on Mastodon (needs instance)

Share on Twitter

Newsletter

Check out the Dev Digest Newsletter I write every week for WeAreDevelopers. Latest issues:

160: Graphs and RAGs explained and VS Code extension hacks Graphs and RAG explained, how AI is reshaping UI and work, how to efficiently use Cursor, VS Code extensions security issues.
159: AI pipelines, 10x faster TypeScript, How to interview How to use LLMs to help you write code and how much electricity does that use? Is your API secure? 10x faster TypeScript thanks to Go!
158: 🕹️ Super Mario AI 🔑 API keys in LLMs 🤙🏾 Vibe Coding Why is AI playing Super Mario? How is hallucinating the least of our worries and what are rules for developing Safety Critical Code?
157: CUDA in Python, Gemini Code Assist and back-dooring LLMs We met with a CUDA expert from NVIDIA about the future of hardware, we look at how AI fails and how to play pong on 140 browser tabs.
156: Enterprise dead, all about Bluesky and React moves on! Learn about Bluesky as a platform, how to build a React App and how to speed up SQL. And play an impossible game in the browser.

My other work: