newtab content cannot be alter using javascript? - javascript

I want to alter the content of my newtab using javascript. In my manifest.json I have this
"chrome_url_overrides": {
"newtab": "index.html"
}
then in my index.html I have
<script src="jquery.js"></script>
<script src="script.js"></script>
<body>
<h1>hello world</h1>
</body>
then in my script.js I do $('h1').remove() nothing triggered. Why? When I try to do console.log($) it worked.

Your code runs as soon as Chrome inserts the <script> tag into the DOM tree.
By the time that happens, <h1> is not there yet.
There are two solutions; one is to simply move the <script> tag below the nodes you refer to.
The other, preferable solution is to use an event that says "okay, DOM tree is complete, you can work with nodes now". Using jQuery, it will be the ready event:
$(document).ready(function() {
/* your code here */
});
Or, shortened,
$(function() {
/* your code here */
});

Related

Does jQuery .length defies DOM ready?

I have this code:
Function loader() will keep running until <body> does exist. When <body> does exist, insert .loader
<html>
<head>
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
loader();
function loader() {
if (!$('body').length) {
window.requestAnimationFrame(loader);
} else {
$('<div class="loader"></div>').prependTo('body');
}
};
</script>
</head>
<body>
<!-- elements -->
</body>
</html>
I want to ask this line
if (!$('body').length) {}
What do .length use to determine its return, is it <body> or <body></body>? Does .length wait for closing tag </body> or not? If it does, what is my alternatives? I need .loader to be inserted without waiting for </body>.
My last resort would be
<body>
<div class="container"></div>
<!-- rest of elements -->
</body>
So then
if (!$('.container').length) {}
But I need alternatives that don't interfere with the elements structure.
EDIT:
I rephrase the question and add below codes.
<html>
<head>
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
console.log("ready timestamp");
});
loader();
function loader() {
if (!$('body').length) {
window.requestAnimationFrame(loader);
} else {
console.log("length timestamp");
}
};
</script>
</head>
<body>
<!-- elements -->
</body>
</html>
Output:
15:03:19.862 length timestamp
15:03:20.198 ready timestamp
Length timestamp always lower than ready timestamp.
Tested with:
Chrome 71.0 and FF 65.0
Enable timestamp in Console Settings (Developer Tools -> Console -> Show timestamps).
Other might ask why I did this, what's right about 300ms?
I implement PWA and need loader, like this:
Showing loader while navigating between pages - PWA.
The problem is, there is 300ms between .on('beforeunload') of the previous page and $() of the next page. It's a blip, obviously.
This blip can ideally/easily be solved by server side scripting but as I mentioned above, I have no access to server side scripting, the furthest I can ask is a blank element <div class="container"></div>.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
console.log( $('#tryToFindMe').length );
</script>
<div id="tryToFindMe"></div>
Similar to how your question tries to access the body before it is defined, this snippet tries to access the div before it is defined. In both cases, the element will not be found.
The reason for this is because when your browser is parsing your webpage into the Document Object Model it parses from top down. So at the point that the script runs, the html that will create the div in the DOM has not been processed yet. So the script tries to lookup the element, it does not exist, and the length is zero.
This is why using the jQuery document ready, binding to the DOMContentLoaded event or the load event exist. These different approaches defer the execution of your logic until either the entire page has been parsed into the DOM, or in the case of load, that not only the page has been parsed into the DOM, but all the resources have been received as well (images, videos, etc). Without these approaches, the script will need to appear in the page after the element is defined to ensure the element exists already in the DOM.
The important part when thinking about interacting with the DOM is not to think in terms of HTML. The DOM contains Nodes, not HTML. The nodes are generated from the HTML.
You can just use a jQuery document ready function ($(() => {})) like so:
$(() => {
$(`<div class="loader"></div>`).prependTo("body");
});
I ran another test.
<html>
<head>
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
console.log("ready timestamp");
});
loader_bottom();
loader_body();
loader_top();
function loader_bottom() {
if (!$('.container_bottom').length) {
window.requestAnimationFrame(loader_bottom);
} else {
console.log("container_bottom.length timestamp");
}
};
function loader_top() {
if (!$('.container_top').length) {
window.requestAnimationFrame(loader_top);
} else {
console.log("container_top.length timestamp");
}
};
function loader_body() {
if (!$('body').length) {
window.requestAnimationFrame(loader_body);
} else {
console.log("body.length timestamp");
}
};
</script>
</head>
<body>
<div class="container_top"></div>
<!-- elements between -->
<div class="container_bottom"></div>
</body>
</html>
Output:
09:09:16.894 body.length timestamp
09:09:16.897 container_top.length timestamp
09:09:17.090 container_bottom.length timestamp
09:09:17.220 ready timestamp
Because $('.container_top') adjacent to $('body'), changing the sequence,
loader_top();
loader_body();
Not suprisingly output:
09:09:39.708 container_top.length timestamp
09:09:39.708 body.length timestamp
Hence I come into conclusions:
Does jQuery .length defies DOM ready? Yes it does.
What do .length use to determine its return, is it <body> or <body></body>? It is <body>.
Although the right phrase for second question should be:
What DOM Parser use to determine nodes, is it <tag> or <tag></tag>? The answer is <tag>.
Actually I'm not surprised that we can manipulate DOM before it's ready. Besides, $().ready() is just an event when DOM is ready. Javascript is multi-thread so (I thought) DOM Manipulating should could run parallel with DOM Parsing. Not until this code I can prove that.

