Null reference error in document.element [duplicate] - javascript

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 6 years ago.
I am facing error at append child as the object null value error is there infact i have created the object in the top of script with document get element
and i am trying to get the issue resolve as left side is in there in the div need some help try to figure it out. Please as u read
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Game</title>
<style>
imgg{
position: absolute;
}
div{
width: 500px;
height: 500px;
position: absolute;
}
#rightSide { left: 500px;
border-left: 1px solid black }
</style>
<script>
var numberOfFaces =5 ;
var theLeftSide = document.getElementById("leftSide");
function generateFaces(){
for(var i = 1 ; i <= numberOfFaces ; i++)
{
var imgg = document.createElement("img");
imgg.src = "smile.png";
imgg.style.height = "100px";
imgg.style.width = "100px";
imgg.style.top = Math.random() *400 ;
imgg.style.left = Math.random() *400 ;
theLeftSide.appendChild(imgg);
}
}
</script>
</head>
<body onload="generateFaces()">
<h2>Matching Game</h2>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
</body>
</html>

document.getElementById("leftSide"); will give error if you put your script inside head. The reason being when js will try to parse this line but there is no such DOM present .
You can resolve it by using
window.onload
put the script tag before closing body tag
<body>
// Dom
<script>
// Rest of code
</script>
</body>
Using window.onload
<head>
//Rest of code
<script>
window.onload = function(){
var numberOfFaces =5 ;
var theLeftSide = document.getElementById("leftSide");
function generateFaces(){
for(var i = 1 ; i <= numberOfFaces ; i++)
{
var imgg = document.createElement("img");
imgg.src = "smile.png";
imgg.style.height = "100px";
imgg.style.width = "100px";
imgg.style.top = Math.random() *400 ;
imgg.style.left = Math.random() *400 ;
theLeftSide.appendChild(imgg);
}
}
}
</script>
</head>
Check this JSFIDDLE , script is wrapped in the body

Place your <script> as last-child of <body> as by the time you are accessing the element using DOM-api, element is not in the DOM
Set position to absolute
Add unit as px(pixel) while assigning top and left
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
function generateFaces() {
for (var i = 1; i <= numberOfFaces; i++) {
var imgg = document.createElement("img");
imgg.src = "http://i185.photobucket.com/albums/x304/metalife/transmetropolitan-smile.png";
imgg.style.height = "100px";
imgg.style.width = "100px";
imgg.style.position = 'absolute';
imgg.style.top = Math.random() * 400 + 'px';
imgg.style.left = Math.random() * 400 + 'px';
theLeftSide.appendChild(imgg);
}
}
imgg {
position: absolute;
}
div {
width: 500px;
height: 500px;
position: absolute;
}
#rightSide {
left: 500px;
border-left: 1px solid black
}
<body onload="generateFaces()">
<h2>Matching Game</h2>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide"></div>
<div id="rightSide"></div>

Related

lastElementChild returns null

