with Imagination: by Dustin Diaz

./with Imagination

A JavaScript, CSS, XHTML web log focusing on usability and accessibility by Dustin Diaz

Add and Remove Elements with JavaScript (reprise)

Wednesday, January 2nd, 2008

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!

53 Responses to “Add and Remove Elements with JavaScript (reprise)”

  1. Scott Nellé

    Nice writeup, Dustin. The code looks to be quite graceful. Perhaps an update to the original post to direct searchers here would be helpful.

  2. Marc Grabanski

    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) :)

  3. Add and Remove HTML elements dynamically with Javascript

    […] 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). […]

  4. Grant Palin

    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?

  5. Dustin Diaz

    @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.

  6. Michael Schuerig

    No, currying it is not. See http://en.wikipedia.org/wiki/Currying

    In your book you call it “branching”.

  7. Dustin Diaz

    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.

  8. Joe Pearson

    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)?

  9. Ruby, Rails, Rails Plugins, JavaScript, SEO « exceptionz

    […] Add and Remove html elements with JavaScript […]

  10. Jack s

    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

  11. Tyrone Slothrop

    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?

  12. Dustin Diaz

    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.

  13. Anthony Delorie

    Dustin, just received your book in the mail, looking forward to reading it.

  14. Marius

    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?

  15. Dustin Diaz

    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.

    
    Event.add(foo, 'click', callback);
    function callback(e) {
      var e = e || window.event;
      try (
        e.preventDefault(e);
      } catch(ex) {
        e.returnValue=false;
      }
    }

    that will work with both w3 and IE.

  16. Wreck

    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.

  17. Wreck

    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.

  18. Wreck

    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.

  19. Lata

    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?

  20. Dan

    Great guide, I’m just starting out with javascript, and have found your site really useful, so a big thanks from me!

  21. kyle

    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?

  22. Gejitrer

    I want a remove function as the old version of the script.

    How can I add a “Remove button” near the element?

    Thanks :)

  23. Gejitrer

    When I add a element into innerHTML, it doesn’t work with IE.

    Are there a solution about this?

  24. Pava

    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.

  25. ekbworldwide

    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.

  26. Michael

    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.

  27. Thom Blake

    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″

  28. Levi

    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?

  29. Vance

    How can I delete a row in mytable in VB
    and/or the entire table and then recreate it programmatically

  30. Tommy Nation » Blog Archive » Add and Remove Elements with JavaScript / ECMAScript

    […] I recommend you check out his guide “Add and Remove Elements with JavaScript (reprise)”. […]

  31. Daniel

    @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.

  32. Steve Houghton

    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

  33. chazzuka

    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

  34. Fred

    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?

  35. Jafar Hosseinzadeh

    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)

  36. Joshua

    This is really great! How do I limit the times it adds a new element?

  37. tim

    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);
    });
    });

  38. gary

    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!!!

  39. Zach

    Hey,

    How do you do something like this for a drop down field?

  40. Will

    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

  41. Gary Mailer

    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)?

  42. Robert

    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.

  43. Nick

    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);
    }
    }()
    };

  44. Hellman

    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?

  45. Nick

    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)
    {

  46. Nick

    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.

  47. Nick

    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.

  48. Jeroen

    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

  49. Jafar

    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

  50. Jafar

    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

  51. Roland Hentschel

    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!!!

  52. Adding and removing elements via JavaScript | John Rockefeller

    […] 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/ […]

  53. ewart

    Nice! Is it also possible using DOM to get the innerHTML of an element, or rather I mean, the whole HTML?

    I have a reference to my element:
    try to click me.

    but innerHTML returns just ‘try to click me’. Seems there is no property to return the whole element text. I can’t use parentNode.innerHTML because this element is on an equal level with others, and so parentNode.innerHTML returns all sub-nodes. To make matters worse, I will also not necessirily have an ID or tagname in the span.

    ideas?

Leave a Reply

Phone Number:

If you're about to post code in your comment, please wrap your code with the tag-combo <pre><code>. Also please escape your html entities - otherwise they will be stripped out. I recommend using postable.

Get "JavaScript Design Patterns"

"As a web developer, you'll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power waiting to be unlocked--JavaScript is capable of full object-oriented capabilities, and by applying OOP principles, best practices, and design patterns to your code, you can make it more powerful, more efficient, and easier to work with alone or as part of a team."

Buy JS Design Patterns from Amazon.com Buy JS Design Patterns from Apress

Flickr

Submit a Prototype

All content copyright © 2003 - 2007 under the Creative Commons License. Wanna know something? Just ask.

About | Archives | Blog Search

[x] close

Loading...

Submit a prototype

By checking this prototype I agree that I am not submitting false credentials, pornography, or a hate crime website. I also understand that by submitting my entry I may or may not be accepted, and if accepted, my entry may be taken down at any given time if I violate these terms.