0

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'));
    }
}
Nate Wagar
  • 640
  • 2
  • 7
  • 18
  • Any particular reason you're wrapping with divs rather than just doing `.addClass()`? – Matt Ball Oct 08 '09 at 17:22
  • The order of the divs. I always suffer from pretty bad divitis, but here I think it's warranted - grabBar has rounded edges and needs to change width fluidly. The rounded edges also require that the border around the component be below the grabBar. The reason that I do this with javascript is that these pieces are only needed in certain scenarios. – Nate Wagar Oct 08 '09 at 17:31
  • I don't see what the problem is. The wrapping div's look like they're being applied fine to all of the elements. You do have this error though: `$("#contentWrapper").sortable is not a function` – Justin Johnson Oct 08 '09 at 18:58
  • I didn't include it in my sample here, but jQuery UI is included in my code, so that error is not an issue. Whenever I run this locally, the wrapping div's are applied to container1 2 3 and 4, but not text1. – Nate Wagar Oct 08 '09 at 19:18

1 Answers1

0

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)

Community
  • 1
  • 1
Tom Leys
  • 18,473
  • 7
  • 40
  • 62
  • 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 Oct 09 '09 at 13:55