I'm working on a Javascript assignment that splits the page into two div elements then appends the div on the left with randomly placed images, then I used .cloneNode() to duplicate on the right, minus the last child image.
That part of it works fine, but I am then supposed to add an event handler to the last element of the left div, but when I try to do this the lastElementChild() method returns null even though the div has the expected child nodes. The code is below and I've commented where the problem is. Any help would be appreciated!
<!DOCTYPE html>
<html>
<head>
<style>
img {position: absolute}
div {position: absolute; height: 500px; width: 500px}
#right {border-left: solid black; left: 500px}
</style>
<script>
<!-- everything here works fine -->
function generateFaces(){
var theLeftSide = document.getElementById("left");
var numberFaces = 5;
for (i = 0; i < numberFaces; i++){
var random_x = Math.random()*400;
var random_y = Math.random()*400;
var image = document.createElement("img")
image.src = "smile.png";
image.setAttribute("style","top: " + random_y + "px;" + "left: " + random_x + "px;");
theLeftSide.appendChild(image);
}
var theRightSide = document.getElementById("right");
leftSideImages = theLeftSide.cloneNode(true);
theRightSide.appendChild(leftSideImages);
theRightSide.lastChild.removeChild(theRightSide.lastChild.lastChild);
}
</script>
</head>
<body onload = "generateFaces()">
<h1> Game </h1>
<p> Instructions </p>
<div id = "right"></div>
<div id = "left"> </div>
<script>
<!-- problem script here -->
var temp = document.getElementById("left");
console.log(temp); // displays <div> with its children <img>
var temp2 = temp.lastElementChild;
console.log(temp2); // returns null
</script>
</body>
</html>
The body's onload event will not fire until after the javascript in your 'problem script' runs.
The order of execution here is basically:
h1, p, #left, and #right get appended to the DOM
script #1 runs, logging the empty #left div and the null lastElementChild.
body onload event fires and script #2 runs (the generateFaces() function). At this point, the <img> tags are inserted into the DOM.
The fix is to make sure that script #1 runs after #2:
<body onload="handleLoad()">
and the JS:
function handleLoad() {
generateFaces()
logStuff()
}
function logStuff() {
var temp = document.getElementById("left");
console.log(temp); // displays <div> with its children <img>
var temp2 = temp.lastElementChild;
console.log(temp2); // logs <img>
}
It might appear, in the console, that #left has images in it at the time that script #1 runs. This is just a quirk of the console; the actual logging happens asynchronously, and since the referenced variable changes in the meantime, the value actually logged is different than what it was when console.log() was called.
You can see this behavior by varying a setTimeout duration on the generateFaces() function call:
function generateFaces() {
var theLeftSide = document.getElementById("left");
var numberFaces = 5;
for (i = 0; i < numberFaces; i++) {
var random_x = Math.random() * 400;
var random_y = Math.random() * 400;
var image = document.createElement("img")
image.src = "smile.png";
image.setAttribute("style", "top: " + random_y + "px;" + "left: " + random_x + "px;");
theLeftSide.appendChild(image);
}
var theRightSide = document.getElementById("right");
leftSideImages = theLeftSide.cloneNode(true);
theRightSide.appendChild(leftSideImages);
theRightSide.lastChild.removeChild(theRightSide.lastChild.lastChild);
}
var temp = document.getElementById("left");
console.log(temp); // displays <div> with its children <img>
var temp2 = temp.lastElementChild;
console.log(temp2); // returns null
setTimeout(generateFaces, 250) // play with this value
img {
position: absolute
}
div {
position: absolute;
height: 500px;
width: 500px
}
#right {
border-left: solid black;
left: 500px
}
<h1> Game </h1>
<p> Instructions </p>
<div id="right"></div>
<div id="left"> </div>
Oh, and note that your generateFaces() function currently creates multiple elements in the DOM with the same id. You're gonna want to fix that.
Your generateFaces() function is called when the body is loaded.
but your second script runs when the window is loaded.
So when the second script runs there is no temp.lastElementChild and you get null.
You can slove is like this
<!DOCTYPE html>
<html>
<head>
<style>
img {position: absolute, height: 30px; width: 30px;}
div {position: absolute; height: 500px; width: 500px}
#right {border-left: solid black; left: 500px}
</style>
</head>
<body onload = "generateFaces()">
<h1> Game </h1>
<p> Instructions </p>
<div id = "right"></div>
<div id = "left"> </div>
<script>
function generateFaces()
{
console.log('y');
var theLeftSide = document.getElementById("left");
var numberFaces = 5;
for (i = 0; i < numberFaces; i++){
var random_x = Math.random()*400;
var random_y = Math.random()*400;
var image = document.createElement("img")
image.src = "smile.png";
image.setAttribute("style","top: " + random_y + "px;" + "left: " + random_x + "px;");
theLeftSide.appendChild(image);
}
var theRightSide = document.getElementById("right");
leftSideImages = theLeftSide.cloneNode(true);
theRightSide.appendChild(leftSideImages);
theRightSide.lastChild.removeChild(theRightSide.lastChild.lastChild);
loaded();
}
<script>
function loaded() {
var temp = document.getElementById("left");
console.log(temp);
var temp2 = temp.lastElementChild;
console.log(temp2);
}

Uncaught TypeError: Cannot read property 'lastChild' of null

