lalalitamplong lalalitamplong - 7 months ago 135
Javascript Question

Google Event Listener: Uncaught TypeError: Cannot read property 'addEventListener' of null

I've asked this question before about the addListener in the addListenerOnce that does not work and the answer is I tried to add the click listener before the element I'm looking for has been rendered. The problem is I can't understand why does it work for the top two event. The event come from the click event of legend. The top two event will appear together. It's like the listener only work for 1 times. I've tried to use addListenerOnce and the event is idle too (like the 1st legend) for calling the event of 2nd legend level, but it does not work at all.

For example, I click the Faculty legend and then click fpa and fskm, it work just wonderful but when I click Sex or Level of Education then click their respective 2nd legend the error of Uncaught TypeError: Cannot read property 'addEventListener' of null comes out. I've even try the DOMContentLoaded, still not working. Just how on earth do I do this? Below is the code, the alert is just to test.

var legend = document.createElement('div');
legend.id = 'legend';
var content = [];
content.push('<h3><b>View option</b></h3>');
content.push('<div id="general"><svg height="20" width="200"><g><rect width="15" height="12"class="general" ></g><g><text x="26" y="10">General</text></g></svg></div>');
content.push('<div id="faculty"><svg height="20" width="200"><g><rect width="15" height="12"class="nothing"></g><g><text x="26" y="10">Faculty</text></g></svg></div>');
content.push('<div id="sex"><svg height="20" width="200"><g><rect width="15" height="12"class="nothing"></g><g><text x="26" y="10">Sex</text></g></svg></div>');
content.push('<div id="level"><svg height="20" width="200"><g><rect width="15" height="12"class="nothing"></g><g><text x="26" y="10">Level of education</text></g></svg></div>');
legend.innerHTML = content.join('');
legend.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_TOP].push(legend);
var legendSpec = document.createElement('div');
legendSpec.id = 'legend';
var contentNew = [];

google.maps.event.addListenerOnce(map, 'idle', function() {

var genOpt = document.getElementById("general");
google.maps.event.addDomListener(genOpt, 'click', function() {
alert("ok");
});

var sexOpt = document.getElementById("sex");
google.maps.event.addDomListener(sexOpt, 'click', function() {
contentNew = [];
contentNew.push('<h3><b>Sex</b></h3>');
contentNew.push('<div id="maleD"><svg height="20" width="200"><g><rect width="15" height="12"class="male" ></g><g><text x="26" y="10">Male</text></g></svg></div>');
contentNew.push('<div id="femaleD"><svg height="20" width="200"><g><rect width="15" height="12"class="female"></g><g><text x="26" y="10">Female</text></g></svg></div>');
legendSpec.innerHTML = contentNew.join('');
legendSpec.index = 1;
alert("ok");
});

var facultyOpt = document.getElementById("faculty");
google.maps.event.addDomListener(facultyOpt, 'click', function() {
contentNew = [];
contentNew.push('<h3><b>Faculty</b></h3>');
contentNew.push('<div id="FSKMd"><svg height="20" width="200"><g><rect width="15" height="12"class="FSKM" ></g><g><text x="26" y="10">FSKM</text></g></svg></div>');
contentNew.push('<div id="FPAd"><svg height="20" width="200"><g><rect width="15" height="12"class="FPA"></g><g><text x="26" y="10">FPA</text></g></svg></div>');
legendSpec.innerHTML = contentNew.join('');
legendSpec.index = 1;
alert("ok");
});

var levelOpt = document.getElementById("level");
google.maps.event.addDomListener(levelOpt, 'click', function() {
contentNew = [];
contentNew.push('<h3><b>Level of Education</b></h3>');
contentNew.push('<div id="degreeD"><svg height="20" width="200"><g><rect width="15" height="12"class="degree" ></g><g><text x="26" y="10">Degree</text></g></svg></div>');
contentNew.push('<div id="diplomaD"><svg height="20" width="200"><g><rect width="15" height="12"class="diploma"></g><g><text x="26" y="10">Diploma</text></g></svg></div>');
legendSpec.innerHTML = contentNew.join('');
legendSpec.index = 1;
alert("ok");
});

map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(legendSpec);
calling();
});

function calling() {
google.maps.event.addListener(map, 'mouseover', function () {

var fskm = document.getElementById("FSKMd");
google.maps.event.addDomListener(fskm, 'click', function () {
alert("ok");
});

var fpa = document.getElementById("FPAd");
google.maps.event.addDomListener(fpa, 'click', function () {
alert("ok");
});
//fskm and fpa legend come together in 1 legend

var degree = document.getElementById("degreeD");
google.maps.event.addDomListener(degree, 'click', function () {
alert("ok");
});

var diploma = document.getElementById("diplomaD");
google.maps.event.addDomListener(diploma, 'click', function () {
alert("ok");
});

var male= document.getElementById("maleD");
google.maps.event.addDomListener(male, 'click', function () {
alert("ok");
});

var female= document.getElementById("femaleD");
google.maps.event.addDomListener(female, 'click', function () {
alert("ok");
});

});

}

Answer

It means your value is null - You don't have a proper reference to whatever you are trying to add the event listener to.

I'm assuming that when you refer to level of education, you are referring to this:

var degree = document.getElementById("degreeD");

If so, degreeD doesn't exist. Perhaps you have the wrong name in your HTML.

** Updated answer based on comments **

Since that element is added dynamically -- when the code is run, that element does not exist, which means the reference to it is, as you discovered, null.

There are two ways to handle that.

1) Move your degreeD event listener inside of the

google.maps.event.addDomListener(levelOpt, 'click', function() {

block, so that degreeD exists.

The other option is to use event delegation to register an event for an element that might not exist yet. I don't know the google.maps API well enough to know if they support event delegation or if you'd have have to handle that manually.

Comments