User
User

Reputation: 357

jQuery .replaceWith freezes in loop

Today i was coding and i tried something out with the while loop and jQuery .replaceWith but then the loop never stopped and i don't know why.

Here is my html code:

<div class="x"></div><div class="x"></div><div class="x"></div>

and here is my javascript code:

while($(".x").length !== 0) {
 $(".x:nth-child(1)").replaceWith('<div id="x"></div>');
}

This code freezes the browser but i don't know why.

I also tried this:

while($(".x").length !== 0) {
 $(".x:nth-child(1)").remove();
}

and that works.

What i want to do is replace all elements with class .x with <div id="x"></div>

Any idea what was going wrong in my code?

Upvotes: 2

Views: 434

Answers (3)

Oriol
Oriol

Reputation: 288250

The problem is that .x:nth-child(1) matches the element with class x which is the first child of his parent.

In your first case, you replace the first match with another element, so other elements of class x won't be the first child of its parent.

In your second code, you remove them, so the next element with class x will be the first child.

Moreover,

  • Avoid using $ in loops. Searching the DOM is expensive, better store the result in a variable before the loop.
  • You can just test .length instead of .length !== 0
  • Avoid creating elements from static strings in a loop. You can create it before and clone it inside the loop.
  • To iterate all elements that match a selector, better use each
  • Be careful when setting ids, they must be unique in the document.

Upvotes: 5

T.J. Crowder
T.J. Crowder

Reputation: 1074475

The reason that's freezing up is that you're looping for as long as you have .x elements, but inside your loop, you're only ever going to replace one of them, because the selector .x:nth-child(1) will only match an element if it has class x and it's the first element in its parent element. It doesn't pick the first .x element. So you replace the first, then loop endlessly not doing replacements at all.

You'd be better off using each:

$(".x").each(function() {
  $('<div id="x"></div>').replace(this);
});

That's assuming you really need to replace the elements, as opposed to simply removing the class and assigning an id to them. If that's all you need to do, Ehsan's answer has you covered.


But be sure to give each one a different id. Only one element in a document is allowed to have a given id value.

Upvotes: 2

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

you can achieve it using $.each(), the way you are doing while loop will never exit as condition will always remain true.

and the way you are doing will wipe content of divs.

$(".x").each(function() {
 $(this).removeClass("x"); // remove class x
 $(this).prop("id","x");  // add id x
});

FIDDLE:

http://jsfiddle.net/ehsansajjad465/04tdd2s9/

NOTE:

Note that i have demonstrated how you can do this, but in general id of every element must be unique.

Upvotes: 1

Related Questions