Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Randomizing $.each loop with Ajax and JSON

I have a json file that I'm pulling to my site using $.ajax. I'm trying to randomize the objects in the array...as in a random order. Here is my json file example:

{
    "greenWasteItems" : [
        {
            "image" : "/img/lawn-clippings.jpeg",
            "text" : "Lawn Clippings"
        },
        {
            "image" : "/img/leaves.jpeg",
            "text" : "Leaves & Weeds"
        },
        {
            "image" : "/img/tree-branches.jpeg",
            "text" : "Tree Branches / Shrubs"
        },
        {
            "image" : "/img/wood-scraps.jpeg",
            "text" : "Wood Scraps"
        }
]
}

I'm using the $.ajax to get the data in the following and I'm trying to make the response I receive random:

$.ajax({
            type: "GET",
            url: "/json/greenwaste.json",
            timeout: 2000,
            success: function(response) {
                //show content
                var arrayRandom = Math.floor(Math.random() * response.length);
                var item = response[arrayRandom];

                $.each(response.greenWasteItems, function(i, item) {
                    var greenW = $('<li class="visible">' + '<img src=' + item.image + '>' + '<p class="text">' + item.text + '</p>' + '</li>');
                    $('.items').append(greenW);
                    greenW.hide().fadeIn(1000);
            }); 
           }
     });

For some reason this is not working. Can anyone help me?

What exactly is not working? Is it receiving everything successfully but not coming out randomly or is it not doing anything you expect it to?

It is receiving everything successfully but not coming out in a randomized order. I've been trying to figure it out with lots of Google searches, but I've been unsuccessful so far.

In that case, I think it may have something to do with the scope of your variables and what happens when you try to pass your 'item' variable to the function in your $.each loop (if that is indeed your goal). Try to console log your item variable before the loop, within the loop, and after the loop. I think you'd see a random response before the loop because you set 'item' equal to 'response' with a random index which should in theory work. Then you would see the whole array in order coming from the $.each loop's function because 'response.greenWasteItems' is what you passed in and it would be indexed with 'i' which is not random. Having 'item' as an argument in the function only grants the illusion that you're passing the variable 'item' you made earlier in your code to your function when really it's just using 'item' as the variable name for 'response.greenWasteItems[i]'. I hope that makes sense and helps.

Maybe you could make a random index array and use it somehow to make everything come out random?

Thank you Michele. What you are saying totally makes sense, but it has not really helped me figure out how to make the code work. Thank you so much for you response though!

2 Answers

Give this a try:

// Handle if your API responds with a 2XX status
var successCallback = function(response) {
    //make sure response.greenWasteItems is coming off the API
    if(response && response.greenWasteItems) {
        //random sort greenWasteItems
        var greenWasteItems = response.greenWasteItems.sort(function() {
          return .5 - Math.random();
        });

        $.each(greenWasteItems, function(i, item) {
            var greenW = $('<li class="visible">' + '<img src=' + item.image + '>' + '<p class="text">' + item.text + '</p>' + '</li>');
            $('.items').append(greenW);
            greenW.hide().fadeIn(1000);
        });
    } else {
        console.warn('check that response.greenWasteItems is in the API response');
    }
},

// Handle if your API responds with a non-2XX status (API fails)
errorCallback = function(){
  console.error('oh shit, your API blew up');
};

$.ajax({
    type: "GET",
    url: "/json/greenwaste.json",
    timeout: 2000,
    success: successCallback,
    error: errorCallback
});

Thank you Riley! That worked perfectly! I could not figure it out, but what you've done makes perfect sense. I do have one question though. I'm not sure I understand the "return .5 - Math.random();". Is the .5 part the same as using Math.floor? Thank you again for your help!

The Math.random() will output a float integer between 0.0 - 1.0 By setting the initial value to 0.5 minus a random float between 0-1, the resulting number will toggle between -0.5 and +0.5. EX: 0.5 - 0.4 = +0.1 || 0.5 - 0.6 = -0.1 || 0.5 - 0.9 = -0.4 || 0.5 - 0.0 = +0.5 | the .sort() method will use these integers to assume that the item being sorted has a number value of one of these randomly generated integers. Based on the random value that is generated, it will sort that item into that place based on the other random integers that were generated.

['this', 'that', 'the other']
Random integers generated in the sort: [-0.5, -0.4, 0.4]
'this' = -0.5
'that = -0.4
'the other' = 0.4
New array order based on random numbers:  ['the other', 'that', 'this']

Very interesting. Thank you for the explanation Riley.