How to add onload to HTML without it being part of the body tag?

I was told to add a tag being generated in Joomla. I just need to add the onload=... between the body tags. Is there a way to add the onload=... by itself or must it be part of the tag? Thanks!
If I understand the question correctly, and you need to trigger some JavaScript to run after the document is ready without editing the body tag itself, you could add it as follows:
<script>
jQuery(document).ready(function() {
// Your code
}
</script>
Notice the lack of "$". In Joomla, avoid using $ to reference jQuery to prevent conflicts with other JS tools.
If I've completely missed the mark, please clarify in a comment.
You can bind the event handler with JavaScript.
<script>
addEventListener('load', yourFunction);
function yourFunction(event) {
// ...
}
</script>
If you add a <script> tag to the header of the page, you can then add an event listener for the page load. Or a better option is to prevent render blocking code and add the <script> tag to the bottom of the page and have it run right away, since the page is already loaded.
Render Blocking Method
<html>
<head>
<script>
window.addEventListener('load',pageLoaded,false);
function pageLoaded(e) { console.log('Loaded'); }
</script>
</head>
<body>
</body>
</html>
Non Render Blocking
<html>
<head>
</head>
<body>
<!-- All The Body Content -->
<script>
(function() {
console.log('Loaded');
})();
</script>
</body>
</html>

JavaScript not working as an external file

I'm new to HTML, JavaScipt and everything related to programming, and I'm trying to create a simple page.
Now, I'm stuck with the following problem: I want to change the date of my main.html file, but the main.js is not working. I've already change the <script> position to inside the <body>, after the </span> and even after the </body>, without success. If the content of the main.js is within the HTML it works fine, but as a external file it doesn't.
Here is my main.html:
<!DOCTYPE html>
<html>
<head>
<link href="main.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="main.js"></script>
<title>Page 1</title>
</head>
<body>
<p>WRF<br>
<span id="data">18/09/1987</span></p>
</body>
</html>
My main.js is just:
document.getElementById("data").innerHTML = "JUBA";
I've looked through the internet and through this forum, but all answers that I've found did not worked.
The files are on the same directory and the main.css works fine.
Thank you in advance.
At time you call main.js element #data was not created in DOM tree. You can fix this by putting the link to your Javascript file right before closing the body like this:
<script type="text/javascript" src="main.js"></script>
</body>
Document Object Model (DOM) is not "READY".
Try use onload event, inside main.js:
window.onload = function() {
document.getElementById("data").innerHTML = "JUBA";
};
If needs more "fast" than onload, use jquery with $(document).ready:
html:
<link href="main.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="main.js"></script>
main.js:
$(document).ready(function() {
$("#data").html("JUBA");
});
window.onload vs $(document).ready()
Answer by #Guffa:
The ready event occurs after the HTML document has been loaded, while the onload event occurs later, when all content (e.g. images) also has been loaded.
The onload event is a standard event in the DOM, while the ready event is specific to jQuery. The purpose of the ready event is that it should occur as early as possible after the document has loaded, so that code that adds functionality to the elements in the page doesn't have to wait for all content to load.
The element is not yet accessible when you run the script.
Either you can put the script at the end of the page or delay the execution.
You could put the JavaScript in the <body> tag after the rest of the page. When the browser loads it, the <span> will already be there to be edited.
As per your code the script will be called first then page will be loaded, therefore when the script is running there will not be any element having id data because yet page have to be loaded. There are many ways to achieve what you need.
1. Add a script tag before or after end of body like
or
<script type="text/javascript" src="main.js"></script>
</body>
Write .js file above before body i.e. in head tag and write the whole javascript code in onload method.
window.onload=function(){
document.getElementById("data").innerHTML = "JUBA";
};
window.onload=function(){
document.getElementById("data").innerHTML = "JUBA";
};
<p>WRF<br>
<span id="data">18/09/1987</span></p>

javascript tag trigger - code position on page

i use that tag to alert me when a tag has been shows up
<html>
<head>
</head>
<body>
<script type="text/javascript">
document.getElementsByTagName('iframe')[0].onload = function() {
alert('loaded');
}
</script>
<iframe></iframe>
</body>
</html>
strange , since this code working :
<html>
<head>
</head>
<body>
<iframe></iframe>
<script type="text/javascript">
document.getElementsByTagName('iframe')[0].onload = function() {
alert('loaded');
}
</script>
</body>
</html>
why the Js need to under the tag to work?
what's the problem here?
Because the code in a script tag is executed immediately. And in the first example the iframe doesn't exist at that time. But what you can do is to wrap you code into an onload (for the main page) event. E.g.:
window.onload = function() {
//your code
}
Then it doesn't matter where the code is placed.
Iframe tag does not exist at the moment you are trying to access it.
You may check that by simply alerting array length, like
alert(document.getElementsByTagName('iframe'));
Have you thought about executing your javascript after the page is loaded? You may use some frameworks like jQuery to facilitate crossbrowser issues. Or just put all your javascript code to the very bottom of body.

Basic jQuery .load Problem

I am trying to use jQuery's .load function to dynamically load content into my webpage. This seem so simple, but I cannot make it work. To try and figure it out, I made a test page with just basic structure, but the external content still won't load:
jquery.html
<html>
<head>
<title>JQuery Test</title>
<script src="jquery1.5.min.js"></script>
</head>
<body>
<script>
$('#foo').load('test.html');
</script>
<div id="foo"></div>
</body>
</html>
test.html
<p>Text text</p>
I'm sure I have made a tiny error, but I can't find it anywhere!
You need to encapsulate your script in the $(document).ready() otherwise #foo won't exist when the script is executed:
<script>
$(document).ready(function(){
$('#foo').load('test.html');
});
</script>
You need to wait for the document to be ready before you can access the DOM. Just add a $(document).ready() around your original code:
<html>
<head>
<title>JQuery Test</title>
<script src="jquery1.5.min.js"></script>
</head>
<body>
<script>
$(document).ready( function() {
$('#foo').load('test.html');
});
</script>
<div id="foo"></div>
</body>
</html>
or if you want a shorter code:
$(function() {
$('#foo').load('test.html');
});
Informally, what's happening is that, as your browser reads the code you wrote, it's drawing its contents as it goes along. When it reaches your <script> tag, it executes it. But when $("#foo") gets executed, the browser's still processing the <script> and hasn't reached the part of the code where you told it there's a div called foo, so the browser doesn't know it exists, and jquery will just find nothing.
Of course, the idea that the browser will just sequentially read your code and render it as it goes is naive at best, so while it might seem that just moving the <script> tag to the bottom of the code would work, you're not actually guaranteed it will work. Instead, the browser will notify you when it's done drawing the page by firing a load (and possibly a DOMContentLoaded) event. So all code that depends on the whole html being drawn should be executed in an event handler bound to those events.
jQuery makes waiting for the page to be loaded easy, just use something like this:
$.ready(function() {
doStuff();
});

Categories