Skip to main content

Bug Tracker

Side navigation

#9181 closed bug (invalid)

Opened May 09, 2011 03:33AM UTC

Closed May 09, 2011 03:47AM UTC

Last modified May 09, 2011 04:18AM UTC

$.each() fails to iterate properly over custom HTML elements when using replaceWith()

Reported by: chris.young-zawada@wmg.com Owned by:
Priority: low Milestone: 1.next
Component: core Version: 1.6
Keywords: Cc:
Blocked by: Blocking:
Description

When using $.each() to iterate over an array of custom HTML elements, reformatting these elements with .replaceWith() does not work properly. The first iteration is correctly replaced, but the following iterations improperly pass the 'DOMWindow' object to 'this', rather than the 'HTMLElement' object.

<!doctype html>
<html xmlns:custom="http://customelement.com">
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<script>
$(function($){

  //get the list of custom elements
  var elems = document.getElementsByTagName('custom:element');

  //iterate over them
  $.each(elems,function(){

    /*
    replace each element with a div instead
    the error that is occurring is that after the first element is replaced,
    the following elements' targets are lost, and each is passed as a 'DOMWindow'
    object instead of the correct 'HTMLElement' object
    */

    console.log('about to kill element: ');
    console.log($(this));

    $(this).replaceWith('<div class="customElement"></div>');
    
    console.log('killed element');
  });


});
</script>
</head>
<body>
  <p>
    Check out the console...
  </p>
  <custom:element>1</custom:element>
  <custom:element>2</custom:element>
  <custom:element>3</custom:element>
</body>
</html>
Attachments (0)
Change History (4)

Changed May 09, 2011 03:47AM UTC by rwaldron comment:1

component: unfiledcore
priority: undecidedlow
resolution: → invalid
status: newclosed

Because getElementsByTagName returns a live nodelist, as you are replacing items in the list, elements matching the tag "custom:element" are being reduced by one each on each iteration.

live nodelists are notoriously unpredictable, as seen here.

Changed May 09, 2011 03:56AM UTC by rwaldron comment:2

If you copy the nodelist to a plain array that wont be affected by the "live" nature of a getElementsByTagName nodelist it works as expected: http://jsfiddle.net/rwaldron/pc9qs/

Changed May 09, 2011 04:07AM UTC by chris.young-zawada@wmg.com comment:3

Got it - thanks!

Changed May 09, 2011 04:18AM UTC by rwaldron comment:4

You're welcome!