tags:

views:

112

answers:

1

I've recently started encountering a very strange problem. To be honest, I'm not entirely sure how to describe it other than to just show it.

Here's the relevant HTML:

<div class="component container w100 noEdit" id="contentWrapper"> 
<div class="component container w50" id="container1"> 
   <div class="component text w50" id="text1"> 
      Text1 
   </div> 
</div> 
<div class="component container w25" id="container2"> 
   Container2 
</div> 
<div class="component container w25" id="container3"> 
   Container3 
</div> 
<div class="component container w25" id="container4"> 
   Container4 
</div> 
</div>

And the relevant JavaScript:

$(document).ready(function () { 
   //Add the Grab Bar to container components on the page. 
   $('.component').each(wrapComponentForEdit); 
   $('#contentWrapper').sortable(); 
   $('#contentWrapper').disableSelection(); 
}); 

var wrapComponentForEdit = function() 
{ 
   if (!$(this).hasClass('noEdit')) { 
      $(this).html('<div class="componentBorder">' + $(this).html() + '</div>'); 
      $(this).prepend('<div class="grabBar_l"><div class="grabBar_r"><div class="grabBar"></div></div></div>'); 
      alert($(this).attr('id')); 
   } 
}

The end result of this is that I see an alert pop up for container1, text1, container2, container3, container 4. And yet only the containers (not the text) end up with the visual changes that the $().each() is supposed to make.

Anyone have any idea what the heck is going on?

Thanks!

EDIT - A different way to do it, that still fails

I tried this, with the same result:

$(document).ready(function () {
    //Add the Grab Bar to container components on the page.
    var matched = $('.component');
    var componentCount = $(matched).size();
    for (i = 0; i < componentCount; i++)
    {
     wrapComponentForEdit($(matched).eq(i));
    }
    $('#contentWrapper').sortable({ handle: '.grabBarBit', tolerance: 'pointer'});
    $('#contentWrapper').disableSelection();
});

var wrapComponentForEdit = function(component)
{
    if (!$(component).hasClass('noEdit')) {
     $(component).html('<div class="grabBar_l grabBarBit"><div class="grabBar_r grabBarBit"><div class="grabBar grabBarBit"></div></div></div><div class="componentBorder">' + $(component).html() + '</div>');
     alert($(component).attr('id'));
    }
}

EDIT 2: Another alternate method, but this one works

I tried another way of doing things, and this way it works. However, the initial question still stands. Judging by how this new way works, it seems to me that the DOM is being updated, but jQuery isn't updating with it, so it loses track of the child element.

$(document).ready(function () {
    //Add the Grab Bar to container components on the page.
    var componentCount = $('.component').size();
    for (i = 0; i < componentCount; i++)
    {
     wrapComponentForEdit($('.component').eq(i));
    }
    $('#contentWrapper').sortable({ handle: '.grabBarBit', tolerance: 'pointer'});
    $('#contentWrapper').disableSelection();
});

var wrapComponentForEdit = function(component)
{
    if (!$(component).hasClass('noEdit')) {
     $(component).html('<div class="grabBar_l grabBarBit"><div class="grabBar_r grabBarBit"><div class="grabBar grabBarBit"></div></div></div><div class="componentBorder">' + $(component).html() + '</div>');
     alert($(component).attr('id'));
    }
}
A: 

This reminds me of another question

wait until previous .append() is complete (jquery).

Perhaps the .html or the .prepend commands are still in flight when the function is called again for the next (nested) html tag.

See if the problem goes away when you remove the outer component class like so :

<div class="container w50" id="container1"> 
   <div class="component text w50" id="text1"> 
      Text1 
   </div> 
</div>

If that does eliminate your problem, you will need to come up with a slower way of updating the html that waits until previous changes are complete.

See 43,439 reasons to use append() correctly for more info on Append (some good ideas in there)

Tom Leys
Removing the component class from the outer element does in fact make the child element render right. I also tried to compress everything into a single $().html() with no change.
Nate Wagar