Help With Loop Logic

I’m testing Getty Images api, pulling in images from the site and I would like them to be in a particular order. The order is determined by a googlesheet, which also contains the image “id” to be pulled in. I can’t share the api key, but the code works.

The images appear when I preview the page, but the order in which they appear does not correspond to the image number id which populates an inner.HTML of another element, which in future will act as a “credit”.

The issue for me is that there are two endpoints to the API, one to pull in creative images and one for editorial images. I need a mixture of both, hence the if and else statements.

 var apiKey = 'xxxxxxxxxxxxxxx';
 
 var data = hypeDocument.customData;
 
 var MyURL = "";
 
 var CountUp = 0; 
 
 
for (var i = 0; i < data.feed.entry.length; i++) {

var Type = data.feed.entry[i].gsx$type.$t; 
 
var ImageNumber = document.getElementsByClassName('ImageNumber')[i];

var Pic = document.getElementsByClassName('pic')[i];



 if (Type == "editorial"){
 
 ImageNumber.innerHTML = data.feed.entry[i].gsx$image.$t + ", EDITORIAL";
 MyURL = "https://api.gettyimages.com/v3/search/images/editorial?phrase=" + data.feed.entry[i].gsx$image.$t + "&fields=high_res_comp";   
  
 
 $.ajax(
    {
        type:'GET',
        
        url:MyURL,
        
        beforeSend: function (request)
            {
             request.setRequestHeader("Api-Key", apiKey)            

            }})
            
    .done(function(data){
      
          var Pic = document.getElementsByClassName('pic')[CountUp];
           
          Pic.innerHTML = '<div style="width: 100%; height: 100%; position: absolute; background-position: center left !important; background-image: url(' + data.images[0].display_sizes[0].uri + '); overflow: hidden; background-size: cover !important; -webkit-background-size: 100%; display: inline; z-index: 1; opacity: 1; background-repeat: no-repeat no-repeat;"></div>';        
          
          CountUp += 1;
          
    })
    
 }
 else  {
 ImageNumber.innerHTML = data.feed.entry[i].gsx$image.$t + ", CREATIVE";  
 MyURL = "https://api.gettyimages.com/v3/search/images/creative?phrase=" + data.feed.entry[i].gsx$image.$t + "&fields=high_res_comp";

 $.ajax(
    {
        type:'GET',
        
        url:MyURL,
        
        beforeSend: function (request)
            {
             request.setRequestHeader("Api-Key", apiKey)            

            }})
            
    .done(function(data){
           
           var Pic = document.getElementsByClassName('pic')[CountUp];
           
           Pic.innerHTML = '<div style="width: 100%; height: 100%; position: absolute; background-position: center center !important; background-image: url(' + data.images[0].display_sizes[0].uri + '); overflow: hidden; background-size: cover !important; -webkit-background-size: 100%; display: inline; z-index: 1; opacity: 1; background-repeat: no-repeat no-repeat;"></div>';         

           CountUp += 1;

    })
 
 }

}

It is because AJAX is an asynchronous action. Meaning every time you fire them up the count variable should be fixed and not determined when the result reports back. Because the latter orders them in time of completed execution.

Hi @MaxZieb, Is there a workaround?

Yes, using a function scope. Put your whole logic inside the loop into a function with the parameters you need. The scope should then keep the values unique (no need to count up or re-fetch Pic etc.). Quick and ugly and not tested but you get the idea. You can obviously make that function scoping much more narrow and extract the if/else to the loop etc…

var apiKey = 'xxxxxxxxxxxxxxx';
var data = hypeDocument.customData;
var MyURL = "";

for (var i = 0; i < data.feed.entry.length; i++) {
    var Type = data.feed.entry[i].gsx$type.$t;
    var ImageNumber = document.getElementsByClassName('ImageNumber')[i];
    var Pic = document.getElementsByClassName('pic')[i];
    loadData(Type,ImageNumber,Pic, data, i);
}

function loadData(Type,ImageNumber,Pic, data, i){
    if (Type == "editorial") {
        ImageNumber.innerHTML = data.feed.entry[i].gsx$image.$t + ", EDITORIAL";
        MyURL = "https://api.gettyimages.com/v3/search/images/editorial?phrase=" + data.feed.entry[i].gsx$image.$t + "&fields=high_res_comp";
        $.ajax({
                type: 'GET',
                url: MyURL,
                beforeSend: function (request) {
                    request.setRequestHeader("Api-Key", apiKey)
                }
            })
            .done(function (data) {
                Pic.innerHTML = '<div style="width: 100%; height: 100%; position: absolute; background-position: center left !important; background-image: url(' + data.images[0].display_sizes[0].uri + '); overflow: hidden; background-size: cover !important; -webkit-background-size: 100%; display: inline; z-index: 1; opacity: 1; background-repeat: no-repeat no-repeat;"></div>';
            })

    } else {
        ImageNumber.innerHTML = data.feed.entry[i].gsx$image.$t + ", CREATIVE";
        MyURL = "https://api.gettyimages.com/v3/search/images/creative?phrase=" + data.feed.entry[i].gsx$image.$t + "&fields=high_res_comp";
        $.ajax({
                type: 'GET',
                url: MyURL,
                beforeSend: function (request) {
                    request.setRequestHeader("Api-Key", apiKey)
                }
            })

            .done(function (data) {
                Pic.innerHTML = '<div style="width: 100%; height: 100%; position: absolute; background-position: center center !important; background-image: url(' + data.images[0].display_sizes[0].uri + '); overflow: hidden; background-size: cover !important; -webkit-background-size: 100%; display: inline; z-index: 1; opacity: 1; background-repeat: no-repeat no-repeat;"></div>';
            })
    }
}
3 Likes

Wow! Thanks @MaxZieb.

So, just for my understanding. The variables in the first for loop are “wrapped up” into a function “loadData” and as a result these variables, such as “Pic”, “i” are now accessible by the AJAX call which runs within the “loadData”?

Thanks again. It works brilliantly. Not sure what’s “ugly” about it…

If you want to understand it read up on function and variable scoping. Basically your index i and your loop was finished counting when your asynchron Ajax callback was fired.

Well, a lot of requests in this setup and the function wrapper could be made more reusable. But that is probably only in the eye of the beholder.

2 Likes