Add and Remove Elements with JavaScript (reprise)
A long time ago (February 28th, 2005 to be exact), I wrote a post titled Add and Remove HTML elements dynamically with JavaScript. To this day, it continues to be the most highly traffic page on my website. However there is a number of things I’d like to point out that we can improve upon that implementation (since it is very outdated), and for the record, retract my three year old statement where I said “I hate JavaScript.” That simply isn’t true anymore, and it hasn’t been true for a while now. Nevertheless, let’s move onto business. Here’s how you can simply add and remove HTML elements.
The basics
When it comes down right to it, the bottom line is this. You need three ingredients. Event attachment; the ability create and append elements, and the ability to remove them. For example:
attach event / add / remove
* element.addEventListener(el, type, fn);
* parent.appendChild(element);
* parent.removeChild(element);
Yeah. That’s it. But this wouldn’t be much of a post if there wasn’t a demonstration of how to wrap this up in a easy to use interface. For this basic task, consider using two singleton’s as a skeleton to act as your API which will appropriately wrap your Dom object, and an Event object.
Dom and Event
var Dom = {
get: function(el) { },
add: function(el, dest) { },
remove: function(el)
};
Event = {
add: function(el, type, fn) { }
};
Your implementation code can live in a closure wrapper when we add this behavior to the window’s ‘load’ event.
implementation
Event.add(window, 'load', function() {
// enclosed implementation here
});
Filling in the gaps
We can now essentially drop in our interface to do our heavy lifting.
Interface
var Dom = {
get: function(el) {
if (typeof el === 'string') {
return document.getElementById(el);
} else {
return el;
}
},
add: function(el, dest) {
var el = this.get(el);
var dest = this.get(dest);
dest.appendChild(el);
},
remove: function(el) {
var el = this.get(el);
el.parentNode.removeChild(el);
}
};
var Event = {
add: function() {
if (window.addEventListener) {
return function(el, type, fn) {
Dom.get(el).addEventListener(type, fn, false);
};
} else if (window.attachEvent) {
return function(el, type, fn) {
var f = function() {
fn.call(Dom.get(el), window.event);
};
Dom.get(el).attachEvent('on' + type, f);
};
}
}()
};
Then simply use it to our convenience.
implementation
Event.add(window, 'load', function() {
var i = 0;
Event.add('add-element', 'click', function() {
var el = document.createElement('p');
el.innerHTML = 'Remove This Element (' + ++i + ')';
Dom.add(el, 'content');
Event.add(el, 'click', function(e) {
Dom.remove(this);
});
});
});
You now have something that’s easy as Pie! View the demonstration. Cheers and happy new year!













