Manipulation of DOM by JavaScript execution order - javascript

I have the following code and results is attached at the end. I understand that JQuery.ready and JQuery.Window load events are run after the DOM is created so it can manipulate the DOM but not the first function to change the background of John.
My questions are:
The background of John has not changed to yellow is because JavaScript is backward referencing by nature and it can't locate the element with the id name1 at the point when the script is run?
If I have to run the first function to change the background of John, should this function be used after the DIV tags?
Blockquote
<script>
(function () {
$('#name1').css('background-color', 'yellow');
})();
$(function () {
$('#name2').css('background-color', 'red');
});
$(window).load((function () {
$('#name3').css('background-color', 'blue');
}));
</script>
<div id="name1">John</div>
<div id="name2">Mary</div>
<div id="name3">Jacob</div>
<div id="name4">James</div>
<script>
(function () {
$('#name4').css('background-color', 'yellow');
})();
</script>
Blockquote

HTML gets read by the browser from top to bottom. So:
<script>
this gets executed immediately: (but as nothing is there yet, there will be no change). To further explain, these are called immediate executed functions (IEFs) ==> (function(){ ... })(); but in this case is pointless to have it because the code will be executed immediately anyway.
(function () {
$('#name1').css('background-color', 'yellow');
})();
this is actually a shortcut in jQuery for $(document).ready(...); It is consider not such a good practice because it is not as readable.
$(function () {
$('#name2').css('background-color', 'red');
});
this one does a window load (which is not exactly the same).
$(window).load((function () {
$('#name3').css('background-color', 'blue');
}));
</script>
<div id="name1">John</div>
<div id="name2">Mary</div>
<div id="name3">Jacob</div>
<div id="name4">James</div>
<script>
this is also executed immediately (IEFs): in this case it will work but it is not a best practice to do this.
(function () {
$('#name4').css('background-color', 'yellow');
})();
</script>
if you want to know more of the differences between document.ready and window.load, look at this stackoverflow question
JavaScript is an event driven language, and the advantage is that you can add as many listeners to events as you need, so adding an event listener to DOM content loaded would be —almost— always the best approach. It is also a best practice to load the scripts always at the end, this way you let the user get the content and styles first and then the functionality kicks in.
How I would have written your code:
<div id="name1">John</div>
<div id="name2">Mary</div>
<div id="name3">Jacob</div>
<div id="name4">James</div>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
// DOM fully loaded and parsed
$('#name1').css('background-color', 'yellow');
$('#name2').css('background-color', 'red');
$('#name3').css('background-color', 'blue');
$('#name4').css('background-color', 'yellow');
});
</script>
Although I wouldn't have used jQuery for this :P. I wouldn't even have used JavaScript for this, just good old CSS ;)

When manipulating the DOM via Javascript (or a Javascript library or framework) you must bring those elements of the DOM you want to manipulate into existence before you attempt to manipulate them.
If you don't, then... there is simply nothing there to manipulate.

Related

How to access an HTML element within a self invoked function.

I am pretty new to JavaScript so I don't know the ins and outs of the language but I do have some knowledge of it. I created a self invoked function that would sort an array of zip-codes and then output it to a div element in the html file.
Unfortunately, the output isn't going into the div element because the function is executed before the html elements is ready, therefor it doesn't exist.
Is there anyway that I could access the div element within the function without having to use Window.Load, etc?
Thank you! click on the link below to view my function.
Screenshot of function
Is there anyway that I could access the div element within the
function without having to use Window.Load, etc?
Just move that code to the end of your html - after elements in question.
For example after </body>
From what I know, you can't access the DOM if it doesn't exist in that moment.
I know I know, don't use window.onload. But I assure you this is different than waiting for the DOM to load and then follow up with your calculations.
You can have a function evaluate something, then actually hang on the result and wait, and then finally fill the innerHTML when the DOMContentLoaded event has fired... or perhaps something of similar flavour, have a look at this.
<script>
const calculations = (function () {
// Super smart calculations...
var output = "Result of smart calculations";
function findWhereOutputGoes() {
return document.getElementById('output-div');
}
return {
output: output,
findWhereOutputGoes: findWhereOutputGoes,
}
})();
document.addEventListener('DOMContentLoaded', function(){ // Fires as soon as DOM has loaded
calculations.findWhereOutputGoes().innerHTML = calculations.output;
});
</script>
<div id="output-div">
</div>

Rerun Jquery function onclick

