0

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.

metaphor
  • 470
  • 4
  • 13
  • 27
  • You appear to be defining the `ToC` function _inside_ the `$.get(url, function(weather) { ... ` ajax callback. You need to move that out, so it's defined and available in the global scope. – jszobody Jun 11 '16 at 02:57
  • 1
    your `ToC` and `ToF` functions are only known in the scope of the `$.get` handler. You can move them out of there - you can even move them above the `$(document).ready(function() {`. However, you will then need to pass the temperature to the functions or you can add a custom `data` attribute to your `` element and work with that (give your anchors a unique ID so you can access them easily). – Mike Scotty Jun 11 '16 at 02:58
  • I've moved out the functions from `$.get` scope. How to pass the _temperature_ to the functions ? i get an error _"temperature is not defined"_. And if you don't mind would you give me an example custom `data` attribute ? i set a unique ID #getConvert to element – metaphor Jun 11 '16 at 03:29
  • @metaphor: I did the same... But no error in console. But I notice that `wheather` is not defined anywhere in `$.get(url, function(weather) {` a console.log inside it never shows. – Louys Patrice Bessette Jun 11 '16 at 03:37
  • Hardly can reproduce this... Was not able to do it in Fiddle (probably doesn't allow `$.get()`... Dunno..... Is `var appid = "&APPID=123456abcde"` valid or a kind of a sample like «example.com» ? – Louys Patrice Bessette Jun 11 '16 at 03:39
  • I have done this freecodecamp challenge. And I can't read your code at all. Please be more specific on what's wrong (or I'll have to assume that it's the entire code, and skip reading it because it's too much work). Where exactly is the problem, and what "wrong" behavior it's showing? – warkentien2 Jun 11 '16 at 05:29
  • @warkentien2 the problem is conversion functions didn't work, when i click the label `F/C` or `C` it's showing _Uncaught ReferenceError: temperature is not defined_ – metaphor Jun 11 '16 at 06:06
  • You do realize that the OpenWeatherMap API provides temperatures in Kelvin, Celsius and Fahrenheit and there is no need to convert that yourself? – Tomalak Jun 11 '16 at 06:32

2 Answers2

8

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

mjrdnk
  • 233
  • 3
  • 9
0

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)
Community
  • 1
  • 1
warkentien2
  • 969
  • 13
  • 20