Zvezdas1989
Zvezdas1989

Reputation: 1465

Window onload and onclick events

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

Answers (4)

btzr
btzr

Reputation: 2154

Window onLoad

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

Mati
Mati

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

azs06
azs06

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

toastrackengima
toastrackengima

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

Related Questions