Bug Tracker

Opened 12 years ago

Closed 12 years ago

Last modified 12 years ago

#9181 closed bug (invalid)

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

Reported by: chris.young-zawada@… 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>

Change History (4)

comment:1 Changed 12 years ago by Rick Waldron

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.

comment:2 Changed 12 years ago by Rick Waldron

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/

comment:3 Changed 12 years ago by chris.young-zawada@…

Got it - thanks!

comment:4 Changed 12 years ago by Rick Waldron

You're welcome!

Note: See TracTickets for help on using tickets.