Reputation: 3104
I have this code:
var elementSelector = 'select.myClass';
$(elementSelector).each(function(i){
/*
* if (several conditions return true) {
*/
doSomeDOMChanges(); //Change the DOM and add several more <select class="myClass">
/*
* }
*/
});
Problem is, within that loop, $(elementSelector)
is not reevaluated, and its' size remains the same throughout the entire loop. $(elementSelector).length
for example would stay 18
, even though it actually increased to 20
within the 4th iteration.
My question is, how to force JQuery to re-select $(elementSelector)
on the next iteration (without "resetting" the loop / repeating previous iterations, of course).
Thank you.
Upvotes: 1
Views: 84
Reputation: 350137
If it is guaranteed that the modified DOM content occurs further in the document than the element that you are currently visiting in the loop, then you could rely on DOM methods that return a live NodeList, such as:
getElementsByTagName
getElementsByClassName
getElementsByName
children
Here is a demo where the DOM is extended with one more select
element, when the value of the current select
element has less than 5 characters. The newly inserted select
element will have options which have values that are 1 character longer.
function doSomeDOMChanges(select) {
$(select).after($("<select>").addClass("myClass").append(
$("<option>").text($(select).val() + "0"),
$("<option>").text($(select).val() + "1"),
$("<option>").text($(select).val() + "2")
));
}
for (var select of document.getElementsByTagName("select")) {
if ($(select).is(".myClass")) {
if ($(select).val().length < 5) {
doSomeDOMChanges(select);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="myClass">
<option>2
<option selected>3
<option>5
</select>
The downsides:
$()
, using the power of a CSS selectorIf one of these points is a problem, you could just make the jQuery selection again, and keep a Set of the elements you had already visited. The next demo makes DOM changes before the currently visited element:
function doSomeDOMChanges(select) {
$(select).before($("<select>").addClass("myClass").append(
$("<option>").text($(select).val() + "0"),
$("<option>").text($(select).val() + "1"),
$("<option>").text($(select).val() + "2")
));
}
let visited = new WeakSet;
let selector = "select.myClass";
for (let more = true; more; null) {
more = false;
$(selector).each(function() {
if (visited.has(this)) return;
visited.add(this);
if ($(this).val().length < 5) {
doSomeDOMChanges(this);
more = true;
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="myClass">
<option>2
<option selected>3
<option>5
</select>
Upvotes: 1
Reputation: 492
mark used classes with an attribute or some class, and select which are not used
var elementSelector = $('select.myClass:not[data-used=1]');
$(elementSelector).each(function(i){
$(this).data('used', 1)
if (several condition return true) {
doSomeDOMChanges(); //Change the DOM and add several more <select class="myClass">
}
});
Upvotes: 1