jQuery :random filter

, ,

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:

  1. it might actually work and you would get exactly one item
  2. the filter would return multiple items, eg. random number 0 for the first item and 2 for third.
  3. 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!

Technorati Tags: ,

46 Responses to “jQuery :random filter”

  1. Alexandre de Oliveira Says:

    Explendid. Very simple and useful.

    Thanks

  2. Alexandre de Oliveira Says:

    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.

  3. e11world Says:

    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?

  4. Waldek Mastykarz Says:

    @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.

  5. Waldek Mastykarz Says:

    @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?

  6. David Millar Says:

    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!

  7. keo Says:

    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!

  8. Waldek Mastykarz Says:

    @keo: could you provide some more information on how you're using it (eg. what is your HTML and what is your selector)?

  9. journalweblogthing » Twitter Weekly Updates for 2010-03-28 Says:

    [...] much liking this little bit of jquery code for random selections. http://blog.mastykarz.nl/jquery-random-filter/ [...]

  10. Allain Lalonde Says:

    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?

  11. Renee Says:

    Can you provide any additional insight regarding using this snippet to display list items (li) in a random order?

    Many thanks for your work!

  12. Waldek Mastykarz Says:

    @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?

  13. Philip Says:

    I used it for a random starting carousel using sorgalla.com Jcarousel. Thank you very much, here is the example code:

    $(".banner_carousel").jcarousel({
    auto:6,
    start:$.random($(".banner_carousel li").size()),
    scroll:2,
    wrap: 'circular'

    });

  14. Philip Says:

    Sorry using this one:

    jQuery.extend({
    random: function(X) {
    return Math.floor(X * (Math.random() % 1));
    },
    randomBetween: function(MinV, MaxV) {
    return MinV + jQuery.random(MaxV – MinV + 1);
    }
    });

  15. Emilio Says:

    This also is proving buggy for me in IE8+.
    Wonder why?

  16. Emilio Says:

    let me just follow up on that. It looks like this happens in compatibility mode – so IE7-. When I check out r.length it is way off pre IE8. Wonder if anyone has noticed anything similar?

  17. Devin R. oLSEN Says:

    I too have had up and down results with both IE7 and IE8 using this filter. My only guess is that IE is randomly selecting some kind of empty node assuming its an element and the rest is history.

    One time I fixed it by helping the filter by identifying both the element's parent and its type:

    $('#parentElm div.someElmClass:random').show();

    Sometimes however, this also fails to kick IE into gear. Any insight?

  18. jQuery.rand() « afEkenholm Web Design Says:

    [...] a bit messy and performs too many tasks and permutations for me to be satisfied. Another one is the :random filter, but that only selects one element. There is also a nice little jquery.shuffle.js that [...]

  19. Jordan Says:

    Cool thanks for sharing! This might not work for all purposes as afEkenholm politely points out…there's a good discussion on it here:
    http://stackoverflow.com/questions/962802/is-it-correct-to-use-javascript-array-sort-method-for-shuffling

  20. 15 Powerful jQuery Tips and Tricks for Developers | Tutorialzine Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  21. 15 Powerful jQuery Tips and Tricks for Developers | Tutorialzine Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  22. Kirn Says:

    what are the arguments to that function? you explained 2 of them but could you let me know what the other two are for? thanks a lot, great work!

  23. Waldek Mastykarz Says:

    @Kirn: those are standard parameters that jQuery passes to its filters. See jQuery documentation for more details.

  24. 15 Powerful jQuery Tips and Tricks for Developers « Cândido Sales Blog Says:

    [...] function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  25. 15 Powerful jQuery Tips and Tricks for Developers | Newformz Says:

    [...] new function to the $ .expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  26. Andrea Says:

    Phillip, I'm curious how you using this with jCarousel. I put in your scripts and it didn't work… is there another element you had to write somewhere else? Or something else you had to take out?

    thanks

  27. Philip Says:

    I used the JQUERY.RAND() method:
    see http://www.labs.skengdon.com/rand

  28. Andrea Says:

    Hi Phillip- thanks for your answer. Sorry to be a dope, but in which file and where do you place that code? I'm just getting started with jquery.
    Thanks.

  29. Philip Says:

    Simple just call the random from the callback:

    $(".banner_carousel").jcarousel({
    auto:6,
    start:$.random($(".banner_carousel li").size()) // <— HERE!
    ,scroll:2,
    wrap: 'circular'
    });

  30. 15 Powerful jQuery Tips and Tricks for Developers | ABDULLAH TURHAN Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  31. 15 Powerful jQuery Tips and Tricks for Developers | DKPHP Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  32. Criando um seletor :random em jQuery | Moises Says:

    [...] eu estava navegando em um site bem legal, quando encontrei um código muito simples, porem extremamente útil em diversas [...]

  33. 15个强大的jQuery开发的提示和技巧 - 紫客网-张慧敏个人原创博客 Says:

    [...] function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  34. 15个强大的jQuery开发的提示和技巧 - 紫客网-张慧敏个人原创博客 Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  35. 15 should be concerned about the jQuery developer skills and experience - Open News Says:

    [...] to add a new method to the $. Expr [':'] object. A great way to Waldek Mastykarz use the blog mentioned: Create a random element to return selector. You can modify the following [...]

  36. 15个值得开发人员关注的jQuery开发技巧和心得 | Flash开发者大会 Says:

    [...] 上面我提到过,jQuery添加它自己的选择器过滤。除了类库,你可以添加自己的过滤器。只需要添加一个新的方法到$.expr[':']对象。一个非常棒的使用方式是Waldek Mastykarz的博客中提到的:创建一个用来返回随机元素的选择器。你可以修改下面代码: [...]

  37. 15 Powerful jQuery Tips and Tricks for Developers « Webpage Worker Blog Says:

    [...] function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  38. 15 Powerful jQuery Tips and Tricks for Developers | Webpage Worker Blog Says:

    [...] function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  39. Eric Says:

    I ran into the same problem as Allain — the filter doesn't work if you qualify the element with a parent selector. For example, $("ul.foo li:random") will select ANY list item, not just the ones in the "foo" list. His workaround avoids the problem.

  40. Tips and Tricks Optimize jQuery Powerful For Developers | My Blog Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  41. BLOG » 15 важных советов и рекомендаций в использовании jQuery для разработчиков Says:

    [...] применения был представлен Уолдеком Мастикарзем в его блоге: создание селектора для получения случайного [...]

  42. Rhyno Says:

    Worked fine for me in IE9. Haven't tried IE8 yet.
    Very cool little filter.
    Used it to help randomize img ordering for a filmstrip of photo's

  43. XwareCreatives™ Tech blog - 15 Powerful jQuery Tips and Tricks for Developers Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  44. XwareCreatives™ Creative blog – 15 Powerful jQuery Tips and Tricks for Developers Says:

    [...] function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

  45. 15个值得开发人员关注的jQuery开发技巧和心得 | W3Dev Says:

    [...] Mastykarz的博客中提到的:创建一个用来返回随机元素的选择器。你可以修改下面代码: [...]

  46. 15 Powerful jQuery Tips and Tricks for Developers | Tutorialzine | Hugo Mineiro Portfolio Says:

    [...] a new function to the $.expr[':'] object. One awesome use case was presented by Waldek Mastykarz on his blog: creating a selector for retrieving a random element. You can see a slightly modified version of [...]

Leave a Reply

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS
Copyright © 2007 - 2013 Waldek Mastykarz

Creative Commons License