metaphor
metaphor

Reputation: 470

Temperature conversion with openweathermap API

I'm building a weather app with Openweathermap API. The app already work but i have problem with temperature converter that still doesn't work.

Here is my HTML:

   <div class='valign col s6 text-style'>
       <div id="iconTemp">
           <div id="icon"></div>
           <div id="temp"></div>
       </div>  
       <div class='divider'></div><br>

       <div class="text-style-details">
           <div class="location"></div>
           <div id="conditions"></div>
           <div id="wind"></div>
       </div>  
   </div>

And my javascript:

 <script type="text/javascript">
      function ToC() {
        var strIn = parseInt(temperature);

        if(isNaN(strIn)) {
          alert("Not a Number");
        } else {
          var f = parseFloat(strIn);
          var c = (f - 32) * 5/9;

          var r = Math.round(c * 100)/100;
          parseInt(temperature) = r.toString();   
        }
    }

    function ToF() {
        var strIn = parseFloat((temperature).toFixed(1));

        if(isNaN(strIn)) {
          alert("Not a Number");
        } else {
          var c = parseFloat(strIn);
          var f = (c * 9/5) + 32;

          var r = Math.round(f * 100)/100;
          parseFloat((temperature).toFixed(1)) = r.toString();   
        }
    }

$(document).ready(function() {

    getLocationData();

    function getLocationData() {
      $.get("http://ipinfo.io", function(location) {
        console.log(location);

        $('.location')
          .append(location.city + ", ")
          .append(location.region);

        var units = getUnits(location.country);
        getWeatherData(location.loc, units);

      }, "jsonp");

    }

    function getWeatherData(loc, units) {
      lat = loc.split(",")[0]
      lon = loc.split(",")[1]

      var appid = "&APPID=123456abcde"

      var url = 'http://api.openweathermap.org/data/2.5/weather?lat=' + lat + '&lon=' + lon + "&units=" + units + appid;

      console.log(url);

      $.get(url, function(weather) {
        var windDir = WindDirection(weather.wind.deg);
        var temperature = weather.main.temp;
        var unitLabel;

        if (units === "imperial") {
          unitLabel = "<a href='#'>F</a>/<a href='#' onclick='ToC()'>C</a>";
          // temperature = parseFloat((temperature).toFixed(1));
        } else {
          unitLabel = "<a href='#' onclick='ToF()'>C</a>";
          // temperature = parseInt(temperature);
        }

        // temperature;

        // temperature = parseInt(temperature);
        // temperature = parseFloat((temperature).toFixed(1));



        console.log(weather);

        $('#icon')
          // .append("<img src='http://openweathermap.org/img/w/" + weather.weather[0].icon + ".png'>");
          .append("<i class='wi wi-owm-"+weather.weather[0].id+"'></i>");
                   // <i class="wi wi-owm-200"></i>

        $('#temp').append(temperature + "&deg; " + unitLabel);
        $('#conditions').append(weather.weather[0].description);
        $('#wind').append(windDir + " " + weather.wind.speed + " knots");

      }, "jsonp");

    };



    function WindDirection(dir) {
      var rose = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
      var eightPoint = Math.floor(dir / 45);
      return rose[eightPoint];
    }

    function getUnits(country) {
      var imperialCountries = ['US', 'ID', 'SG', 'MY', 'BS', 'BZ', 'KY', 'PW'];

      if (imperialCountries.indexOf(country) === -1) {
        var units = 'metric';
      } else {
        units = 'imperial';
      }

      console.log(country, units);
      return units;
    }

  });
</script>

The app pict:

enter image description here

I created function ToC (convert F to C) and ToF ( convert C to F), when i click the label i get an error message "Uncaught ReferenceError: ToC is not defined". I want the app temperature value will be change when i click C (celcius) and F (fahrenheit).

Any help would be appreciated greatly, thank you.

Upvotes: 0

Views: 6426

Answers (2)

mjrdnk
mjrdnk

Reputation: 233

Although writing those kind of functions for training is always good, answering your main question according to openweathermap API unit conversion support:

You can pass: &units=metric to your API call in order to get temperature in Celsius, like this:

api.openweathermap.org/data/2.5/weather?lat=LATITUDE&lon=LONGITUDE&units=metric&APPID=YOUR_API_KEY

Here is some info from official documentation:

Units format Description: Standard, metric, and imperial units are available.

Parameters:

units metric, imperial. When you do not use units parameter, format is Standard by default.

Temperature is available in Fahrenheit, Celsius and Kelvin units.

For temperature in Celsius use units=metric For temperature in Fahrenheit use units=imperial

Examples of API calls:

standard api.openweathermap.org/data/2.5/find?q=London

metric api.openweathermap.org/data/2.5/find?q=London&units=metric

imperial api.openweathermap.org/data/2.5/find?q=London&units=imperial

Upvotes: 8

warkentien2
warkentien2

Reputation: 979

It's a scope problem.

var temperature is being defined inside the nameless function inside $.get inside getWeatherData inside another nameless function inside $(document).ready()!
That's 6 levels deeper than you can read with ToF or ToC

In simple terms: you have access to all variables declared in this scope or in a parent scope.

There's a great explanation on JavasScript scope here (stackoverflow)

solutions:

  • global variables:

    1. add a global variable var temperature = 0; right under <script>
    2. remove the var from var temperature inside $.get(url, function());
    3. to use onclick(), write your <script src="[your-js-file]"> inside <head>.
  • change function's scope:

    1. place the ToC and ToF function declarations inside the $.get(url, function(){ [HERE] }); scope
    2. remove onclick='ToC()', it no longer works. (same with ToF)
    3. add an id to <a href="#">F</a>, e.g.: id="toggle-unit-btn" (same with ToF)
    4. add a click event handler $('#toggle-unit-btn').on('click', ToC);
      inside the $.get(url, function(){ [HERE] }); scope
  • pass and return value from functions: [recomended]

    1. add an input and output parameter to ToC and ToF
function ToC(temp) { // INPUT
  var strIn = parseInt(temp); 
  // note that I changed all temperature instances 
  // to instances of the parameter temp [could have any name]

  if(isNaN(strIn)) {
    alert("Not a Number");
  } else {
    var f = parseFloat(strIn);
    var c = (f - 32) * 5/9;

    var r = Math.round(c * 100)/100;
    temp = parseInt(r.toString()); // fix this line for any solution!
  }
  return temp; // OUTPUT
}
  1. remove onclick='ToC()', it no longer works. (same with ToF)
  2. add an id to <a href="#">F</a>, e.g.: id="toggle-unit-btn" (same with ToF)
  3. add a click event handler
    $('#toggle-unit-btn').on('click',function(){temperature = ToC(temperature);});
    inside the $.get(url, function(){ [HERE] }); scope
    (note that it's different from previous solution, because it needs to pass and receive temperature)

Upvotes: 0

Related Questions