I have a simple jquery script that changes the url path of the images. The only problem is the doesn't apply after I click the load more button. So I'm trying to do a workaround where it calls the script again after clicking the button.
<script type='text/javascript'>
$(document).ready(function ReplaceImage() {
$(".galleryItem img").each(function() {
$(this).attr("src", function(a, b) {
return b.replace("s72-c", "s300")
})
})
});
</script>
HTML
Load More
While Keith's answer will get you what you are looking for, I really can't recommend that approach. You are much better off with something like this.
<script type="text/javascript">
$(function() {
var replaceImage = function() {
$('.galleryItem img').each(function() {
$(this).attr('src', function(index, value) {
return value.replace('s72-c', 's300');
});
});
};
replaceImage();
$('.js-replace-image').on('click', replaceImage);
});
</script>
Using this html
<button class="js-replace-image">Load More</button>
By taking this approach, you do not expose any global variables onto the window object, which can be a point of issue if you work with other libraries (or developers) that don't manage their globals well.
Also, by moving to a class name and binding an event handler to the DOM node via JavaScript, you future proof yourself much more. Also allows yourself to easily add this functionality to more buttons very easily but just adding a class to it.
I updated the anchor tag to a button because of the semantics of what you need to do - it doesn't link out anywhere, it's just dynamic functionality on the page. This is what buttons are best served for.
I'd also recommend putting this in the footer of your site, because then, depending on your situation, you will already have the images updated properly without having to click the button. The only need for the button would be if you are dynamically inserting more images on the page after load, or if this script was in the head of your document (meaning jQuery couldn't know about the images yet).
I hope this helps, reach out if you have questions.

How to call jQuery function in HTML <body> onload?

