Document ready function, free weather app

Why Javascript refuses to execute the getweather function inside document ready function? If i click the button the getweather function works properly, its just refuses to work on page load. There must be something really easy im missing, but i really dont know what.

var city="";
var unit="metric";
var units =  {
             "metric"  : {
             "apihandle" : "metric",
             "windtext"  : "m/s",
             "temptext"  : "Celsius",
            },
             "imperial" : {
             "apihandle" : "imperial",
             "windtext"  : "miles/h",
             "temptext"  : "Fahrenheit",
            }
             };

function getcity(){
$.getJSON("http://freegeoip.net/json/?callback=?",function(datas){
    yourlocation=datas.city;
  });
return yourlocation;
}

function apiUrl(unit){
  var city=getcity();
return "http://api.openweathermap.org/data/2.5/weather?q="+city+"&APPID=XXXXXXXXXXXXXXXX&units="+unit+"";
}

function getweather(test){
  
 $.getJSON(apiUrl(test.apihandle),function(data){
    
  var temp = data.main.temp;
  var description = data.weather[0].description;
  var icon = data.weather[0].icon;
  var wspeed = data.wind.speed;
  var html = '<img src="http://openweathermap.org/img/w/' + icon + '.png" alt="Weather Icon">' + '<p> ' + Math.round(temp) + ' ' + test.temptext + ', ' + description + '<br> Wind Speed: ' + wspeed + " " + test.windtext + '</p><p>' + city + '</p>';
    $("article").html(html);
});
};

$("button").on("click",function(){
    if (unit==="metric") {getweather(units.metric);}
    else {getweather(units.imperial)}
    unit = unit === "imperial" ? "metric" : "imperial";
    if (unit=="metric") {
      $("button").text("Change to Metric");
    }
    else {
      $("button").text("Change to Imperial");
      }
 });

$(document).ready(function(){
    getweather(units.metric);
}); //document ready

It appears that the page would crash initially within the getcity function call. Trying to return yourlocation from that function is going to fail because of the way the getJSON call is working here (that it is being deferred). Your return statement will happen before the JSON data has been retrieved from the freegeoip.net site.

Somewhere along the way city is getting set properly after that initial call on document ready.

One way I can think of to fix it would be to set your city variable at the top to have an initial city value and then change the way getcity works…first change its name to setcity as we are going to be setting the city variable and not returning it anymore. Rewriting it like so:

  function setcity(){
    $.getJSON("http://freegeoip.net/json/?callback=?",function(datas){
        city=datas.city;
      });
    }

Also apiURL would change to this then:

function apiUrl(unit){
  setcity();
 return "http://api.openweathermap.org/data/2.5/weather?q="+city+"&APPID=XXXXXXXXXXXXXXXX&units="+unit+"";
}

Feel free to try out those changes and let us know. If you could setup a full codepen example it would help us debug also :slight_smile:

1 Like

thanks , you are right, your changes made it work.

Getweather now gets correctly executed on page load, but only with the preset value. After clicking the button it retrieves the correct city, while actually doing the same function again? I still dont understand this behaviour. Shouldnt this also work without presetting a city?

Is there a way to make this work? or is my approach just not suitable to make it work?

It can work on load…but you have to change a bit more code and structure of the calls. It is a timing issue as to why it didn’t currently work on document ready.

1 Like

yeah i guess so, im kinda losing my mind on this and its 2.am here…

i tried some stuff (no more return functions) but always the same, he only gets it on the second run, maybe i find out tomorrow.

here is my codepen, maybe u can take a quick look, http://codepen.io/moorli/pen/yVdjNp?editors=1010

thx for the help

Just move the getweather call from document ready to the callback of getcity (that way you know not to get weather data until you have the city set). Below is entire code changed from your codepen file that you can just copy/paste.

var city="test";
var unit="metric";
var url="";
//var url="http://api.openweathermap.org/data/2.5/weather?q="+city+"&APPID=949eb5e75582e074f256f1a98afb10f1&units="+unit+"";
var units =  {
             "metric"  : {
             "apihandle" : "metric",
             "windtext"  : "m/s",
             "temptext"  : "Celsius",
            },
             "imperial" : {
             "apihandle" : "imperial",
             "windtext"  : "miles/h",
             "temptext"  : "Fahrenheit",
            }
             };

function getcity(unit){
$.getJSON("http://freegeoip.net/json/?callback=?",function(datas){
    city=datas.city;
  getweather(unit);
  });

}

function apiUrl(unit){
  url= "http://api.openweathermap.org/data/2.5/weather?q="+city+"&APPID=949eb5e75582e074f256f1a98afb10f1&units="+unit+"";
}

function getweather(test){
  apiUrl(test.apihandle);
 $.getJSON(url,function(data){
    
  var temp = data.main.temp;
  var description = data.weather[0].description;
  var icon = data.weather[0].icon;
  var wspeed = data.wind.speed;
  var html = '<img src="http://openweathermap.org/img/w/' + icon + '.png" alt="Weather Icon">' + '<p> ' + Math.round(temp) + ' ' + test.temptext + ', ' + description + '<br> Wind Speed: ' + wspeed + " " + test.windtext + '</p><p>' + city + '</p>';
    $("article").html(html);
});
};

$("button").on("click",function(){
    if (unit==="metric") {getweather(units.metric);}
    else {getweather(units.imperial)}
    unit = unit === "imperial" ? "metric" : "imperial";
    if (unit=="metric") {
      $("button").text("Change to Metric");
    }
    else {
      $("button").text("Change to Imperial");
      }
   
   });


$(document).ready(function(){
  getcity(units.metric);
}); //document ready
1 Like

thx a lot, works now :relaxed:

one last question, so because getjson works async , thats why getweather has to be the callback of getcity?

1 Like

Yep - that is correct!