window.onload != <body onload=""> - javascript

This is rather interesting, I think. Consider following code, both the window.onload and body onload="" call the same function. However, the results are different. It appears to me that window.onload has a problem with collections. Here's the code:
<html>
<script type="text/javascript">
window.onload = getSpanElements();
function getSpanElements(){
var collectionBoolean = document.getElementsByTagName("span")?true:false;
alert(
"collection exists? " + collectionBoolean + "; number of collection members: " + document.getElementsByTagName("span").length
);
}
</script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
</head>
<body onload="getSpanElements()">
<span> test </span>
</body>
As you can see, both report that the collection exists, however window.onload reports that it has no members. Any ideas?

You're setting the function wrong:
window.onload = getSpanElements();
should be
window.onload = getSpanElements;
You're setting the onload handler to the return value of getSpanElements() at the moment.

window.onload = getSpanElements();
should be
window.onload = getSpanElements;
The code you have calls the getSpanElements function and assigns its return value as the onload event handler.

You're wrongly doing this:
window.onload = getSpanElements();
which sets the window.onload to the result of the call to the function getSpanElements (undefined).
You should do this instead:
window.onload = getSpanElements;

You might want to move your window.onload assignment below the getSpanElements declaration:
<html>
<script type="text/javascript">
function getSpanElements(){
var collectionBoolean = document.getElementsByTagName("span")?true:false;
alert(
"collection exists? " + collectionBoolean + "; number of collection members: " + document.getElementsByTagName("span").length
);
}
window.onload = getSpanElements;
</script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
</head>
<body onload="getSpanElements()">
<span> test </span>
</body>
At the point in your code where you're assigning the window.onload event handler, getSpanElements() has not yet been defined. Also, the line should be
window.onload=getSpanElements;
not
window.onload=getSpanElements();
The function name without parentheses is a reference to the function. With parentheses, it executes the function and the return value is assigned to window.onload.

You have to assign a reference to the function getSpanElements to window.onload - currently, the function doesn't get executed onload, but immediately after parsing.
What you actually assign is the undefined return value.
In short: drop the ().

I think the window object is created before any actual elements are parsed.

Related

Ask about jquery function operation [duplicate]

This question already has answers here:
How to prevent a click on a '#' link from jumping to top of page?
(24 answers)
Closed 2 years ago.
I'm student and it hasn't been long since I studied programming.
below code is simplified than real for explain.
'test()' is actually Ajax function to get data.
My goal is making 'a tag' for paging operation.
But when i clicked 'a tag', 'test()' inside of '$(document).ready' is called after 'a tag' click event occurred.
So page is always back to 1.
I don't know why this happen.
Anyone could help me?
Thank you!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
var page = 1;
$(document).ready(function(){
test();
alert(page);
});
function test(){
for(var i = 1; i <= 3; i++) {
var a = $("<a></a>").text(i).attr({
href: "",
idx: i
});
a.preventDefault;
$(a).click(function(){
page = $(this).attr("idx");
test();
alert(page);
});
$("#pageLink").append(a," ");
}
}
</script>
</head>
<body>
hello!
<div id="pageLink"></div>
</body>
</html>
For some reason you're calling test() inside of test(). There are a few minor things you need to change also
Prefix jQuery objects with $. var $a=... to avoid ambiguity.
preventDefault is used on the event, not the jQuery object. $a.click(function(event){event.preventDefault();...});
Otherwise it works as I believe you want it to, alerting the page number on click.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
createLinks();
});
function createLinks(){
for(var i = 1; i <= 3; i++) {
var $a = $("<a></a>").text(i).attr({
href: "",
idx: i
});
$a.click(function(event){
event.preventDefault();
page = $(this).attr("idx");
// why are you calling this again? // test();
// maybe you want to load something // loadSomething(page);
alert(page);
});
$("#pageLink").append($a," ");
}
}
</script>
</head>
<body>
hello!
<div id="pageLink"></div>
</body>
</html>

Javascript immediate function call from external function

I am trying to call the immediate function defined in test1.js on click of the button defined under html file. It always throws error "test is undefined". I am little bit aware that being a immediate function, it calls immediately, and so it returns the "undefined error". But is there any way I can call the immediate function (access methods, properties, etc.) on click of the button?
Thank you in advance.
//test1.js
var test = (function(){
alert(window);
var tmp = 'hello';
}());
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="test1.js"></script>
<input type="button" id="btn1" value="ClickMe!" />
<script type="text/javascript">
var btn = document.getElementById("btn1");
btn.addEventListener("click",fun1,false);
function fun1(){
alert(test.tmp);
}
</script>
</body>
</html>
You have to modify your code so that the IIFE returns an object with a tmp property. Such as
var test = (function(){
alert(window);
var tmp = 'hello';
return {tmp:tmp};
}());
You need to explicitly return an object containing any data you want made available after you run the IIFE. (Just add the return as I did to the snippet below).
//test1.js
var test = (function(){
alert(window);
// you need to return any values you want accessible
return {
tmp: "hello"
}
}());
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="test1.js"></script>
<input type="button" id="btn1" value="ClickMe!" />
<script type="text/javascript">
var btn = document.getElementById("btn1");
btn.addEventListener("click",fun1,false);
function fun1(){
alert(test.tmp);
}
</script>
</body>
</html>

Why can I call function which is in a shadow dom?