<!DOCTYPE html>
<html>
<head>
<title>Face Matching Game</title>
<h2>Matching Game</h2>
<p>Click on the EXTRA face on the left side</p>
<style type="text/css">
div { position: absolute; width: 640px; height: 550px; background-color: maroon }
img { position: absolute; width: 100px; height: 100px}
#rightSide { left: 650px; border-left: 2px solid black; }
</style>
<script type="text/javascript">
var NUM_OF_FACES = 0;
var THE_LEFT_SIDE, THE_RIGHT_SIDE;
//Function to generate faces
function generateFaces() {
THE_LEFT_SIDE = document.getElementById("leftSide");
THE_RIGHT_SIDE = document.getElementById("rightSide");
NUM_OF_FACES += 5;
var image;
while(NUM_OF_FACES>0){
image = document.createElement("img");
image.src = "smile.png";
image.style.top = Math.floor(Math.random()* (THE_LEFT_SIDE.offsetHeight - 100)) + "px";
image.style.left = Math.floor(Math.random()* (THE_LEFT_SIDE.offsetWidth - 100)) + "px";
THE_LEFT_SIDE.appendChild(image);
NUM_OF_FACES -= 1;
//console.log(image.style.top, image.style.left )
}
var leftSideImages = THE_LEFT_SIDE.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
THE_RIGHT_SIDE.appendChild(leftSideImages);
}//end generatefaces()
function deleteFaces(argument) {
while(THE_LEFT_SIDE.firstChild){
THE_LEFT_SIDE.removeChild(THE_LEFT_SIDE.firstChild);
}
while(THE_RIGHT_SIDE.firstChild){
THE_RIGHT_SIDE.removeChild(THE_RIGHT_SIDE.firstChild);
}
}//end deleteFaces()
var theBody = document.getElementsByTagName("body")[0];
THE_LEFT_SIDE = document.getElementById("leftSide");
THE_RIGHT_SIDE = document.getElementById("rightSide");
//Event handling
THE_LEFT_SIDE.lastChild.onclick = function goToNextLevel() {
alert("You clicked on correct face.");
deleteFaces();
generatefaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!!");
theBody.onclick = null;
THE_LEFT_SIDE.lastChild.onclick = null;
};
</script>
</head>
<body onload="generateFaces()">
<div id="leftSide"></div>
<div id="rightSide"></div>
</body>
</html>
I am beginner in Javascript and ran into a problem while doing an assignment.
It is Fact Matching game and you have to click the extra face on the left side and game continues until you click somewhere else than extra face on left.
Above is the HTML file and JS code is embedded in it.
I am getting an error as: Uncaught TypeError: Cannot read property 'lastChild' of null at line number 48, which is onclick event handler function on lastChild of THE_LEFT_SIDE div. I don't know how it is coming and what is the problem with my code?
Any leads will be appreciated.
You are trying to access the element with id leftSide before it has been added to the DOM.
If you move your script to the end of the page body, you will no longer see this error, but a different, unrelated one instead:
<!DOCTYPE html>
<html>
<head>
<title>Face Matching Game</title>
<h2>Matching Game</h2>
<p>Click on the EXTRA face on the left side</p>
<style type="text/css">
div { position: absolute; width: 640px; height: 550px; background-color: maroon }
img { position: absolute; width: 100px; height: 100px}
#rightSide { left: 650px; border-left: 2px solid black; }
</style>
</head>
<body onload="generateFaces()">
<div id="leftSide"></div>
<div id="rightSide"></div>
<script type="text/javascript">
var NUM_OF_FACES = 0;
var THE_LEFT_SIDE, THE_RIGHT_SIDE;
//Function to generate faces
function generateFaces() {
THE_LEFT_SIDE = document.getElementById("leftSide");
THE_RIGHT_SIDE = document.getElementById("rightSide");
NUM_OF_FACES += 5;
var image;
while(NUM_OF_FACES>0){
image = document.createElement("img");
image.src = "smile.png";
image.style.top = Math.floor(Math.random()* (THE_LEFT_SIDE.offsetHeight - 100)) + "px";
image.style.left = Math.floor(Math.random()* (THE_LEFT_SIDE.offsetWidth - 100)) + "px";
THE_LEFT_SIDE.appendChild(image);
NUM_OF_FACES -= 1;
//console.log(image.style.top, image.style.left )
}
var leftSideImages = THE_LEFT_SIDE.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
THE_RIGHT_SIDE.appendChild(leftSideImages);
}//end generatefaces()
function deleteFaces(argument) {
while(THE_LEFT_SIDE.firstChild){
THE_LEFT_SIDE.removeChild(THE_LEFT_SIDE.firstChild);
}
while(THE_RIGHT_SIDE.firstChild){
THE_RIGHT_SIDE.removeChild(THE_RIGHT_SIDE.firstChild);
}
}//end deleteFaces()
var theBody = document.getElementsByTagName("body")[0];
THE_LEFT_SIDE = document.getElementById("leftSide");
THE_RIGHT_SIDE = document.getElementById("rightSide");
//Event handling
THE_LEFT_SIDE.lastChild.onclick = function goToNextLevel() {
alert("You clicked on correct face.");
deleteFaces();
generatefaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!!");
theBody.onclick = null;
THE_LEFT_SIDE.lastChild.onclick = null;
};
</script>
</body>
</html>

