chuckw87
chuckw87

Reputation: 707

appendChild performance problems in Chrome

I am having an issue with speed in chrome with an appendchild line in javascript. This seems to be running fine in firefox and chrome, but not Chrome is extremely slow. I am only trying to add one element on a button click. The page already has well over 10,000 elements, but I'm not sure if that is part of the issue.

Just to go over things I have looked at. I have looked up documentfragment, and attempted to implement that, but was getting the same results. And from what I gather, documentfragment usually improves performance when you are adding A LOT of elements to the dom, not just one. (Feel free to correct me if I am wrong on this assumption). I also ran the timeline in Chrome and found that that the "Layout" is taking 11.91s to load and seems to be getting stuck on the appendchild line. I have commented the line in question below.

As I mentioned before I had tried documentfragment with the no improvement, so this is my original code.

function addYr() { 
         divArray = document.getElementById('acct_sect').getElementsByTagName("div");
         divRow = document.createElement("div");
         divRow.id = "acct_row_" + (divArray.length);

         var yr  = document.createElement("input");
         yr.type= "text";
         yr.id= "yr_" + divArray.length;
         yr.name= "yr_" + divArray.length;
         yr.setAttribute("onkeydown", "TabNext(this,'down',2); return justNums(event);");
         yr.setAttribute("onkeyup", "TabNext(this,'up',2,this.form.fnd_)");
         yr.maxLength = 2;   
         yr.className = "c1";
         yr.setAttribute("onchange", "buildAccountMultiRow(this)");
         yr.value = "";

         divRow.appendChild(yr);


    //line that is taking a while
    document.getElementById('acct_sect').appendChild(divRow);
}

Upvotes: 1

Views: 774

Answers (1)

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324630

The large number of elements is most likely to blame, but here's something to try:

  • getElementsByTagName returns a live list, that must be updated every time it changes. Instead, try this:

    divArray = document.getElementById('acct_sect').children;
    
  • If you don't use the id attribute for anything, remove that.

  • If you can rearrange some code on the server, try:

    yr.name = "yr[]";
    

    Then on the server you will get (for instance in PHP) $_POST['yr'] as an array containing the values.

  • If you can do both of the above two items, then you will find that you don't even need divArray any more, and can just get rid of that entirely, which should save a LOT of time.
  • Try changing how you handle events. Instead of assigning three event handlers to every single element, assign a single one to the container.

    var ac = document.getElementById('acct_sect');
    ac.onkeydown = function(e) {
        e = e || window.event;
        var t = e.srcElement || e.target;
        if( t.nodeName == "INPUT") {
            tabNext(t,'down',2);
            return justNums(e);
        }
    };
    ac.onkeyup = function(e) {
        e = e || window.event;
        var t = e.srcElement || e.target;
        if( t.nodeName == "INPUT") {
            tabNext(t,'up',2,t.form.fnd_);
        }
    };
    ac.onchange = function(e) {
        e = e || window.event;
        var t = e.srcElement || e.target;
        if( t.nodeName == "INPUT") {
            buildAccountMultiRow(t);
        }
    };
    

Upvotes: 1

Related Questions