While working on a new JavaScript mockup I needed a way to obtain a random jQuery item. While I could use jQuery(“selector”).get(int) to get a random item, I wanted to have a cleaner way of doing that to keep my code clean.
jQuery ships with great support for extensibility. You can not only extend jQuery with custom functions but filters as well. That is when I thought of the custom “:random” filter, just as you have the standard “:first”, “:last” and “:nth” filters.
Is jQuery capable of returning a random item?
While trying to get the “:random” filter working I’ve stumbled upon a challenge which kept making it all done impossible. As far as my understanding of the jQuery framework goes, it first selects all items based on the selector and then fires the logic defined at the filter to determine whether the particular item should be included in the returned match or not.
As far as I can tell the filter logic is being fired for each match and is supposed to return false if the match should be skipped and true if it should be included in the result. The problematic part here is “fired for each match”: as we are supposed to return a random item we should have one random number and then return only the item of which index is equal to the random number. Because the filter logic is fired for every item you would get a different random number at every run which could result in three scenarios:
- it might actually work and you would get exactly one item
- the filter would return multiple items, eg. random number 0 for the first item and 2 for third.
- the filter would return an empty array: eg. random number 3 for the first item and 0 for the last
The higher the number of matches the smaller the chance for scenario a as the routine for generating random number would be called more often.
Eventually I came with the following solution:
jQuery.jQueryRandom = 0;
jQuery.extend(jQuery.expr[":"],
{
random: function(a, i, m, r) {
if (i == 0) {
jQuery.jQueryRandom = Math.floor(Math.random() * r.length);
};
return i == jQuery.jQueryRandom;
}
});
Each time jQuery calls the “:random” filter the logic is being fired. The i parameter holds the index of the match returned by the selector. If it’s the first element in the match the random number will be generated and stored in the jQueryRandom variable. The random number is being generated based on the total number of matches returned by the selector which can be read from the r parameter. The rest is easy: if the index of the current item is equal to the random number, the current item should be included in the results.
You can use the “:random” filter as follows:
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
<script type="text/javascript">
$().ready(function() {
alert($("li:random").text());
});
</script>
Enjoy!
















July 15th, 2009 at 4:37 pm
Explendid. Very simple and useful.
Thanks
July 15th, 2009 at 5:10 pm
It seems to not be working on any IE.
r.length returns the element\'s text string length (246, for example), not the number of elements. On any other browser, it returns correctly.
August 14th, 2009 at 8:19 pm
I'm wondering how you would use this script for the following:
Have random quotes on a page (li list). You would have the list but jQuery positions/reorders them randomly for each time the page refreshes?
Any ideas?
August 15th, 2009 at 8:42 am
@e11world: to be honest I would create new code to do the job. Instead of retrieving the separate li items using the :random filter I would retrieve the whole list at once, and then do the shuffling.
August 16th, 2009 at 10:28 am
@Alexandre de Oliveira: it took a while, but I've just tested it in IE8 and it works perfectly. Could you provide any more details about your scenario?
December 6th, 2009 at 9:14 pm
Thank you for the awesome snippet of code! I'm currently working on a for-fun project making a story engine similar to text adventure games, and have been looking for good ways to randomize and limit options, and this will work perfectly!
January 4th, 2010 at 10:38 pm
Hi, thanks for the snippet it works fine but I'm getting same error that Alexandre de Oliveira in IE(8)
please, you can fixed it?
thank you!
January 5th, 2010 at 6:32 am
@keo: could you provide some more information on how you're using it (eg. what is your HTML and what is your selector)?
March 28th, 2010 at 11:46 pm
[...] much liking this little bit of jquery code for random selections. http://blog.mastykarz.nl/jquery-random-filter/ [...]
April 19th, 2010 at 6:38 pm
Great snippet.
For some reason I had to change my query slightly from:
$("#section1 .links a:random")
To:
$("#section1 .links").find("a:random").
r.length was considerably higher than it should have been in the first case, but the second selector worked fine.
Thoughts?
July 7th, 2010 at 8:07 pm
Can you provide any additional insight regarding using this snippet to display list items (li) in a random order?
Many thanks for your work!
July 8th, 2010 at 5:01 am
@Renee: the script I showed you allows you to pick a random item, not shuffle list items in a random order. I think you would need a whole different script for your scenario. Have you already tried looking up the jQuery plugins gallery?