2

I am trying to randomise part of the order of options in a select dropdown. Keeping the first option first and latter two options last.

<select class="form-control" id="return-reason">
    <option value="" disabled="disabled" selected="selected">Please select...</option>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
    <option>Option 4</option>
    <option>Option 5</option>
    <option>Option 6</option>
    <option>Prefer not to say</option>
    <option>Other</option>
</select>

I am working from the idea of randomising the whole list:

var ul = document.querySelector('#return-reason');
for (var i = ul.children.length; i >= 0; i--) {
    ul.appendChild(ul.children[Math.random() * i | 0]);
}

I can place the 'please select' option at the bottom of the HTML list, and by running a slightly amended loop, it will append a randomised list (less the 'please select' option) after 'please select'.

var ul = document.querySelector('#return-reason');
for (var i = ul.children.length + 1; i >= 0; i--) {
    ul.appendChild(ul.children[Math.random() * i | 0]);
}

But this still doesn't take care of keeping the 'prefer not to say' and 'other' options at the bottom. I'm not entirely sure that I can achieve my requirements this way, and it doesn't feel right.

Can anyone kindly advise a way forward.

For my own purposes it doesn't have to be 100% accurately random.

BoffinBrain
  • 6,337
  • 6
  • 33
  • 59
jamesthemullet
  • 443
  • 4
  • 18

2 Answers2

2

First of all it will be better to add an attribute that specify if the option will be randomized or not, like data-randomize for example :

<select class="form-control" id="return-reason">
    <option data-randomize="false" value="" disabled="disabled" selected="selected">Please select...</option>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
    <option>Option 4</option>
    <option>Option 5</option>
    <option>Option 6</option>
    <option data-randomize="false">Prefer not to say</option>
    <option data-randomize="false">Other</option>
</select>

Then you could use a selector $('#return-reason option:not([data-randomize])') to get all the options that you want to randomize, store them in an array and loop through them getting every time a random option from the array replace it in the list then remove it from the array so you will not get duplicate options.

Hope this helps.

//Get the list of options that we will randomize
var selector = '#return-reason option:not([data-randomize])';
var arr      = $(selector).map(function() {
  return $(this).html();
}).get();

//Randomize the list
$(selector).each(function() {
  var index = Math.floor(Math.random() * arr.length);

  $(this).text(arr[index]);
  arr.splice(index, 1);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select class="form-control" id="return-reason">
    <option data-randomize="false" value="" disabled="disabled" selected="selected">Please select...</option>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
    <option>Option 4</option>
    <option>Option 5</option>
    <option>Option 6</option>
    <option data-randomize="false">Prefer not to say</option>
    <option data-randomize="false">Other</option>
</select>
Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
0

If you build your options into an array...

var options = ["Option 1", "Option 2", ...];

...then you can use the answer to how to shuffle an array in JavaScript to randomize your options before inserting them into the select element as you already are.

BoffinBrain
  • 6,337
  • 6
  • 33
  • 59