JavaScript getElementById returns null - javascript

I'm learning JavaScript and I'm wondering why something like:
document.getElementById('partofid'+variable+number) doesn't work?
Here are samples and JSfiddle link, I want "next" button to remove displayed item and show the next one.
HTML:
<div id="div-1"> 1 </div>
<div id="div-2" style="display: none"> 2 </div>
<div id="div-3" style="display: none"> 3 </div>
<div id="div-4" style="display: none"> 4 </div>
<a id="next" href="#">next</a>
JS:
var counter = 1;
var button = document.getElementById('next');
button.addEventListener("click",function(){
var currentDiv = document.getElementById('div-'+counter);
currentDiv.remove();
var nextDiv = document.getElementById('div-'+counter+1);
alert(nextDiv); // why does it return null
alert('div-'+counter+1); // while this doesn't?
nextQuestion.style.display = "block";
counter++;
},true);

Try using parseInt:
var nextDiv = document.getElementById('div-'+parseInt(counter+1,10));
The parseInt function converts its first argument to a string, parses it, and returns an integer.The second arguement is radix which is "base", as in a number system.
Demo

What's going on here is Javascript has some strange rules about types and the + operator.
string + anything means convert anything to string, then concatenate them together. So "foo" + "bar" == "foobar"... and "div" + 1 == "div1".
The the next step, addition is done left to right, so "div" + 1 + 1 goes to "div" + 1 == "div1".
"div1" + 1... remember, convert to string then put together, so we get "div1"+ 1 == "div11".
I would put parenthesis around your arithmetic. "div" + (1+1) would do the right hand side thing first, so (1+1) == 2 as you expect, then "div" + 2 == "div2", so that's what you expect.
As to the alert thing, your first one is looking at the result of the element lookup, and the second one is looking at the string itself. So the first is null because the element lookup didn't find anything.

This code results in string concatenation. E.g. if counter is 1, then you will get div-11
'div-'+counter+1
This is because addition is resolved from right to left.
Then you try to retrieve element with id div-11, but you don't have html element with such an id. That's why the function getElementById returns null.
To solve the problem first add counter to 1 and then join it with div, like this 'div-'+(counter+1)

Because counter+1 = 11 => id = div-11 is not exist. Try this:
var counter = 1;
var button = document.getElementById('next');
button.addEventListener("click",function(){
var currentDiv = document.getElementById('div-'+counter);
currentDiv.remove();
var nextDiv = document.getElementById('div-'+Number(counter+1));
alert(nextDiv); // why does it return null
alert('div-'+Number(counter+1)); // while this doesn't?
nextQuestion.style.display = "block";
counter++;
},true);

it does work and does exactly what you asked it to do but since you do not have a div-11 there is nothing found so the evaluation returns null.
if you want div-2 then simply use order of operations to sum the counter to the number:
Fiddle

Here is your answer:
<html>
<head>
<script>
function load()
{
var counter = 1;
var button = document.getElementById('next');
button.addEventListener("click",function(){
var currentDiv = document.getElementById('div-'+counter);
currentDiv.remove();
var nextDiv = document.getElementById('div-'+(counter+1));
//alert(nextDiv); // why does it return null
//alert('div-'+(counter+1)); // while this doesn't?
nextDiv.style.display = "block";
counter++;
},true);
}
</script>
</head>
<body onload="load()">
<div id="div-1"> 1 </div>
<div id="div-2" style="display: none"> 2 </div>
<div id="div-3" style="display: none"> 3 </div>
<div id="div-4" style="display: none"> 4 </div>
<a id="next" href="#">next</a>
</body>
<html>

To solve this kind of returning "null" values by getElementById("").
you can use script inside the body instead of head it will return the html element.
const m=document.getElementById('one')
const m1=document.getElementById('demo')
console.log(m1);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p id="demo">sample text</p>
<script src="script.js"></script>
</body>
</html>

Related

How can I create an unordered HTML list using JavaScript (without strange behaviour)?

I am trying to capture time from a stopwatch within a browser and display the times (laps) below. To do this, I am intending to create an unordered list from an array within a JavaScript file.
Here is the JS:
laps = []:
function show() {
$time = document.getElementById('time');
document.getElementById("capture").setAttribute("disabled","disabled"); // disable capture button until start
update();
}
function update() {
$time.innerHTML = formatTime(time());
displayLaps();
}
function displayLaps() {
if (laps == "" || laps.length == 0) {
return false; // stop the function if the value is empty
}
var inner = `Lap ${lap_count} :${formatTime(laps[lap_count-1])}`;
document.getElementById("laps").innerHTML += '<li>' + inner + '</li>';
}
And the associated html:
<!doctype html>
<html lang="en">
<head>
</head>
<body onload="show()">
<div>Time: <span id="time"></span></div>
<button onclick="onStart()" id="start" style="width:150px">Start</button>
<button id="capture" style="width:150px">Capture</button>
<div id="laps"><ul></ul></div>
<script src=".\stopwatch.js"> </script>
</body>
</html>
I am getting peculiar behaviour though. It seems that the += operator on the last line of code keeps adding rows that display the last array vaue (see below), whereas replacing this with a simple = operator just creates a single row that is then replaced every time a new lap value is added to the array.
I'm obviously missing something, but would appreciate some guidance, if possible.
Many thanks!

