0

I have a section with few divs inside:

<section class="list">
 <div class="item"></div>
 <div class="item"></div>
 <div class="item"></div>
</section>

I prepended an extra item in the section with jQuery:

<section class="list">
 <div class="extra-item"></div>
 <div class="item"></div>
 <div class="item"></div>
 <div class="item"></div>
</section>

What I want is to randomly sort this extra prepended item within the section – so all the other items are preserving its order but this extra one is sorted on every page refresh:

i.e 1:

<section class="list">
 <div class="item"></div>
 <div class="item"></div>
 <div class="item"></div>
 <div class="extra-item"></div>
</section>

i.e 2:

<section class="list">
 <div class="item"></div>
 <div class="item"></div>
 <div class="extra-item"></div>
 <div class="item"></div>
</section>

etc...

With the code below I managed to randomly sort all the items inside the section; but would it be possible to simply re-order this prepended item and keep the rest in its order?

$(function () {
    var parent = $(".list");
    var divs = parent.children();
    while (divs.length) {
        parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
    }
});

Thanks

Anta
  • 141
  • 1
  • 9

2 Answers2

1

Rather than attempt to sort after your extra-item has been added, you can insert it into a random location using

$(".list>div").eq(__random_position__).before("<div class='extra-item'>")

To get the random position, use:

var children = $(".list").children();
var position = Math.floor(Math.random() * children.length);

however, if you also want it to appear at the start of the list and at the end of the list, then it needs a bit of extra handling:

var children = $(".list").children();
var position = Math.floor(Math.random() * (children.length + 1));
if (position == children.length)
  children.eq(position-1).after('<div class="extra-item"></div>');
else
  children.eq(position).before('<div class="extra-item"></div>');
.list > div { height:20px; margin-bottom: 0.5em; }
.item { border: 1px solid green; }
.extra-item { border: 1px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="list">
 <div class="item"></div>
 <div class="item"></div>
 <div class="item"></div>
</section>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
1

a solution whichs randomize the action and the position:

// i suppose extra-item is already in the list
const pos = Math.floor(Math.random() * ($(".list .item").length));
const action = Math.floor(Math.random() * 2);

var item = $(".extra-item").detach();

if(action == 0){
  item.insertBefore(`.item:nth(${pos})`);
}else{
  item.insertAfter(`.item:nth(${pos})`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="list">
 <div class="extra-item">111</div>
 <div class="item">1</div>
 <div class="item">2</div>
 <div class="item">3</div>
</section>

To avoid memory leak, use detach() instead of remove();

Frenchy
  • 16,386
  • 3
  • 16
  • 39
  • Thanks a lot, this worked like a charm. Is there a known reason why the document 'jumps/scroll' a bit on every refresh? – Anta Mar 09 '21 at 07:27
  • its difficult to answer without seing the problem. and how you refresh the page..when you refresh , you rebuild totally the html page, following the number of items, you could have scrolling..its just a suggestion..if you dont see , maybe open a new question with the complete code to see what it happens (sorry for my english, hope you understant) – Frenchy Mar 09 '21 at 08:17