"getElementsByTagName(...)[0]" is undefined? - javascript

I have the following code, which basically toggles through a bunch of images.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var num = 1;
img = document.getElementsByTagName("img")[0];
hbutton = document.getElementsByTagName("h1")[0];
hbutton.onclick = function() {
num += 1;
img.src = num + ".jpg";
}
</script>
</head>
<body>
<h1>Press Here!</h1>
<img src = "1.jpg"></img>
</body>
</html>
For some reason, when I run it, nothing happens, because of the following error as displayed by my Firebug console.
hbutton is undefined
---
hbutton.onclick = function() {
When I run just the JS after the page has loaded however, it works perfectly fine!!! Why is this?

Your code is executing before the h1 tag is defined. You must run it in an onload handler or put it just before /body

JavaScript is interpreted top-to-bottom. So at the place where your <script> executes, no h1 tags are known yet.
Try putting the <script>-Tag to the bottom of your page. Otherwise, if you need the script at the beginning of the page, an onLoad-Handler might help:
<script type="text/javascript">
function onLoadHandler() {
// your original javascript code here...
}
</script>
<body onload="onloadHandler()">
<!-- HTML Code here-->

When you put it in the header, your h1 is not loaded yet. hbutton becomes undefined, not an object. Then when you try to set .onclick, it breaks because you cant set properties of something undefined. When you put the code in the body, your h1 is already loaded, so the code works as you expected it to.
You can fix this by leaving your code at the top, but only calling it after an onload event.

The head gets executed before the dom is loaded. Put it on the button of the page or put an onload function in the body tag.
It cannot find document.getElementsByTagName("img") when the Document isnt ready yet, because it is simply not there yet.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function onDocumentReady(){
var num = 1;
img = document.getElementsByTagName("img")[0];
hbutton = document.getElementsByTagName("h1")[0];
hbutton.onclick = function() {
num += 1;
img.src = num + ".jpg";
}
}
</script>
</head>
<body onload="onDocumentReady()">
<h1>Press Here!</h1>
<img src = "1.jpg"></img>
</body>
</html>
or simply do this:
<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>Press Here!</h1>
<img src = "1.jpg"></img>
<script type="text/javascript">
var num = 1;
img = document.getElementsByTagName("img")[0];
hbutton = document.getElementsByTagName("h1")[0];
hbutton.onclick = function() {
num += 1;
img.src = num + ".jpg";
}
</script>
</body>
</html>

The problem is that the script is being executed immediately it is encountered during page load.
Since it's at the top of the page, in the header, this means that it is executed before the page has loaded the <h1> element (or any of the rest of the body).
Therefore, when it asks for getElementsByTagName('h1'), there aren't any matching elements at that moment in time.
You need to either:
* move the code to the end of the script.
* or wrap it in a function, and trigger the function to execute when the page has finished loading -- ie use the onload method.

Related

Why i do not need to set onload event to run setInterval() method in the script tag?

Hello I am new in Javascript i want to know that this code is changing image every four seconds and it is working very well but i did not give onload event here to run setInterval() method but still setInterval() got called how? who called setInterval() method?
<html lang="en">
<head>
<title>sliding image</title>
</head>
<body>
<img id="img1" src=""alt="" width="1200px">
<script>
let images = [
"C:\\Users\\SUDARSHAN\\Desktop\\html_UI\\images\\1200px-Heart_corazon.svg.png",
"C:\\Users\\SUDARSHAN\\Desktop\\html_UI\\images\\alex-haney-AGqzy-Uj3s4-unsplash.jpg",
"C:\\Users\\SUDARSHAN\\Desktop\\html_UI\\images\\mitchell-luo-jz4ca36oJ_M-unsplash.jpg"
];
let i = 0;
function image()
{
let img2=document.getElementById("img1");
i = (i + 1) % images.length;
img2.src = images[i];
}
window.setInterval(image,4000);
</script>
</body>
</html>
Code in <script> elements is ran automatically when the script tag is received. To wait until the page finishes loading, you do <script defer>.
For example,
<script>
console.log("Hello World!")
</script>
This would print Hello World! to the console immediately when the <script> tag is received.
<script defer>
console.log("Hello World!")
</script>
This would print Hello World! to the console after the page finishes loading.

Can't load HTML into HTA file when click by link inside of the HTML

I have one HTA file, one JS file is enqueued to the HTA file and HTML files with contents are loaded into the HTA file.
For example this is my_hta_file.hta
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=9.0" />
</head>
<body></body>
</html>
<script type="text/javascript" src="my_js_file.js"></script>
and this is my_js_file.js
function getFileContent(filePath) {
var fileStream = new ActiveXObject('ADODB.Stream');
fileStream.Type = 2;
fileStream.Charset = 'utf-8';
fileStream.Open();
fileStream.loadFromFile(filePath);
var fileContent = fileStream.ReadText();
fileStream.Close();
return fileContent;
}
// initial loading of home page
document.body.innerHTML = getFileContent('index.html');
var pageLinks = document.querySelectorAll('a');
for(i = 0; i < pageLinks.length; i++) {
var linkHref = pageLinks[i].getAttribute('href');
pageLinks[i].setAttribute('href','#!'+linkHref);
// I add this leading prefix to prevent following by the link when click by it
pageLinks[i].onclick = function() {
var page = this.getAttribute('href').substring(3);
if(page == '') {
var page = 'index';
}
// load HTML of the page by link path when click by the link
document.body.innerHTML = getFileContent(page+'.html');
}
}
and my HTML files with contents are:
index.html
Home
Second
Third
<div>Home page content</div>
second.html
Home
Second
Third
<div>Second page content</div>
third.html
Home
Second
Third
<div>Third page content</div>
When I click by a link, I need to load all the HTML content from the HTML file by the link path including the very links I click by.
If I open my HTA file and click the link "Second", I get the second page links and content successfully.
But after that if I click the link "Third", I get the error
Cannot find file 'file:///D:/third' ...
How to resolve the problem?
UPDATE 1
If I move my script to the bottom of the HTA body and add a div for loading HTML for example
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=9.0" />
</head>
<body>
<div id="body"></div>
<script type="text/javascript" src="my_js_file.js"></script>
</body>
</html>
and in my JS file load HTML into div i.e.
document.getElementById('body').innerHTML = ...
instead of
document.body.innerHTML = ...
the problem still remains
As said in the comments, all the links with attached event listeners are replaced by new elements when innerHTML is changed. These new links don't have the listeners which the old elements had.
The snippet below shows how you can use a function to reinit the listeners. The snippet assumes a content wrapper element is used (as you already seem to use it). I've also simplified the code a bit, and used more modern JS (since IE9 mode is used in the OP).
function getFileContent (filePath) {
// As it currently is
}
// Handles clicks on the links
function newContent (e) { // e contains information of the current event
var path = e.target.href || 'index',
body = document.getElementById('body');
e.preventDefault(); // Prevents the default action of the clicked link
body.innerHTML = getFileContent(path + '.html');
init(); // Initialize the new content
return;
}
// Initializes the page
function init() {
var links = document.querySelectorAll('a'),
i, ei;
for (i = 0, ei = links.length; i < ei; i++) {
links[i].addEventListener('click', newContent);
}
return;
}
// Initialize the first page
init();

How do I change innerHTML of loaded page with JQuery

I want my jquery to change text inside blocks with class "ToChange". It works fine inside current html file, but it does not with external html file (that I insert with "load" method). Here is my code:
index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home page</title>
<script src="jquery-3.1.1.js"></script>
<script>
$(function(){
$('.insert_external').load("external.html");
});
</script>
<script>
$(function(){
length = document.getElementsByClassName("ToChange").length;
for (i = 0; i < length; i++) {
document.getElementsByClassName("ToChange")[i].innerHTML = "New Text";
}
});
</script>
</head>
<body>
<div class="insert_external"></div>
<div class="ToChange">
This changes fine
</div>
<div class="ToChange">
This changes fine too
</div>
</body>
</html>
external.html :
<div class="ToChange">
This text does not change :(
</div>
As result I see 3 strings :
This text does not change :(
New Text
New Text
And I want all of them to be "New Text". Is it possible to do so using only html and js with jquery?
You have to change the html inside load() callback so the new data is here, else it will change in the old DOM since the JS works asynchronously.
You've to wait for the .load() to finish the request :
$('.insert_external').load("external.html", function() {
length = document.getElementsByClassName("ToChange").length;
for (i = 0; i < length; i++) {
document.getElementsByClassName("ToChange")[i].innerHTML = "New Text";
}
});
NOTE : Since you're using jQuery it'll be better to use .each() function instead :
$('.insert_external').load("external.html", function() {
$(".ToChange").each(function(){
$(this).text("New Text");
})
})
Hope this helps.
The function updating the text is running before the new content is actually loaded, because the load-function works asynchronously. You should wait until the new data has loaded. For this, use the callback of the .load()-function.
Try something like that
<script>
$(function(){
$('.insert_external').load("external.html",function(){
setText();
});
});
</script>
<script>
$(function(){
function setText(){
length = document.getElementsByClassName("ToChange").length;
for (i = 0; i < length; i++) {
document.getElementsByClassName("ToChange")[i].innerHTML = "New Text";
}
}
});
</script>
You just have to set a callback function when completed.

Need to place whole HTML5 code inside div or iframe

I have a complete HTML5 page in a JSON object, I have to show it to my page inside a div or iframe. Following is sample code.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
window._reviewWidget = {
onReady: function () {
var block1 = {
voyagerId:"xxxxxxx",
container: "container",
flavour:"small"
};
_reviewWidget.loadReview(block1);
}
};
(function (W,i,D,G,E,T)
{
W[G] = W[G] || {};
T = i.getElementsByTagName(D)[0];
E =i.createElement(D);
E.async = 1;
E.src ='/js/reviewWidget.js';
T.parentNode.insertBefore(E, T);
})(window, document,'script','_reviewWidget');
</script>
</head>
<body>
<div id="container">
</div>
</body>
</html>
When I am trying to put the code in div or iframe getting just container div, header part and body, HTML tag missing. I know we can't put such tags in div so I tried an iframe as well. But same issue either can see whole code as text or just container div.
Iframe code i am using (html_code JS variable with above HTML code)
Type-1
$('#HtmlFrame').contents().find('body').html(html_code);
Type-2
var iframe = document.createElement('iframe');
var ctnr = document.getElementById('Ewidget');
ctnr.appendChild(iframe);
iframe.contentWindow.document.open('text/htmlreplace');
iframe.contentWindow.document.write(html_code);
iframe.contentWindow.document.close();
Thanks.

javascript code in html to js file

I am struggling with the following problem.
I have made a memorygame with javascrpt for school.It all works fine, but my teacher told me that i can not have on line of javascript in my HTML, like this :
HTML :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Memory spelen</title>
</head>
<body>
<script type="text/javascript" src="javascript.js"></script>
<div id="memory_board"></div>
<script>newBoard();</script>
</body>
</html>
The newBoard() is applied to the memory_board div. How can i take this little piece of script out of my HTML file and place it in my js file, to still function properly.
Thanks in advance
Inside of your javascript.js put this
window.onload = function {
// content of your script
var newBoard = function(){
// the new updated newBoard() function from below
}
// other parts of your script
if(window.location.href == 'your-url') {
// now, after the newBoard() has been updated
// the next to lines are not needed
// var board = document.getElementById('memory_board');
// board.innerHTML = newBoard();
// just call the function
newBoard();
}
};
UPDATE
I just took a look at your old fiddle and I changed your newBoard function to this
function newBoard(){
tiles_flipped = 0;
var output = '';
memory_array.memory_tile_shuffle();
for(var i = 0; i < memory_array.length; i++){
var div = document.createElement('DIV');
div.id = "tile_" + i;
(function(div,i){
div.onclick = function() {
memoryFlipTile(this, memory_array[i]);
};
}(div,i));
document.getElementById('memory_board').appendChild(div);
}
}
Check the working fiddle.
try to put it like this in external js file
$(document).ready(function(){
newBoard();
});
It looks that you need to call newBoard() method on onload event of memory_board div , You can do this in following ways:
<div id="memory_board" onload="javascript:newBoard()" ></div> // use onload event of memory_board
you can use onload function on the javascript. It will call the function when all the HTML tag is loaded on the screen.

Categories