Why does adding a class affect the reported height within the same loop using JS/jQuery
<p>I am building a timelined comments feature for part of my app.  Inspired by facebook's new timelined profiles.</p>

<p>As an example here is a screenshot of the current display.</p>

<p><img src="http://i.stack.imgur.com/u5hEj.jpg" alt="Example"></p>

<p>As you can see the comment/reply boxes fill up all vertical space.</p>

<p>In order to do this I have used jQuery to do the following to the <code>&lt;li&gt;</code> elements in the ordered list of comments with nested replies.</p>

<ul>
<li>collect the items into an object</li>
<li>iterate over each one and get its individual height all the while building a left and right variable with the total height of the left
hand side boxes and the total of the right hand side boxes</li>
<li>I then check which out of the left and right have the higher total height and apply either a timeline-left or timeline-right class to
the next comment box.</li>
</ul>

<p>This all seems very simple however I ran into a huge problem which I am at a loss to explain.</p>

<p>If I apply the class within the initial loop (iteration over the elements) The height variable gets effected within the loop.  It appears to be adding them together rather than replacing the current one.  This of course causes the boxes to be switched to the incorrect sides and therefore fails to close the gaps.  Although not relevant to the functionality I added the heights as an attribute to each element in order to better see what was going on.  And without a shadow of a doubt.  As soon I add the class 'timeline-left' within the same loop as the height detection, the height variable combines each loop rather than reflecting the individual elements value.</p>

<p>To work around this I have come up with what I consider to be a very ugly method solve the issue.</p>

<ul>
<li>I iterate through the objects and build an array of values (height,side) for each box.</li>
<li>I then iterate AGAIN through this new array and apply the classes to each box.</li>
</ul>

<p>Now this actually works fine and performance is also fine.  While I usually adhere to the whole pre-optimization is bad mentality.  In this case I just cannot let it lie as surely there should be no reason to iterate through the elements more than once?</p>

<p>Here is the current (ugly) code I am using which collects the data about each element and then re-loops a second time to apply the classes:</p>

<pre><code>    var side = "left",
         $timeline = $("#timeline"),
         $elements = $timeline.children("li").not(".timeline-spine"),
         newwidth = parseInt(($("#rightcolumnwrapper").width() / 2) - 26),
         length = $elements.length,
         array = [],
         $i = 0,
         leftheight = 0,
         rightheight = 0,
         side = "left";

     while ($i &lt; length) {

         var $this = $elements.eq($i),
             height = $this.outerHeight(true);

         if (leftheight &gt; rightheight) {
             side = "right";
         } else {
             side = "left";
         }

         array.push({
             "side": side,
             "height": height
         });

         if (side == "right") {
             var rightheight = rightheight + height + 25;
         } else if (side == "left") {
             var leftheight = leftheight + height + 25;
         }
         $i++;
     }

     $.each(array, function (index, value) {

         var $timelineItem = $("#timeline").children("li").not(".timeline-spine").eq(index);

         $timelineItem.attr("data-height", array[index]["height"]).addClass("timeline-" + array[index]["side"]).children(".window-wrapper").width(newwidth).siblings("#pointer").addClass("pointer-" + array[index]["side"]);


//The code below is not relevant to the question but is left in for completeness

         if ($timelineItem.is("#timeline-bottom")) {
             $timelineItem.find("#pointer").css({
                 "left": (newwidth + 21) + "px"
             });
         } else if ($timelineItem.is("#loves-capsule")) {
             if ($timelineItem.find("#love-main").height() &gt; $this.find("#loves-wrapper").height() - 33) {
                 $timelineItem.height("176px").find("#loves-wrapper").css({
                     "height": "174px",
                     "margin-bottom": "-35px"
                 }).end().find("#love-footer").show();
             }
         }

     });
</code></pre>

<p>Is there anything I can do to get this into one loop without (and I really cannot explain why) effecting the heights reported for each element?  </p>

<p>Note:  There is some other stuff going on at the end is not really relevant to the question however I have left it in for code completeness.</p>

<p>EDIT:  Just to be clear there is no css styling other than clear:left; float:left and clear:right; float:right; in either of the css rules that I am adding. Just in case anyone thought I may be styling them to modify the height.</p>
