Reputation: 1465
Hello guys I’m trying to make simple weather app and I’ve run into an issue. Everything worked fine until I decided to make a function which would change Celsius to Fahrenheit and vice versa. I decided to make a function which I would call onclick event after window.load event, but for some reason it’s not working. When I use onclick element I get following error.
Uncaught TypeError: Cannot set property ‘onclick’ of null
and when I add to it window.load nothing happens. Here is my JS:
// This won't work on github because openweatherapp requires payed version of api for https and github forces https
const ipApi = 'http://ip-api.com/json';
const body = document.getElementsByTagName("body")[0];
fetch(ipApi)
.then(response => response.json())
.then(function(data) {
let latitude = data.lat;
let longitude = data.lon;
let city = data.city;
const openWeatherAppId = '********';
const openWeatherUrl = 'http://api.openweathermap.org/data/2.5/weather?lat=' + latitude + '&lon=' + longitude + '&units=metric' + '&APPID=' + openWeatherAppId;
fetchWeather(city, openWeatherUrl);
})
.catch(function(error) {
// If there is any error you will catch them here
console.log(error);
});
function fetchWeather(city, api) {
fetch(api)
.then(response => response.json())
.then(function(data) {
let desc = data.weather[0].description;
let temperature = data.main.temp;
let icon = data.weather[0].icon;
var iconSrc = 'http://openweathermap.org/img/w/' + icon + '.png';
let myCity = createNode('h2');
myCity.innerHTML = city;
let myDesc = createNode('p');
myDesc.innerHTML = desc;
let myDiv = createNode('div');
myDiv.setAttribute('id', 'temperatureDiv');
let myTemp = createNode('p');
myTemp.innerHTML = temperature;
myTemp.setAttribute('id', 'temperature'); // Give ID to 'p' so I can use with DOM
let myUnit = createNode('span');
myUnit.innerHTML = 'Celsius';
myUnit.setAttribute('id', 'unit'); // Give ID to 'p' so I can use with DOM
let myIcon = createNode('img');
myIcon.src = iconSrc;
append(body, myCity);
append(body, myDesc);
append(body, myDiv);
append(myDiv, myTemp);
append(myDiv, myUnit);
append(body, myIcon);
changeUnits(temperature);
})
.catch(function(error) {
// If there is any error you will catch them here
console.log(error);
});
}
function changeUnits (myTemperature) {
let currentTemp = myTemperature; // This is current temperature in celsius
if (document.getElementById('unit').innerHTML == 'Celsius') {
document.getElementById('temperature').innerHTML = (currentTemp * 1.8 + 32).toFixed(0);
document.getElementById('unit').innerHTML = 'Fahrenheit';
} else {
document.getElementById('temperature').innerHTML = currentTemp;
document.getElementById('unit').innerHTML = 'Celsius';
}
}
window.load = function () {
document.getElementById('unit').onclick = changeUnits;
}
function createNode(element) {
return document.createElement(element); // Create the type of element you pass in the parameters
}
function append(parent, el) {
return parent.appendChild(el); // Append the second parameter(element) to the first one
}
Can anyone help me with this. Here is JSBin, so you see what is happening http://jsbin.com/jujifo/edit?html,js,console,output I’m using openweather API so use http, so you can see code in action it won’t work on https
Upvotes: 1
Views: 3498
Reputation: 2154
The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links and sub-frames have finished loading.
You are trying to get an element
before even exist.
See: MDN
Just assign the onClick
handler on creation:
myUnit = createNode('span');
myUnit.addEventListener('click', function(e) { changeUnits()})
...
See: jsbin
Upvotes: 1
Reputation: 1148
Use window.onload
instead of window.load
. Try this:
window.onload = function () {
document.getElementById('unit').addEventListener('click', changeUnits);
}
Alternatively, in most modern browsers, you can use the async
or defer
attributes on the script tag to avoid the synchronous blocking behavior that is the default.
Upvotes: 0
Reputation: 3517
You could just add event listener after creating the node, like this
let myUnit = createNode('span');
myUnit.addEventListener('click', changeUnits);
Working jsbin http://jsbin.com/xuvanen/edit?html,js,output
Upvotes: 0
Reputation: 8742
An element with an ID of unit
does not exist when the page loads, as it is made when your AJAX call happens.
Once the AJAX call happens, you should define onclick
as a function (in the same way that you do with window.onload
, not just a pointer to one, i.e.
document.getElementById("unit").onclick = function() {
chnageUnits();
}
Upvotes: 0