1

I have lists of addresses inside php files and the files are labelled by country. So in a list called uk I could have 12 list items of addresses. But on my homepage I am trying to use jQuery to calculate the values of each country and then put the value inside a div on that country map so that it indicates that uk was x addresses, usa has x addresses and so forth.

The code I have put together below works up till the .ajax and then in console.log it echos 1 single country instead of a list of countrys.

HTML

<div class="right map">
    <div class="canada" data-name="Canada"></div>
    <div class="usa" data-name="USA"></div>
    <div class="uk" data-name="UK"></div>
    <div class="ireland" data-name="Ireland"></div>
    <div class="spain" data-name="Spain"></div>
    <div class="portugal" data-name="Portugal"></div>
    <div class="italy" data-name="Italy"></div>
    <div class="australia" data-name="Australia"></div>
</div>

jQuery

$('.map div').each(function() { 
    $this = $(this);
    country = $this.attr("class");
    console.log(country);
    $.ajax({
        url : "/assets/inc/coe/"+country+".php",
            success : function (data) {
                console.log($('.map div.'+country));
                $('.map div.'+country).text($(data).find('li').size());
            }
        }); 
});

php files

<ul>
    <li>
        <strong>Company Name</strong>
        123 Fake Street<br />
        Fakesville<br />
        <a href="#">Link</a>
    </li>
    <li>
        <strong>Company Name</strong>
        123 Fake Street<br />
        Fakesville<br />
        <a href="#">Link</a>
    </li>
</ul>

console.log

canada
usa
uk
ireland
spain
portugal
italy
australia
[div.australia]
[div.australia]
[div.australia]
[div.australia]
[div.australia]
[div.australia]
[div.australia]
[div.australia]
Elliot B.
  • 17,060
  • 10
  • 80
  • 101
ngplayground
  • 20,365
  • 36
  • 94
  • 173

3 Answers3

3

The problem you're having is that country is not in the scope of your success function. When your success function is invoked, it looks up the scope chain to find country. But because your AJAX runs asynchronously, the loop will always finish before success is invoked, and country will therefore always be the last country set in the loop.

To resolve this issue, you need to need to nest your success function in a new scope level and pass in country by value. In my example below, I accomplish that with an immediate executing function, that returns your original success function:

Change this:

$.ajax({
        url : "/assets/inc/coe/"+country+".php",
            success : function (data) {
                console.log($('.map div.'+country));
                $('.map div.'+country).text($(data).find('li').size());
            }
        }); 

To this:

$.ajax({
        url : "/assets/inc/coe/"+country+".php",
            success : (function (country) {
                return function(data) {
                    console.log($('.map div.'+country));
                    $('.map div.'+country).text($(data).find('li').size());
                };
            })(country)
        }); 

It's all about closures.

Community
  • 1
  • 1
Elliot B.
  • 17,060
  • 10
  • 80
  • 101
1

Make your ajax request synchronous. Adding async: false will work. It will wait for the current ajax request to get finished before starting another. So the reference to country will correctly map to the correct country div

$('.map div').each(function() { 
$this = $(this);
country = $this.attr("class");
console.log(country);
$.ajax({
    url : "/assets/inc/coe/"+country+".php",
    async: false,
        success : function (data) {
            console.log($('.map div.'+country));
            $('.map div.'+country).text($(data).find('li').size());
        }
    }); 

});

Elliot B.
  • 17,060
  • 10
  • 80
  • 101
Hary
  • 5,690
  • 7
  • 42
  • 79
  • @DonaldSutherland: While this solution should work, be aware that when setting `async: false` that your UI will lock-up during each individual request. If a request will then take a little while it can seem to the user like the browser is frozen. – Nope Jan 29 '13 at 08:40
  • 1
    @DonaldSutherland `Elliot B` answer would be better – Hary Jan 29 '13 at 08:51
0

It's a closure problem and the asyncness of ajax; its got a handle on the country variable which beats all the ajax calls, so its always at the last setting (australia).

Write a new property to the ajax function/object

$.ajax({
        url : "/assets/inc/coe/"+country+".php",
        country: country,
            success : function (data) {
                var country = this.country;
                console.log($('.map div.'+country));
                $('.map div.'+country).text($(data).find('li').size());

            }
        }); 
jenson-button-event
  • 18,101
  • 11
  • 89
  • 155