Please tell me, I can’t understand what’s wrong.
Task: There is a set of house elements (can be anything). I hide all elements, take a set of elements from the DOM by class, randomly select, for example, 5 elements, add them to an empty array and want to output them only from the array by iterating over each one, but in order. As a result, the numbering is displayed inconsistently... What's the matter? Is it enumerating out of order?
$(document).ready(function () {
var elems = $(".test");
var items_ = [];
for (var i = 0; (i < 5) && (i < elems.length); i++) {
var r = Math.floor(Math.random() * (elems.length - i)) + i;
var res = elems[r];
elems[r] = elems[i];
elems[i] = res;
items_.push(res)
}
$('.test').fadeOut('slow', function(){
$(items_).each(function (index) {
$(this).find('.number_test').text(index + 1);
$(this).fadeIn('slow')
});
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="test">First - <span class="number_test"></span></div>
<div class="test">Second - <span class="number_test"></span></div>
<div class="test">Third - <span class="number_test"></span></div>
<div class="test">Fourth - <span class="number_test"></span></div>
<div class="test">Fifth - <span class="number_test"></span></div>
<div class="test">Sixth - <span class="number_test"></span></div>
<div class="test">Seventh - <span class="number_test"></span></div>
<div class="test">Eighth - <span class="number_test"></span></div>
<div class="test">Ninth - <span class="number_test"></span></div>
<div class="test">Tenth - <span class="number_test"></span></div>
The order of the elements in your items_
array is different from the order these elements have in the DOM. This explains why the first element in the array might not be the topmost element (in their visual order) among those that are in the array.
If you want the order in the array to also be the visual order of these elements, then you really need to move those elements in the DOM.
You can do that move by simply adding those selected elements again (in the order they are put in the array) to their parent container element:
$('.test').parent().append(items_);
Add this statement in the callback function that runs after the fade out, and it will work. Be aware though that now the order of the elements has really changed, so that if you would unhide also the other elements, you will not see the original order.
The each
loop is executed (as a whole) multiple times, because the fadeOut
callback is executed for every element that matches the .test
selector. This is obviously overkill: you only need that fadeOut
callback to execute once. You can do that by getting the promise and chain a then
call to it:
$('.test').fadeOut('slow').promise().then(function(){
$('.test').parent().append(items_);
$(items_).each(function (index) {
$(this).find('.number_test').text(index + 1);
$(this).fadeIn('slow');
});
});