January 2nd, 2008 at 7:20 pm
Nice writeup, Dustin. The code looks to be quite graceful. Perhaps an update to the original post to direct searchers here would be helpful.
January 2nd, 2008 at 10:04 pm
Nice and to the point. I’m sure there will be people out there that will have a hard time understanding your coding pattern. To whom I will say, buy Dustin’s book! (top right of his website) :)
January 2nd, 2008 at 11:23 pm
[…] UPDATE: There is a newer “up-to-date” version of this entry posted on January 02, 2008. View Add and Remove Elements with JavaScript (reprise). […]
January 3rd, 2008 at 12:16 am
Thanks for sharing the code. I’ve really got to get caught up with all the neat things you can do with JavaScript.
Just an observation here, but in your code sample labeled “interface”, the second-to-last line seems to have a stray “()” after the “}”…That seems a bit out of place, does it serve a purpose?
January 3rd, 2008 at 12:20 am
@Grant: Yes. That’s supposed to be there. That immediately invokes the function at runtime. You can see that new functions are returned to the value. That’s a basic trick known as currying.
January 3rd, 2008 at 2:17 am
No, currying it is not. See http://en.wikipedia.org/wiki/Currying
In your book you call it “branching”.
January 3rd, 2008 at 11:08 am
Well, yeah. It’s kind of like a half-baked version of currying though. It only lacks passing one argument to the next function. However it is still most definitely branching.
January 3rd, 2008 at 11:40 am
Don’t you want to remove any event handlers on an element before removing the element from the DOM (in order to prevent IE memory leaks)?
January 3rd, 2008 at 7:53 pm
[…] Add and Remove html elements with JavaScript […]
January 3rd, 2008 at 8:17 pm
hi, thanks for this article, i read your old one yesterday - i guess it was right before you posted this lol.
I used this to add inputs to a form. So the user can enter as many ingredients in a recipe as they want.
is there a way of telling my php script how many ingredients the user added?
thanks for the great article
January 4th, 2008 at 12:00 am
OK, so I’m might be a moron of some renown but in this snippet:
Event.add(el, 'click', function(e) {
Dom.remove(this);
});
How is ‘this’ the HTML element you want removed?
January 4th, 2008 at 12:21 am
Joe: Microsoft was supposed to have fixed this issue. Otherwise, yes, you can add in extra behavior that would go in and sweet any existing listeners before they were removed from the DOM. Most JS libraries will do this for you automatically too.
Jack: Simply put in a name like
<input type="text" name="fieldname[]" />and that will create multiple keys for that on the server side.Tyrone: ‘this’ is the element that is clicked on. Since you’re within the scope of the callback function of the event listener, ‘this’ refers to the element that was clicked.
January 4th, 2008 at 12:34 pm
Dustin, just received your book in the mail, looking forward to reading it.
January 7th, 2008 at 2:55 pm
I’m might missing something here, but what if I have a link leading somewhere, with a JS onclick event attached to it, which returns false in order for the browser not to follow it:
Event.add(link, 'click', function () {// Do whatever
return false;
});
In this example, the browser still follows the link.
I would expect the code above to behave like this:
link.onclick = function () {// Do whatever
return false;
};/code>
which does not make the browser follow the link. How can this be accomplished?
January 7th, 2008 at 11:57 pm
Marius: you’re looking for the preventDefault method. There is an invisible argument passed to your event listener callbacks known as the event object. Call the preventDefault method off that object.
that will work with both w3 and IE.
January 8th, 2008 at 9:27 pm
I’m just going over the Currying you mentioned but sorry had to mention, i find it amusing i’m buying a Javascript book from guy who said 3 years ago “I hate JavaScript.”
But like you i’m starting to love JS.
January 8th, 2008 at 9:27 pm
Sorry had to mention, i find it amusing i’m buying a Javascript book from guy who said 3 years ago “I hate JavaScript.”
But like you i’m starting to love JS.
January 8th, 2008 at 9:28 pm
I’m just going over the Currying you mentioned but sorry had to mention, i find it amusing i’m buying a Javascript book from guy who said 3 years ago “I hate JavaScript.”
But like you i’m starting to love JS.
January 9th, 2008 at 12:33 am
Hey Dustin. This article shows how to remove a child element from a parent node. The element I want to remove is directly under the body tag and doesnt have a parentNode (e1.parentNode gives an error in that case). Any ideas how i cud remove the node?
January 23rd, 2008 at 8:13 am
Great guide, I’m just starting out with javascript, and have found your site really useful, so a big thanks from me!
January 23rd, 2008 at 12:37 pm
dustin - i’m using you’re function (older version), however in my case anytime a user calls the function, it adds the elements within a new div tag.
In IE, when user clicks on the add link instead of adding the new element to the “current” div tag, it adds it to top most div tag, and not the div tag from which the function was called. make sense or do i need to further clarify?
January 24th, 2008 at 11:14 pm
I want a remove function as the old version of the script.
How can I add a “Remove button” near the element?
Thanks :)
January 26th, 2008 at 9:20 pm
When I add a element into innerHTML, it doesn’t work with IE.
Are there a solution about this?
January 30th, 2008 at 6:32 am
Has anyone found a fix or workaround for the back button problem on IE? I’m talking about the problem that the elements created from javascript disappear after you submit the page and click the browser back button to see the page again.
February 3rd, 2008 at 4:39 am
Thank you.
Because you wrote (and shared) getElementsByClass - I didn’t give up on on trying to figure out greasemonkey and I was finally able to write my first greasemonkey script.
February 6th, 2008 at 6:41 am
This is a really neat bit of code. I am not a programmer, but am usually able to put bits & peices together — however, I’m trying to find a ‘history-based breadcrumb’ script (lists what the user has clicked, rather than hierarchical-based, which would not work in this situation). I have found a couple, but they do not work as they are supposed to. What i would like to do is what your code does: when a user clicks on a choice, it gets ‘logged’ or listed-up, so that they can jump back to a previous choice if they wanted to. Once they have jumped back (say 3 choices/clicks), the following choices/clicks would disappear.
This is intended for an on-line type of training system that I am developing for teachers for self-study. Any thoughts or ideas would be appreciated.
February 7th, 2008 at 2:01 pm
awesome.
After seeing (and writing) lots of very badly done versions of this sort of thing, I’m glad to see there’s a clean and elegant approach.
p.s. your copyright notice says “2007″
February 10th, 2008 at 8:36 pm
If I insert an input text field and I click on the text field to type something in, the field is removed. How would I work around this obstacle?
February 11th, 2008 at 7:15 am
How can I delete a row in mytable in VB
and/or the entire table and then recreate it programmatically
February 11th, 2008 at 7:32 am
[…] I recommend you check out his guide “Add and Remove Elements with JavaScript (reprise)”. […]
February 11th, 2008 at 11:33 pm
@Pava -
That is a really weird edge case to be concerned about. If you’re generating form inputs, for example, wouldn’t you just instruct the form’s action target page (often itself) to generate those new elements on the server, and not the JS? That is, if you even care about the dynamically generated elements after form submission.
In other words, don’t use these functions to replace server-side generation, and use form redirects smartly. Your JS will thank you.
February 14th, 2008 at 3:06 am
Is there a way of renumbering the subsequent elements after removing? eg 1 2 3 4 5 removing 3 leaves 1 2 4 5, I would like to be left with 1 2 3 4. Thanks
February 14th, 2008 at 9:14 pm
I’ve tried to use this codes to add remove file element (multi file upload), a bit confuse on how to put remove button (not on self click)
thanks
February 19th, 2008 at 9:45 am
ok, I’m not a JS wiz yet but from a tutorial point of view, the old version was far better. This one I can’t seem to figure out where to add my block of code that I want to duplicate.
I had the old version up and running in 2 minutes in my own example. This one is far too dodgy to use because in my case I’m using form fields and if I click on the gap in between the field I delete them! Not really what I wanted! *sigh*
Sorry Dustin, maybe I’m missing something?
February 20th, 2008 at 11:16 am
Hi,
Thank you for writing such a great code. I have implement the code for adding text fileds for a form. The following is the changed part. I have tested it and it works. on your action page you can create a loop to find the POST info and the end of the loop comes as hidden field. You may want to add something like this if the user only submit once:
$counter=$_POST[’counter’];
if (!$counter){ $counter=1
then you can start your loop with $i=1 rather than 0. I hope this can help someone.
Regards, –jh
=========CUT HERE
Event.add(window, ‘load’, function() {
var i = 1;
Event.add(’add-element’, ‘click’, function() {
var el = document.createElement(’p');
i=i+1;
el.innerHTML = ‘Alerts:Advisories:(’+i+’)';
Dom.add(el, ‘content’);
Event.add(el, ‘click’, function(e) {
//Dom.remove(this);
});
});
});
====FORM PART
form name=”the_form” id=”the_form” method=”post” action=”youractions file”>
Add form elements
(1)
February 23rd, 2008 at 2:26 pm
This is really great! How do I limit the times it adds a new element?
February 28th, 2008 at 4:46 pm
for a form, and a “remove” text in a span to remove the form element:
Event.add(window, ‘load’, function() {
var i = 0;
Event.add(’add-element’, ‘click’, function() {
var ela = document.createElement(’span’);
ela.innerHTML = ‘remove’ ;
var el = document.createElement(’p');
el.innerHTML = ‘ ‘;
el.appendChild(ela);
Dom.add(el, ‘content’);
Event.add(ela, ‘click’, function(e) {
Dom.remove(el);
Dom.remove(ela);
});
});
March 5th, 2008 at 3:56 am
Jafar,
I have been looking for something like this too. Basically to be able to dynamically add text fields in a form.
But I tried your code and it doesn’t work. On clicking add element only this is added “Alerts:Advisories:(1)”
How do I add text fields or textboxes and then how do I get their value in the Post action?
Thanks for your help!!!
March 12th, 2008 at 4:27 pm
Hey,
How do you do something like this for a drop down field?
March 26th, 2008 at 11:55 am
I am new to DOM javascript. This code is really helpful, but maybe a little too advanced for me. I am trying to add text “input” elements but after they are added and I click them they keep disappearing. How do I make a separate Remove with the “click” event and disable the click event on the text area?
I saw Tim and Jafar’s comments but still can’t get it. Thanks
March 27th, 2008 at 11:47 am
Great script - but like Levi indicated if you put an input form element in and then click on it the element disappears!!
How do you say put an input element in and not have it disappear when it is clicked on (eg to type text into the input box)?
March 28th, 2008 at 3:14 pm
I’m just a beginner when it comes to javascript, but I found it to work perfectly for what i needed.
Problem: I’ve tried to use your script with another one that does a neat autocomplete based on some arrays and it’s not working on the fields generated with the script. Any ideea how this can be fixed ?
I noticed that the autocomplete works on fields already present in the html when the page loads, but not on the ones added after the page finished loading … I’m guessing that’s the problem the script isn’t working ?
Thank you in advance for any clues or enlightment you might bring over my problem.
April 5th, 2008 at 12:37 pm
Hello. I love your code, but I am having some problems. I have been trying to add a method to the event variable to remove an event, but when I do, the browser throws a fit and says that the event.add method doesn’t exist. and none of my events get added.
var Event =
{
add: function(element, type, model, func)
{
if(window.addEventListener)
{
return function(element, type, model, func)
{
DOM.getElement(element).addEventListener(type, func, model);
};
}
else if(window.attachEvent)
{
return function(element, type, model, func)
{
DOM.getElement(element).attachEvent("on" + type, function()
{
func.call(DOM.getElement(element), window.event);
});
};
}
else
{
type = "on" + type;
DOM.getElement(element).type = func;
}
}(),
remove: function(element, type, model, func)
{
if(window.removeEventListener)
{
DOM.getElement(element).removeEventListener(type, func, false);
}
else if(window.detachEvent)
{
DOM.getElement(element).detachEvent("on" + type, func);
}
}()
};
April 6th, 2008 at 7:31 pm
Dustin,
This is very awesome. I am on the cusp of grasping this and it’s funny I can understand examples but I can’t seem to add the bits I want in gracefully.
For instance I want to know how I can call this to add a preset/dynamic number of the entries as soon as the page loads. This would be handy for being able to load previous stored entries, depending on your implementation.
Would you do a loop or is there a more graceful approach?
April 7th, 2008 at 12:06 pm
Hello again. I have another question. What would you have to change in the code if you have a function already declared and you wanted to add an event listener to an object that would call the pre-defined method. For example, I have this code:
function setupEvents(events)
{
April 7th, 2008 at 12:18 pm
Hello again. I have another question. What would you have to change in the code if you have a function already declared and you wanted to add an event listener to an object that would call the pre-defined method. For example, I have a function:
function functionName(attribute)
{
//...some code here
}
How would I go about using this function when an event is fired?
I’ve tried a few things but have not been successful yet:
Event.add(window, 'load', functionName);
Event.add(window, 'load', functionName());
Event.add(window, 'load', functionName.call());
Also, as for my last question, I still need help figuring that out, I just didn’t want to leave my website with a non-working navigation, so I didn’t leave the non working code up on my website. I guess that was a dumb move on my part, as you might have wanted to look at the actual errors. I will put that back up now.
Thanks for your time.
April 7th, 2008 at 12:37 pm
Sorry about the cut off post, I messed up and hit tab while trying to type some code then I hit enter.
Anyway, I feel really stupid now, I just figured out the answer to my first question. I forgot to return the function in the Event.remove function. Still would like to know how to call a pre-existing function on an event though.
April 8th, 2008 at 2:59 pm
Hi,
Thanks for this topic, but I’m still struggling:
I have a site which loads data from an xml file. This data set then populates a fresh table.
On every pageload, the former table should be remove, and a new one should be created. I have written some code which works excellent in FF, yet in IE, the new table is simply add under the existing one.
var theTable = document.getElementById("table");
var oldtablebody;
if (oldtablebody = document.getElementById("table")) {
while (oldtablebody.hasChildNodes()) { // while tbody has datarow elements
oldtablebody.firstChild.firstChild.nodeValue = null;
oldtablebody.firstChild.lastChild.nodeValue = null;
while (oldtablebody.firstChild.hasChildNodes()) {
oldtablebody.firstChild.removeChild(oldtablebody.firstChild.firstChild);
}
oldtablebody.removeChild(oldtablebody.firstChild);
}
}
please help!
Thx,
Jeroen
April 15th, 2008 at 8:47 am
Hi Gary,
did you create somthing like this:
Alerts:
(1)
This one will create a textarea field for you.
I will check again tomorrow to see if you got it woring.
Regards, –jh
April 15th, 2008 at 8:52 am
Hi Gary, part two:
change the script part to this:
el.innerHTML = 'Alerts:(’+i+’)';
Dom.add(el, ‘content’);
This matchs the static part of th form. I have tested this and it works on every browser.
Regards, –jh
April 17th, 2008 at 3:06 am
Hi!
Was looking for this kind of script, need it to insert content from external files with iframes;
now what I still need, is a way to check, if a certain content already is loaded (then the insert-function would do nothing) or not (then it would insert the iframe); plus I need a way to decide, if the new element (including the iframe with content) will be inserted before or after …
Would be nice, f someone could help me!!!
May 10th, 2008 at 2:42 pm
[…] The second link is a reprise by the same author almost three years later with a much cleaner implementation of the same functionality in JavaScript. Unfortunately, it requires more knowledge about JavaScript and events, and for a beginner in programming, the first link may be easier to swallow. For the site, click this link: http://www.dustindiaz.com/add-remove-elements-reprise/ […]