Javascript FadeIn Not Working Properly - javascript

I need some help with my code, This is what my HTML looks like:
<body onLoad="loader();">
<div class="loader"><img src="images/loader.gif></div>
<div class="main"></div>
CSS:
.main {
display:none;
}
So, the loading Gif Is shown, and then when the page fully loads, it should do this:
function loader() {
setTimeout(function () {
$("#main").fadeIn("fast");
$("#loader").fadeOut("fast");
}, 1000);
};
But all it does, is that the loader div disappears, then the main div appears like it should for a split second, then just dissappears. Thanks in advance for any help. #:)

I think you mean for the loader to fade out after main has faded in, in which case you'll need to take advantage of the callback argument.
You can also use delay() rather than setting a timeout.
You should also use $(document).ready() rather than invoking the function in the onload="" handler.
$(function(){
$('.main').delay(1000).fadeIn('fast', function(){
$('.loader').fadeOut('fast');
});
});
Noted by Blauharley: You are targeting elements with an ID of main (and loader), whereas the elements in your markup use classes.

Related

jquery not quick enough to take effect

I have a need to add a class to certain pages - ones that contain an ID of #hero. For all other pages, the class must not be added.
Because I'm using asp.net with a few layered master pages, its not as simple as just adding a class directly to the html becuase the body tag sits a couple of pages above the aspx page.
I could locate the body tag, but so far I've tried to avoid that due to the added complexity, and instead tried to use jquery.
Here's the code:
$(document).ready(function () {
updateBodyClasses();
});
function updateBodyClasses() {
if($("#hero")) {
$("html, body").addClass("hero");
}
}
Nothing complicated, but here's the rub. By the time the class has been appended, the page has been rendered and the class doesn't seem to have any effect. However, if I test it by adding the class directly to the html, it works - so I know the CSS works and that its a timing issue.
I suppose I could add the code higher up the page - jquery is deferred, so I would need to know the equivalent javascript to try it out.
Would appreciate any thoughts on this potential solution, or perhaps and other ideas.
/* UPDATE */
For clarity, it seems to be the HTML related class that isn't being applied.
You can alter the DOM without waiting for it to be ready.
You need to:
load jQuery in a synchronous way(without defer or async).
Put #hero element i above the script.
Please consider this example:
.red {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero">I don't care about DOM being ready</div>
<script>
var $el = $('#hero');
if ($el.length) {
$el.addClass('red');
}
</script>
You can use IIFE(Immidiately Invocked Function Expression):
like:
(function()
{
if($("#hero")) {
$("html, body").addClass("hero");
}
})();
just put your function in document ready like
$(function(){
if($("#hero")) {
$("html, body").addClass("hero");
}
});
No real solution provided.
Not reasitic to change the whole site infrastructure - from one that defers jquery to loading it synchronously.
The two other jquery answers are as per the current setup and don't work.
The only working solution was provided by Tushar, although it would still require selective loading of the script, which was not included in the answer.
In the end, I used a workaround, which bypassed the need for any javascript. Instead of selectively adding a class to html tag, I added the css permanently to the html tag, affecting all pages. I then added an inner div, which reverses it out. This means that any page can now manipulate its own functionality directly without having to add classes to the html tag.

Manipulation of DOM by JavaScript execution order

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.

.Show() not working in Jquery Mobile

I'm looking to simply hide and image before the page loads and then once the page has loaded to show the image. Problem is when I try to show the image it doesn't show the image at all.
Here is my html code:
<body>
<div id ="splash" data-role="page">
<center>
<div id='class'> <img src="BookBayText.png"></div>
<div id='book'> <img src="Book.png"></div>
</center>
</div>
</body>
Here is my javascript/jquery mobile:
<script type="text/javascript">
$(document).on('pagebeforeshow','#splash',
function()
{
$("#book").hide();
});
$(document).on('pageinit','#splash',
function(){
setTimeout(
function()
{
$("#class").animate({top: "1em"}, 'slow');
},3000);
//For some reason this line below doesn't run
$("#book").show();
});
</script>
Any ideas why this isn't working??
I managed to get the desired effect I wanted with the following code:
setTimeout(
function()
{
$("#class").animate({top: "1em"}, 'slow');
$("#book").show();
},2000);
Basically I moved the $("#book").show(); line into the setTimeout function. But it still leaves me a tad lost as to why the code wouldn't show the image outside the function. If anyone with the answer to this could update this answer it would really be appreciated.
kinda similar to this post jQuery mobile popup on pageinit .
Although the post blames a delay in the browser, for me it is still unclear why it does it. I have never experience such behaviour.
I wonder what if you do the following changes:
put your center tag inside a data-role:content,
replace pageinit for pageshow.
search your iem as follows
inside either pageinit or pageshow (not settimeout).
>
var elem = $("[data-role='page']:last").find('#book img'); // others may use $.mobile.activePage
if (elem.length) {
// check height or img width here...
}

onload for div tag

I have div tag, after some event, I insert (change old content) into this tag, several images and also texts, for example:
$("#some_button").on("click", function () {
$("#mydiv").html("<div>aaaa</div><img src='1.jpg'><div>bbb</div><img src='2.jpg'>");
});
I want, that after load "mydiv" tag full content, alert("mydiv contonet is loaded"). That is, some like this:
$("#mydiv").onload( function () {
alert("mydiv contonet is loaded");
});
Tell please, how can this make?
Divs have no onload event. The best you can do is something like this:
<div id="myDiv">I am a div</div>
<script>// do stuff with loaded div</script>
...unless you can/want to specifically address stuff within the div which does support onload, like images.
.html() is a synchronous operation. The actual updating of the DOM depends on what your html content is. If you have <img> or <iframe> tags, they will take time to load. The next statement following the .html() should immediately see the new html contents.
You can have a callback using .load()
http://api.jquery.com/load/
Preload (http://stackoverflow.com/questions/476679/preloading-images-with-jquery) your images then you won't have to worry about this use case.
You'll have to check the loading of the images you have in your div as there is no callback usable in your case.
The typical way is, for each image
to check if the image is loaded (check if (img.width))
add a onload callback on this image
As you have multiple images, you might want a function like this one :
function onLoadAll(images, callback) {
var n=0;
for (var i=images.length; i-->0;) {
if (images[i].width==0) {
n++;
images[i].onload=function(){
if (--n==0) callback();
};
}
}
if (n==0) callback();
}
that you can call like this :
onLoadAll(imagesObj, function(){
// do something with imagesObj when all images are loaded
});

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