Why does jQuery's $().each() function seem to be losing track of the DOM?
Posted
by Nate Wagar
on Stack Overflow
See other posts from Stack Overflow
or by Nate Wagar
Published on 2009-10-08T17:19:57Z
Indexed on
2010/03/29
6:03 UTC
Read the original article
Hit count: 201
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'));
}
}
© Stack Overflow or respective owner