I created a custom element called "memory-box" like the below code.
Please pay attention to the function "logthis" which is in "memory-box-template".
memory-box.html
<template id="memory-box-template">
<input id="memory-box" type="form" />
<input type="button" id="testbutton" />
<script type="text/javascript">
function logthis(me){
console.log(me);
}
</script>
</template>
<script type="text/javascript">
(function() {
var thisDoc = document.currentScript.ownerDocument;
var storage = localStorage;
var proto = Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var temp = thisDoc.querySelector('#memory-box-template');
var con = document.importNode(temp.content, true);
this.createShadowRoot().appendChild(con);
var input = this.querySelector('::shadow #memory-box');
var data = storage.getItem(this.id);
input.value = data;
input.addEventListener('input', saveData.bind(input, this.id));
}
},
});
document.registerElement('memory-box', {
prototype: proto
});
function saveData(id, e) {
storage.setItem(id, this.value);
}
})();
</script>
Now, I uses the custom element "memory-box" like the below code.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="import" href="/html/memory-box.html">
</head>
<body>
<div><memory-box id="memory1"></memory-box></div>
<div><memory-box id="memory2"></memory-box></div>
<div><memory-box id="memory3"></memory-box></div>
<div><memory-box id="memory4"></memory-box></div>
</body>
<script type="text/javascript">
logthis(this);
</script>
</html>
As you can see, I putted a script in the index.html and called the function "logthis" just because I was curious. And no error occurred.
Why?
The function "logthis" is in each shadow doms. It's supposed not able to be called outside the shadow dom, I think.
As explained here, while the HTML within Shadow DOM is encapsulated, any JavaScript is NOT -- it is in the global scope, unless you utilize specific javascript techniques (namescaping, IIFE) to do so.
Hope this helps,
Jonathan Dodd

document.createElement fails for new window

I have two HTML files, FirstWindow and SecondWindow. FirstWindow has FirstWindowJS.js as its script and SecondWindow has SecondWindowJS.js as its script.
Through FirstWindowJS.js, I open SecondWindow.html. However, I am unable to create an element for it. Here's the code along with the problem -
FirstWindow.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>FirstWindow</title>
</head>
<body>
<script type="text/javascript" src="FirstWindowJS.js"></script>
</body>
</html>
SecondWindow.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>SecondWindow</title>
</head>
<body>
<script type="text/javascript" src="SecondWindowJS.js"></script>
</body>
</html>
FirstWindowJS.js
main();
function main()
{
var myWindow = window.open("SecondWindow.html", "My Window",
"resizable=0,width=700,height=600");
var e = myWindow.document.createElement("currentUserElement");
e.setAttribute("id", "currentUserElement");
e.setAttribute("value","John");
}
SecondWindowJS.js
main();
function main()
{
var e = document.getElementById("currentUserElement");
var value = e.getAttribute("value");
console.log("value = "+value);
}
The error that I get in the SecondWindowJS.js is -
TypeError: e is null
Why is "e" null? What is the mistake?
It's possible that the new window runs its JavaScript before the opener's script continues, but it's more likely that you can't use getElementById on an element that has not been appended to the document yet.
myWindow.document.body.appendChild(e);
You create the element, but it doesn't look like you are adding it to the DOM. An element doesn't exist in the DOM until you explicitly add it using the parentNode.appendChild() method.
In your case it would look something like this, if you just want to add the element as the last element in your body-element:
function main()
{
var myWindow = window.open("SecondWindow.html", "My Window",
"resizable=0,width=700,height=600");
var e = myWindow.document.createElement("currentUserElement");
e.setAttribute("id", "currentUserElement");
e.setAttribute("value","John");
// The element doesn't exist in the DOM until you explicitly add it
myWindow.document.body.appendChild(e);
}

Can the mouseover event be used on any element, or only on images?

<html >
<head>
<title>JavaScript Example</title>
<script type="text/javascript">
function greet {
var greet = document.getElementById("greeting");
greet.value="this is dynamic";
</script>
</head>
<body>
<p onmouseover="greet()"> Hello! Welcome to My Page </p>
</html>
What is the problem in this code?
Firstly, you haven't closed your greet function (missing the closing } character). Secondly, you're missing the parentheses after the name of the function:
function greet() {
//Function body
}
Secondly, you're using getElementById to try and obtain a reference to the p element, but the p element doesn't have an id.
Thirdly, the greet variable will contain a reference to a p element, which doesn't have a value property (like, for example, input elements do). You may have meant innerHTML if you are trying to change the contents of the element.
Finally, you haven't closed your <body> element. Edit (see comments) - This isn't a problem, but personally I prefer closing it for consistency.
You could pass a reference to the element into the function when it's called, to save you having to get it by id:
<p onmouseover="greet(this);">Example</p>
And JavaScript:
function greet(elem) {
elem.innerHTML = "Something new";
}
the p element should have an ID of greet, as in:
<p onmouseover="greet()" id="greeting"> Hello! Welcome to My Page </p>
, so that when you select the element's ID at:
document.getElementById("greeting");
the document can find the tag you are trying to select from the HTML document.
Additionally, instead of editing the node's "value" attribute, I think you need to use the "innerHTML" instead. So that gives:
<html >
<head>
<title>JavaScript Example</title>
<script type="text/javascript">
function greet {
var greet = document.getElementById("greeting");
greet.innerHTML="this is dynamic";
}
</script>
</head>
</body>
<p onmouseover="greet()" id="greeting"> Hello! Welcome to My Page </p>
</html>
I am not exactly familiar with JavaScript, but I believe that should work.
You can try:
greet = function(elem) {
elem.innerHTML = "Something new";
}
or
greet = function() {
var greet = document.getElementById("greeting");
greet.innerHTML="this is dynamic";
}
Along with the other tips of course(like id attribute for the relevant <p> element and well-forming your HTML).

Categories