Why Javascript Event Handler only works on the HTML page? [duplicate]

<html>
<head>
<script type="text/javascript">
var image = document.getElementById(image);
var desc = document.getElementById(desc);
var images = ["http://i.imgur.com/XAgFPiD.jpg", "http://i.imgur.com/XAgFPiD.jpg"]
var descs = ["1", "2"]
var num = 0;
var total = images.length;
function clicked(){
num = num + 1;
if (num > total){
num = 0;
}
image.src = images[num];
desc.innerHTML = images[num];
}
document.getElementById(submit).onclick(clicked());
</script>
</head>
<body>
<div><h2>Project |</h2><h2> | herbykit</h2></div>
<div>
<button id="submit">Next</button><br/>
<img id="image" src="http://i.imgur.com/XAgFPiD.jpg" height="20%" width="50%"/>
<p id="desc">first desc.</p>
</div>
</body>
</html>
The line "document.getElementById(submit).onclick(clicked());" throws an error
"ReferenceError: submit is not defined"
When I tried accessing buttons in general
[through getElementsByClassName & getElementsByTagName]
it gave an error of "ReferenceError: button is not defined"
Using strings in getElementById it throws the error "getElementById is null"
I found several questions and answers to this.
Only one of them I understood how to implement, due to the use of PHP and that being the error on most others. Other solutions I found involved errors numerically.
On this error I tried a fix of printwindow.document.getElementById(..etc
This gives me an error of "ReferenceError: printwindow is not defined"
Browsers run JavaScript as soon as possible in order to speed up rendering. So when you receive this code:
<html>
<head>
<script type="text/javascript">
var image = document.getElementById(image); // Missing quotes, typo?
... in runs intermediately. There's no <foo id="image"> on page yet, so you get null. Finally, you get the rest of the page rendered, including:
<img id="image" src="http://i.imgur.com/XAgFPiD.jpg" height="20%" width="50%"/>
It's too late for your code, which finished running long ago.
You need to bind a window.onload even handler and run your code when the DOM is ready (or move all JavaScript to page bottom, after the picture).
It should be document.getElementById('submit').onclick(clicked());
your must enclose the id you are searching for in quotes:
document.getElementById('ID_to_look_up');
You are executing javascript before your 'body' rendered. Thus document.getElementById("submit") would return null. Because there are no "submit" DOM element yet.
One solution is to move your javascripts under 'body', Or use JQuery with
$(document).ready(function() {
...
});
Your variable also has scope problem, your function cannot access variable declared outside this function with 'var' declaration. If you really need that variable, you should remove 'var' declaration.
A better way is to move all your variable inside clicked function. like following code
<html>
<head>
</head>
<body>
<div><h2>Project |</h2><h2> | herbykit</h2></div>
<div>
<button id="submit">Next</button><br/>
<img id="image" src="http://i.imgur.com/XAgFPiD.jpg" height="20%" width="50%"/>
<p id="desc">first desc.</p>
</div>
</body>
<script type="text/javascript">
function clicked(){
var image = document.getElementById("image");
var desc = document.getElementById("desc");
var images = ["http://i.imgur.com/XAgFPiD.jpg", "http://i.imgur.com/XAgFPiE.jpg"];
var descs = ["1", "2"];
var num = 0;
var total = images.length;
num = num + 1;
if (num > total){
num = 0;
}
image.src = images[num];
desc.innerHTML = images[num];
}
document.getElementById("submit").onclick = clicked;
</script>
</html>

Javascript innerHTML not changing div contents [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 4 years ago.
I am trying to change the text displayed by a div from 'hello' to 'hey' on click using innerHTML. I know my function is executed and the innerHTML is changed because I get an alert on click displaying 'hey', but on my webpage and in inspector the 'text' element's contents remain as 'hello'.
What is going on here?
code:
<html>
<head>
<script type="text/javascript">
function changehtml() {
var text = document.getElementsByClassName('text');
text.innerHTML = 'hey';
alert(text.innerHTML)
}
</script>
</head>
<body>
<div class='text' onclick='changehtml()'>
hello
</div>
</body>
</html>
Get elements by class returns an array of elements if you just want to change the one div give it and id and getElementById.
If you want to change multiple divs with that class the second snippet loops through the divs with that class and changes all of their texts.
function changehtml() {
var text = document.getElementById('x');
text.innerHTML = 'hey';
alert(text.innerHTML)
}
<html>
<head>
</head>
<body>
<div id="x" class='text' onclick='changehtml()'>
hello
</div>
</body>
</html>
function changehtml() {
var text = document.getElementsByClassName('text');
for (let i = 0; i < text.length; i++) {
text[i].innerHTML = 'hey';
}
}
<html>
<head>
</head>
<body>
<div class='text' onclick='changehtml()'>
hello
</div>
</body>
</html>
document.getElementsByClassName('text') gives you collection of nodes. So, you;ll have to loop through them to get each node. Or for this example you can use
document.getElementsByClassName('text')[0];
Or
document.querySelector('.text')
This will give you the first node with class name of text.
And make it your habit to check your console for errors, you'll probably be getting one

javascript returns NaN in additition

I am trying to calculate total number of links click by user. To do so i am using following code
<html>
<head>
<script type="text/javascript">
function fnc()
{
document.getElementById("atext").innerHTML="tested";
var iStronglyAgreeCount=parseInt (document.getElementById("ISA") );
document.getElementById("ISA").innerHTML=iStronglyAgreeCount +1;
}
</script>
</head>
<body>
<label id="atext" onClick="fnc()">I strongly agree</label> (<span><label id="ISA">0</label></span>)
</body>
I am storing starting number 0 into a variable and trying to add 1 at each click.But it shows NaN.
Use .textContent to get the text content of the element.
function fnc() {
document.getElementById("atext").innerHTML = "tested";
var iStronglyAgreeCount = parseInt(document.getElementById("ISA").textContent);
document.getElementById("ISA").innerHTML = iStronglyAgreeCount + 1;
}
<a href="#">
<label id="atext" onClick="fnc()">I strongly agree</label>
</a>(<span><label id="ISA">0</label></span>)
Note: If target browser is <IE9, consider using Polyfill

Javascript display all (elements, tags) from method elementsbyTagName

Im learning JavaScript and i have problem with DOM methods.
HTML
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="DOM_Ponovno.js"></script>
</head>
<body>
<div>
<p id="demo" >
this is the first paragraph</p>
<p> boooooooooooommmmmmmmmmmm</p>
<p> third paragraph </p>
<button onclick="changeText()">click me</button>
</div>
</body>
function changeText() {
var tmpTag = document.getElementsByTagName("p");
for(var i = 0;i< tmpTag.length;i++) {
document.write(tmpTag[i].textContent);
}
}
If i follow the tutorial its ok, but i wanted to display all elements by tag name p. I want to display all paragraphs stored in tmpTag.
Someone please explain:
How can ( why cant) display all elements with tag name p ?
How can (why cant) display 3x p tag from variable tmpTag ?
Tried to change to Array with prototype.slice.call method but no success.
You know like Java stuff loop through display/change at index etc..
Thank you :)
Hi and thanx for fast answers.. Sory about the function name it was for testing... I just want to display all elements by tag name p. This code displays only first element and i counter in for loop stops at 1. Why cant i get other 2 paragraph elements ?
Im using document.write like system.out.print in Java to see whats in array. I know if i wanna change i need innerHTML.
If you are wanting to update each paragraph, do not use document write. Try the following:
function changeText() {
var tmpTag = document.getElementsByTagName("p");
for(var i = 0;i< tmpTag.length;i++) {
tmpTag[i].innerHTML = "Your new updated text to change it to for tag index " + i + "...";
}
}
As #Juhana mentioned, the moment you start your loop you overwrite the document using document.write, so all your p tags get removed from the document and replaced by the text in the first paragraph and then your function fails, as the now-empty objects don't have any textContent property. You could concatenate all the contents and write it once:
function changeText() {
var tmpTag = document.getElementsByTagName("p");
var print = '';
for(var i = 0;i< tmpTag.length;i++) {
print += tmpTag[i].textContent;
}
document.write(print)
}
But actually, just don't use document.write - SO snippets don't even allow it anymore! Here a way with a div as output:
var output = document.getElementById('output');
function changeText() {
var tmpTag = document.getElementsByTagName("p");
for(var i = 0;i< tmpTag.length;i++) {
output.textContent += tmpTag[i].textContent;
}
}
<div>
<p id="demo" >this is the first paragraph</p>
<p> boooooooooooommmmmmmmmmmm</p>
<p> third paragraph </p>
<button onclick="changeText()">click me</button>
</div>
<div id="output"></div>
I'm not sure what you're trying to do but you can add another div for result with id='result' and append result you want to it, check following example.
Hope this will help.
function changeText() {
var tmpTag = document.getElementsByTagName("p");
var result = document.getElementById('result');
for(var i = 0;i< tmpTag.length;i++) {
result.innerHTML += tmpTag[i].textContent+'<br>';
}
}
<div>
<p id="demo" >
this is the first paragraph</p>
<p> boooooooooooommmmmmmmmmmm</p>
<p> third paragraph </p>
<button onclick="changeText()">click me</button>
<br>
<div id="result" ></div>
</div>

Categories