I want to call a jQuery function from an HTML <body> tag. Here's my HTML:
< body bgcolor="#ffffff" onLoad="???" >
How would I call a jQuery function when the page is loaded? My jQuery function looks like this
jQuery(function($){
var input_id;
//code
});
whatever code you write in the below method(block) would be executed automatically after the DOM load. You need not call this from HTML component again.
$(document).ready(function() {
//your code
});
This topic has been covered here before.
You are most likely looking for
$(document).ready(function() {
var input_id;
//code
})
Or
$(window).load(function($) {
var input_id;
//code
});
If you are curious about the difference between these two, see the JQuery documentation on the topic.
Also note that <body onload="">, which you seem to be trying to use, is generally not compatible with the above JQuery.
$(function() {
// code
});
This is shorthand for document.ready() so it will wait for the body to finish loading before executing.
HTML: You're on the right track, but you do not have to have put JS in the body tag. See the JS options below:
<body bgcolor="#ffffff">
JS
$(window).load(function($) {
functionA(arg1, arg2, arg3);
});
This will fire up functionA() once the DOM including graphics have fully loaded.
OR
$(document).ready(function($) {
functionA(arg1, arg2, arg3);
});
This will fire functionA() once the DOM has loaded and before any graphics finish loading.
As of Jquery 3, the following syntax is depreciated:
document.ready(function(){
//code
});
The recommended alternative in Jquery 3 is to use the following syntax (which in previous versions was just considered a shorthand syntax):
$(function(){
//code
});
Here is is the official Jquery explanation for why the first syntax was depreciated and is no longer recommended (https://api.jquery.com/ready/):
... The selection [of document] has no bearing on the behavior of the .ready() method, which is inefficient and can lead to incorrect assumptions about the method's behavior.
document.ready(function($){
// here you go
})

How to execute code before window.load and after DOM has been loaded?

Here is the circumstance:
I have 2 pages:
1 x html page
1 x external Javascript
Now in the html page, there will be internal Javascript coding to allow the placement of the window.onload, and other page specific methods/functions.
But, in the external Javascript I want certain things to be done before the window.onload event is triggered. This is to allow customized components to be initialized first.
Is there a way to ensure initialization to occur in the external Javascript before the window.onload event is triggered?
The reason I have asked this, is to attempt to make reusable code (build once - use all over), to which the external script must check that it is in 'order/check' before the Javascript in the main html/jsp/asp/PHP page takes over. And also I am not looking for a solution in jQuery #_#
Here are some of the links on Stack Overflow I have browsed through for a solution:
Javascript - How to detect if document has loaded (IE 7/Firefox 3)
How to check if page has FULLY loaded(scripts and all)?
Execute Javascript When Page Has Fully Loaded
Can someone help or direct me to a solution, your help will be muchness of greatness appreciated.
[updated response - 19 November 2012]
Hi all, thanks for you advice and suggested solutions, they have all been useful in the search and testing for a viable solution.
Though I feel that I am not 100% satisfied with my own results, I know your advice and help has moved me closer to a solution, and may indeed aid others in a similar situation.
Here is what I have come up with:
test_page.html
<html>
<head>
<title></title>
<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript" src="test_script_1.js"></script>
<script type="text/javascript" src="test_script_2.js"></script>
<script type="text/javascript">
window.onload = function() {
document.getElementById("div_1").innerHTML = "window.onload complete!";
}
</script>
<style type="text/css">
div {
border:thin solid #000000;
width:500px;
}
</head>
<body>
<div id="div_1"></div>
<br/><br/>
<div id="div_2"></div>
<br/><br/>
<div id="div_3"></div>
</body>
</html>
loader.js
var Loader = {
methods_arr : [],
init_Loader : new function() {
document.onreadystatechange = function(e) {
if (document.readyState == "complete") {
for (var i = 0; i < Loader.methods_arr.length; i++) {
Loader.method_arr[i]();
}
}
}
},
load : function(method) {
Loader.methods_arr.push(method);
}
}
test_script_1.js
Loader.load(function(){initTestScript1();});
function initTestScript1() {
document.getElementById("div_1").innerHTML = "Test Script 1 Initialized!";
}
test_script_2.js
Loader.load(function(){initTestScript2();});
function initTestScript2() {
document.getElementById("div_2").innerHTML = "Test Script 2 Initialized!";
}
This will ensure that scripts are invoked before invocation of the window.onload event handler, but also ensuring that the document is rendered first.
What do you think of this possible solution?
Thanking you all again for the aid and help :D
Basically, you're looking for this:
document.onreadystatechange = function(e)
{
if (document.readyState === 'complete')
{
//dom is ready, window.onload fires later
}
};
window.onload = function(e)
{
//document.readyState will be complete, it's one of the requirements for the window.onload event to be fired
//do stuff for when everything is loaded
};
see MDN for more details.
Do keep in mind that the DOM might be loaded here, but that doesn't mean that the external js file has been loaded, so you might not have access to all the functions/objects that are defined in that script. If you want to check for that, you'll have to use window.onload, to ensure that all external resources have been loaded, too.
So, basically, in your external script, you'll be needing 2 event handlers: one for the readystatechange, which does what you need to be done on DOMready, and a window.onload, which will, by definition, be fired after the document is ready. (this checks if the page is fully loaded).
Just so you know, in IE<9 window.onload causes a memory leak (because the DOM and the JScript engine are two separate entities, the window object never gets unloaded fully, and the listener isn't GC'ed). There is a way to fix this, which I've posted here, it's quite verbose, though, but just so you know...
If you want something to be done right away without waiting for any event then you can just do it in the JavaScript - you don't have to do anything for your code to run right away, just don't do anything that would make your code wait. So it's actually easier than waiting for events.
For example if you have this HTML:
<div id=one></div>
<script src="your-script.js"></script>
<div id=two></div>
then whatever code is in your-script.js will be run after the div with id=one but before the div with id=two is parsed. Just don't register event callbacks but do what you need right away in your JavaScript.
javascript runs from top to bottom. this means.. if you include your external javascript before your internal javascript it would simply run before the internal javascript runs.
It is also possible to use the DOMContentLoaded event of the Window interface.
addEventListener("DOMContentLoaded", function() {
// Your code goes here
});
The above code is actually adding the event listener to the window object, though it's not qualified as window.addEventListener because the window object is also the global scope of JavaScript code in webpages.
DOMContentLoaded happens before load, when images and other parts of the webpage aren't still fully loaded. However, all the elements added to the DOM within the initial call stack are guaranteed to be already added to their parents prior to this event.
You can find the official documentation here.

jQuery each doesn't work with certain classes, or classes in general?

I'm using Phonegap to build a small (test only) Macrumors application, and remote hosts actually work (there is no same host browser restrictions). I am using the jQuery Load() function to load the contents of the Macrumors homepage http://www.macrumors.com/ into a bin, hidden div, then the each function to loop through all the article classes to show the title in a box with a link to the page.
The problem is, after the Macrumors HTML content is loaded, the each function doesn't work with the article class. Also, in the load function (which allows you to specify certain selectors, id's and classes included, to only load in those sections of the page) the class doesn't work; none of the classes do, in both the load function and each function. And many Id's don't work in the each function either.
Can anybody explain this to a noob like me?
Here is the code:
function onDeviceReady()
{
// do your thing!
$('#bin').load('http://www.macrumors.com/ #content');
$('.article').each(function(){
var title = $('a').html();
$('#content').append('<b>'+title+'</b>')
});
}
And the HTML stuff
<body onload="onBodyLoad()">
<div id="bin">
</div>
<div id="content">
</div>
</body>
I sincerely apologize if there's some very simple mistake here that I'm missing; I'm a major JS newbie.
.load() is asychronous. It hasn't completed yet when you're executing .each(). You need to put your .each() and any other code that wants to operate on the results of the .load() in the success handler for .load().
You would do that like this:
function onDeviceReady()
{
// do your thing!
$('#bin').load('http://www.macrumors.com/ #content', function() {
$('.article').each(function(){
var title = $('a').html();
$('#content').append('<b>'+title+'</b>')
});
});
}
I'm also guessing that your .each() function isn't working quite right. If you want to get the link out of each .article object, you would need your code to be like this so that you're only finding the <a> tag in each .article object, not all <a> tags in the whole document:
function onDeviceReady()
{
// do your thing!
$('#bin').load('http://www.macrumors.com/ #content', function() {
$('.article').each(function(){
var title = $(this).find('a').html();
$('#content').append('<b>'+title+'</b>')
});
});
}

Categories