Matching Game. Javascript. DOM lastChild

There is a simple game. The left and right sides are identical, except for one thing: the left side has one extra face. The user needs to find out and click on that extra face (lastChild). It will trigger the function to double the face quantity.
The problem is - all the faces in my game are lastChild. Where is the problem?
Thanks!
<!DOCTYPE <!DOCTYPE html>
<html>
<head>
<title>Matching Game. Part 3.</title>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
</style>
<script>
function generateFaces(){
var numberOfFaces = 5;
//var theLeftSide = document.getElementById("leftSide");
for(var i=0; i < numberOfFaces; i++) {
var smileImage = document.createElement("img");
smileImage.src="http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
var topPosition = Math.floor(Math.random()* 400) + 1;
var leftPosition = Math.floor(Math.random()* 400) + 1;
smileImage.style.top = topPosition + "px";
smileImage.style.left = leftPosition + "px";
leftSide.appendChild(smileImage);
var leftSideImages = leftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
rightSide.appendChild(leftSideImages);
leftSide.lastChild.style.background = "red";
var theBody = document.getElementsByTagName("body")[0];
leftSide.lastChild.onclick = function nextLevel(event) {
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
}
}
}
</script>
</head>
<body onload = "generateFaces()">
<h1>Matching Game</h1>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
</body>
</html>
You are binding your click event to every element in the loop. You first need to over-ride the previous handler and then re-bind it to the last element.
function generateFaces(){
var numberOfFaces = 5;
var leftSide = document.getElementById("leftSide");
var rightSide = document.getElementById("rightSide");
for(var i=0; i < numberOfFaces; i++) {
var smileImage = document.createElement("img");
smileImage.src="http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
var topPosition = Math.floor(Math.random()* 400) + 1;
var leftPosition = Math.floor(Math.random()* 400) + 1;
smileImage.style.top = topPosition + "px";
smileImage.style.left = leftPosition + "px";
leftSide.appendChild(smileImage);
var leftSideImages = leftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
rightSide.appendChild(leftSideImages);
leftSide.lastChild.style.background = "red";
var theBody = document.getElementsByTagName("body")[0];
}
var pics = document.getElementsByTagName("img");
for(i=0;i<pics.length;i++){
pics[i].onclick = function() {
return false;
}
}
leftSide.lastChild.onclick = function nextLevel(event) {
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
}
}
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
<body onload = "generateFaces()">
<h1>Matching Game</h1>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
</body>

Using on click vanilla JS, activating on wrong node

Almost finished this sort of game i am working on to learn Dom manipulation. Basically the game spawns 5 images on the left and 4 on the right, you click the odd one out and then 10 spawn on the left and 9 on the right(+5 everytime).
I am wanting my nextlevel function to work every time the last child(of theLeftSide) is clicked on. It works the first time but after that regardless of if i click the correct node or not, my gameOver function is called and im not sure why. I tried removing the game over function and still the 2nd time i want my nextLevel to run(after click), it doesnt. Am i going about this the totally wrong way? Any input is appreciated thank you. Left my gameOver function in so you can see what im trying to do with it.
var theLeftSide = document.getElementById("leftside");
var theRightSide = document.getElementById("rightside");
var facesNeeded = 5;
var totalfFaces = 0;
var theBody = document.getElementsByTagName("body")[0];
function makeFaces() {
while (facesNeeded != totalfFaces) {
smiley = document.createElement("img");
smiley.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
smiley.style.top = Math.random() * 401 + "px";
smiley.style.left = Math.random() * 401 + "px";
document.getElementById("leftside").appendChild(smiley);
totalfFaces++;
// alert(totalfFaces); used to debug
}
if (facesNeeded == totalfFaces) {
//alert(facesNeeded);
//alert(totalfFaces);
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
document.getElementById("rightside").appendChild(leftSideImages);
//alert("hi");
}
}
makeFaces();
function delFaces(side) {
while (side.firstChild) {
side.removeChild(side.firstChild);
}
}
theLeftSide.lastChild.onclick = function nextLevel(event) {
event.stopPropagation();
delFaces(theRightSide);
delFaces(theLeftSide);
totalfFaces = 0;
facesNeeded += 5;
//alert(facesNeeded);
//alert(totalfFaces);
makeFaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
<!DOCTYPE html>
<html>
<head>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightside {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<h1> Matching Game</h1>
<p>Click on the extra smiling face on the left</p>
<div id="leftside"></div>
<div id="rightside"></div>
<script src="script3.js"></script>
</body>
</html>
You just need to move the onclick inside the makeFaces after the while, so its added everytime after it creates them all:-
var theLeftSide = document.getElementById("leftside");
var theRightSide = document.getElementById("rightside");
var facesNeeded = 5;
var totalfFaces = 0;
var theBody = document.getElementsByTagName("body")[0];
function makeFaces() {
while (facesNeeded != totalfFaces) {
smiley = document.createElement("img");
smiley.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
smiley.style.top = Math.random() * 401 + "px";
smiley.style.left = Math.random() * 401 + "px";
document.getElementById("leftside").appendChild(smiley);
totalfFaces++;
// alert(totalfFaces); used to debug
}
if (facesNeeded == totalfFaces) {
//alert(facesNeeded);
//alert(totalfFaces);
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
document.getElementById("rightside").appendChild(leftSideImages);
//alert("hi");
}
theLeftSide.lastChild.onclick = function nextLevel(event) {
event.stopPropagation();
delFaces(theRightSide);
delFaces(theLeftSide);
totalfFaces = 0;
facesNeeded += 5;
//alert(facesNeeded);
//alert(totalfFaces);
makeFaces();
};
}
makeFaces();
function delFaces(side) {
while (side.firstChild) {
side.removeChild(side.firstChild);
}
}
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
<!DOCTYPE html>
<html>
<head>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightside {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<h1> Matching Game</h1>
<p>Click on the extra smiling face on the left</p>
<div id="leftside"></div>
<div id="rightside"></div>
<script src="script3.js"></script>
</body>
</html>

JavaScript/HTML div creation error

I am trying to make a basic sensor pad for HTML (JavaScript), which creates 500 small divs which then turn red on mouse hover. However, when I tried it, nothing was created
example.html
<!DOCTYPE html>
<html>
<head>
<title>SensorPad Test</title>
<link rel="stylesheet" href="styles.css" type="text/css">
<script type="text/javascript" src="SensorPad.js">
window.onload = createSensor;
</script>
</head>
</html>
styles.css
.sPad{
width: 0.4px;
height: 0.4px;
background-color: #EEE;
border: 0.1px solid #000;
}
.uPad{
background-color: #F00;
}
SensorPad.js
var sPos;
var count = 1;
function createSensor(){
for(var i = 0; i < 500; ++i){
var pad = document.createElement('div');
pad.className = 'sPad';
pad.id = 'pad' + count.toString();
pad.onmousehover = function(){sPos = parseInt(pad.id); clearPads(); pad.className = 'uPad';};
count++;
}
}
function clearPads(){
for(var i = 1; i <= count; ++i){
var n = 'pad' + i.toString();
var p = document.getElementById(n);
p.className = 'sPad';
}
}
You're missing
document.body.appendChild(pad);
First the code will not run because of the way you added the JavaScript
<script type="text/javascript" src="SensorPad.js">
window.onload = createSensor;
</script>
you can not have code inside and a src
<script type="text/javascript" src="SensorPad.js"></src>
<script type="text/javascript"
window.onload = createSensor;
</script>
First, you need to use separate script tags - one for the external reference and another for the onload.
As for the divs, you're creating them but you're not adding them to the DOM.
for(var i = 0; i < 500; ++i){
var pad = document.createElement('div');
pad.className = 'sPad';
pad.id = 'pad' + count.toString();
pad.onmousehover = function(){sPos = parseInt(pad.id); clearPads(); pad.className = 'uPad';};
document.body.appendChild(pad)
count++;
}
EDIT: Addressing Teemu's concern you might simply want to use CSS for that hover instead so:
for(var i = 0; i < 500; ++i){
var pad = document.createElement('div');
pad.className = 'sPad';
pad.id = 'pad' + i.toString();
document.body.appendChild(pad)
}
css
.sPad{
width: 0.4px;
height: 0.4px;
background-color: #EEE;
border: 0.1px solid #000;
}
.sPad:hover{
background-color: #F00;
}

Categories

Resources