Ok so for a site that is heavily graphic based I had to come up with a way for the user not to watch each image load in one by one. So I developed the following code as a sort of preloader until all the images on the page are ready. I know usually we shouldn't delay seeing page content for images, but the images are the only content on the page so I chose the lesser evil of faux-preloading.
The code works like this : it finds all the images in the ul page, holds them in a var (images) and fades in its parent li once the image in scope has loaded. It also has a check for when the image is being pulled from the cache. This creates a nice one by one fade in of the empty li's which are styled as empty boxes until the images themselves are loaded and the rest functionality of the page is triggered.
Now the problem : ie9 and ie10 only get halfway through the process and then randomly stops thus the page never finishes "loading" and the site is nonfunctioning. I've tried a few things but Im not sure what the problem is. The html and js are below.
The images html (only show two of 80 something li's :
<ul>
<li class="ch-one link">
<img class="gif" src="_images/_gifs/_inthemess/inthemess_1.gif" />
<img src="_images/_spreads/_thumbs/spread-04.jpg" />
</li>
<li class="ch-one link">
<img class="gif" src="_images/_gifs/_inthemess/inthemess_2.gif" />
<img src="_images/_spreads/_thumbs/spread-05.jpg" />
</li>
</ul>
The gif is revealed on mouse over, the jpg is the solid state.
var images = $('.spreads').find('img');
var loadedLen;
var liLen;
var x = 0, i = 0;
images.each(function () {
if ($(this).complete) {
$(this).parent().animate({
'opacity': '1'
}, 1000);
$(this).parent().addClass('loaded');
checkPageState();
} else {
$(this).load(function () {
$(this).parent().animate({
'opacity': '1'
}, 1000);
$(this).parent().addClass('loaded');
checkPageState();
});
};
function checkPageState() {
//check if all images are loaded
//if they are animate TOC in
loadedLen = $('.spreads li.loaded').length;
liLen = $('.spreads li').length;
if (loadedLen === liLen) {
showPages();
console.log('#showPages call from checkPageState');
} else if (loadedLen === 10) {
//fix li height issue
var imgHeight = $(images[4]).height() + 2;
};
};
});
function showPages() {
var ph = $(document).height();
//then we call the function that will loop
//and fade in each image until it reaches the last one
pageTime = setTimeout(function () {
clearTimeout(pageTime);
fadeInEachPage();
}, 100);
function fadeInEachPage() {
if (i < images.length) {
clearTimeout(pageTime);
//start the countdown first
pageTime = setTimeout(function () {
i++;
fadeInEachPage();
}, 1);
theImage = images[i];
$(theImage).not('.gif').animate({ 'opacity': '1' }, 800);
} else if (i === images.length) {
//trash collection
//fadeInEachPage is called so frequently the program
//will pass else if (i === images.length) a few times
//thus causing the text to pulse in correctly
if( x === 0 )
{
//adds listener for mouse over effect
addGifListener();
$('#overview header h1.title').stop().animate({ 'opacity': '0' }, 300);
var inTime = setTimeout(function () {
clearTimeout(inTime);
$('#overview header h1.title').html('Thank you for purchasing the 6 Memos eBook. Simply select a chapter to enjoy full size.');
$('#overview header h1.title').stop().animate({ 'opacity': '1' }, 300);
}, 2000);
var finalTitleTime = setTimeout(function() {
clearTimeout(finalTitleTime);
$('#overview header h1.title').stop().animate({ 'opacity': '0' }, 300);
}, 8000);
var finalFadeIn = setTimeout( function() {
$('#overview header h1.title').html('6 Memos');
$('#overview header h1.title').stop().animate({ 'opacity': '1' }, 300);
clearTimeout(finalFadeIn);
}, 9000);
//trash collection
x++;
} else {
return;
};
};
};
};
Thanks for the help!
The solution for this was $(this).prop('compelete'); as suggested by Musa.
Using $(this).prop('complete') or $('img').prop('complete') will catch any image files already on the page when the js is deployed; whereas load() only checks if it has loaded since the js was deployed.
This was what I was trying for with $(this).complete(); - which seems to be associated with AJAX and thus was not passing the conditional causing the rest of the images to be loaded and displayed while leaving the ones which loaded before the js in the dark - so to speak.
Related
I have a site where I am trying to use a scroll event to
1) fade out a textual version of the company name,
2) replace the content of that element with an image file of the company logo and
3) fade the logo back in. Issues I'm facing:
I'm able to get the fade out to work, but cannot get the replace (.html) function and fadeIn method to work at all
I notice that the fade out does not take place immediately upon the user scrolling beyond 250px from the top; it lags quite a bit, especially with faster page scrolling.
I've tried both the .animate and .fadeIn/.fadeOut versions for the fading, but still had no luck with the callback function properly replacing the element contents and fading it back into view.
My code is below:
jQuery(window).scroll(function() {
var scrollTop = $(this).scrollTop();
var data = '<img src="assets/template/images/afl_logo_sm.png" width="135" height="55" alt="AFL">'
console.log('Scroll ', scrollTop);
if (scrollTop >= 250) {
jQuery('a.navbar-brand').stop().animate({
opacity: 0.0
}, 500, function() {
jQuery('a navbar-brand').html(data).fadeIn('fast');
});
}
});
Thanks for any help you can provide,
Sandman
You are missing the class selector in the fadein/html code, you are using the class like a descendant selector
jQuery(window).scroll(function () {
var scrollTop = $(this).scrollTop();
var data = '<img src="//placehold.it/135X55" width="135" height="55" alt="AFL">'
if (scrollTop >= 250) {
jQuery('a.navbar-brand').stop().animate({
opacity: 0.0
}, 500, function () {
jQuery(this).html(data).animate({
opacity: 1
});
});
}
});
Demo: Fiddle
Also, once the animation is done, I think the further scrolling should not repeat it so
var flag = false;
jQuery(window).scroll(function () {
var scrollTop = $(this).scrollTop();
var data = '<img src="//placehold.it/135X55" width="135" height="55" alt="AFL">'
if (scrollTop >= 250) {
if (!flag) {
flag = true;
jQuery('a.navbar-brand').stop().animate({
opacity: 0.0
}, 500, function () {
jQuery(this).html(data).animate({
opacity: 1
});
});
}
}
});
Demo: Fiddle
As for the lagging, the browser is a single threaded application so when there is a faster scrolling the browser may spend more time on updating the view as per the scroll than in the script executing which handles the fadeIn
i was working on a galery where when the user scrolls and reaches a thumb certain background action occurs.
Now did this coding and i am able to get the result but somehow i am confused as it only works one time and then when i again scroll to that position it does nothing.
I am using alert boxes to reach 5th and 7th thumb and it only shows message once.
I am using something like this
$(document).ready(function () {
// Thumb 1
var thumb4Target = $("#myImg1").offset().top;
var interval = setInterval(function () {
if ($(window).scrollTop() >= thumb4Target) {
alert('1nd Image Position Obtained');
clearInterval(interval);
}
}, 0);
//Thumb 2
var thumb4Target2 = $("#myImg2").offset().top;
var interval2 = setInterval(function () {
if ($(window).scrollTop() >= thumb4Target2) {
alert('2nd Image Position Obtained');
clearInterval(interval2);
}
}, 0);
});
check this Fiddle
LINK
Please tell me where i am doing wrong.Thanks.
Use scroll event instead of interval. LIVE DEMO 1 Or LIVE DEMO 2
$(window).scroll(function()
{
var thumb4Target = $("#myImg1").offset().top;
var thumb4Target2 = $("#myImg2").offset().top;
if ($(window).scrollTop() >= thumb4Target) {
alert('1nd Image Position Obtained');
}
if ($(window).scrollTop() >= thumb4Target2) {
alert('2nd Image Position Obtained');
}
});
When a user loads my page I want to let the background color be white then after 5 seconds fade away the color and fade in the picture. And after 5 seconds fade in another picture again so you can create sort of a slide show in the background behind my content. This is what I have now but it doesn't work, any help?
$(document).ready(function() {
setTimout(function() {
$('body').css("background-image","url('../img/background/1.jpg')").fadeIn(1000)
},5000);
function repeat() {
$('body')
.delay(5000).css("background-image","url('../img/background/2.jpg')").fadeIn(1000)
.delay(5000).css("background-image","url('../img/background/3.jpg')").fadeIn(1000)
.delay(5000).css("background-image","url('../img/background/1.jpg')").fadeIn(1000);
}
window.setInterval(repeat, 18000);
});
The following is a syntax error:
setTimout(function() {
$('body').css("background-image","url('../img/background/1.jpg')").fadeIn(1000)
},5000);
Should be
setTimeout(function() {
$('body').css("background-image","url('../img/background/1.jpg')").fadeIn(1000)},5000);
It is missing the e in setTimeout
I also do not believe you will be able to fadeIn the background image unless you are setting it on a DIV unless you fadeOut the body. I have re-written your background changer into fewer lines of code that repeat with a list of images provided. This should keep looping for the images you have in the array.
$(document).ready(function () {
var images = ["../img/background/1.jpg", "../img/background/2.jpg"];
var index = -1;
window.setInterval(function () {
index = (index + 1 < images.length) ? index + 1 : 0;
$('body').css("background-image", "url('" + images[index] + "')");
}, 5000);
});
This is a follow-up post to a previous question: jQuery - scroll down every x seconds, then scroll to the top
I have refined the scrip a little further, but am having a little trouble with the last step.
I have a div that automatically 50px at a time until it reaches the bottom, at which point it scrolls to the top and starts again. I have this working perfectly thanks to the above question and with a little add work.
I need to make all scrolling stop when the div is hovered. I have done part of this already (there is no incremental scrolling down on hover) but I cannot get the full picture. The div will still scroll to the top even when hovered.
Here is my jQuery and a fiddle to go along with it: http://jsfiddle.net/wR5FY/1/
var scrollingUp = 0;
var dontScroll = 0;
window.setInterval(scrollit, 3000);
function scrollit() {
if(scrollingUp == 0 && dontScroll == 0) {
$('#scroller').animate({ scrollTop: $("#scroller").scrollTop() + 50 }, 'slow');
}
}
$('#scroller').bind('scroll', function () {
if (dontScroll == 0) {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
scrollingUp = 1;
$('#scroller').delay(2000).animate({ scrollTop: 0 }, 1000, function() {
scrollingUp = 0;
});
}
}
});
$('#scroller').bind('mouseenter', function() {
dontScroll = 1;
});
$('#scroller').bind('mouseleave', function() {
dontScroll = 0;
});
In the fiddle, try hovering the scroller div when the yellow square is visible. You will see that it scrolls to the top.
A couple of notes:
You will notice I have used mouseenter and mouseleave rather than hover and mouseout. This was the best way I could find to ensure all child elements within the div didn't have an adverse affect.
A potential problem area is the fact that I have binded to the scroll event for my function that scrolls to the top. I think this might cause some additional problems when a user is manually scrolling through the items, with my jQuery trying to scroll against the user.
I did a little experimenting with killing setInterval, but I didn't find this to be very helpful as the function that triggers isn't the problem area.
My overall goal here is to lock down all automatic scrolling when a user is hovering or manually scrolling through the list. This is 90% there. If they happen to scroll to the bottom, NOTHING should happen until they move the mouse elsewhere - this is the problem.
Keep it easier ;)
The problem was that you first evaluate wheter dontScroll is zero, then start the timer.
When the timer has ended, it doesnt evaluate anymore, whether dontScroll STILL is zero.
Just pulled that into your scrollIt function:
var scrollingUp = 0;
var dontScroll = 0;
window.setInterval(scrollit, 2000);
function scrollit() {
if(dontScroll == 0){
if ($('#scroller').scrollTop() + $('#scroller').innerHeight() >= $('#scroller')[0].scrollHeight) {
scrollingUp = 1;
$('#scroller').animate({ scrollTop: 0 }, 1000, function() {
scrollingUp = 0;
});
} else if(scrollingUp == 0) {
$('#scroller').animate({ scrollTop: $("#scroller").scrollTop() + 50 }, 'slow');
}
}
}
$('#scroller').bind('mouseenter', function() {
dontScroll = 1;
});
$('#scroller').bind('mouseleave', function() {
dontScroll = 0;
});
You can view my custom slider here: http://www.awaismuzaffar.com/examples/index.html
And below is the JQuery code for it:
$(document).ready(function() {
// Slider Function
var slideWidth = $('div.slide').width();
// Set the left position of each div element
$('div.slide').each(function(index){
$(this).css('left', index * slideWidth ); // Multiply each div element by the index(0, 1 etc) so each div is placed inline
});
// Next step is to animate the div elements
var clickCount = 1;
var slideCount = $('div.slide').length;
// Set the previous button to hide when loading with the first slide
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc');
}
$('a#next-button').click(function() {
if(clickCount < slideCount) {
$('div.slide').animate({"left":"-=" + slideWidth}, 'slow');
$('a#previous-button').css('background-color', '#ffffff');
clickCount++;
}
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
$('a#previous-button').click(function() {
if(clickCount > 1){
$('div.slide').animate({"left":"+=" + slideWidth}, 'slow');
$('a#next-button').css('background-color', '#ffffff');
clickCount--;
}
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
});
I am trying to modify this slider to allow continous scrolling.
I am not sure exactly how to achieve this, I am assuming I need to use append, but I am not sure how to make use of it.
Thanks.
You're doing things a little manually, I'm thinking someone else might've solved the problem. But in any case, in your click next button, you'd need to load in additional content when you hit the end. So if I were you, I'd do something like this:
$('a#next-button').click(function() {
...
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc');
$.get(moreContentUrl, objectRepresentingCurrentScrollPosition, loadContent);
spinner.show(); // show some kind of spinner here (you can also hook up a default spinner on all ajax events with a global ajax handler
}
});
function loadContent(response) {
// append your content (your controller should return just the <div class="slide" /> elements, and give them a class="slide newSlide" so you can distinguish them below
// you can also do client side templating here. would be more efficient, then just return the items as objects instead of html
$('#slide-container').append(response.itemsHtml);
// slide all new divs right
$('div.newSlide').animate({"left":"+=" + slideWidth}, 'fast');
$('div.newSlide').removeClass('newSlide');
// update variables and un-grey the next button
$('a#previous-button').css('background-color', '#ffffff');
slideCount += response.itemCount;
// hide the spinner shown when starting the load
spinner.hide();
}
Give it a shot, hope it works. Now, to clean up that code a little bit, I'd suggest using css classes instead of inline background colors, etc.
Here's a solution (somewhat like Shaz's), just less code :):
$(document).ready(function(){
$('#previous-button').click(function(){slidePanel(-1)});
$('#next-button').click(function(){slidePanel(1)});
var n = 0;
var animating = false;
$('#slide-'+n).css('display', 'block');
function slidePanel(delta)
{
if(!animating)
{
animating = true;
var d = (delta > 0 ? $('#slide-'+n).width()*-1 : $('#slide-'+n).width());
$('#slide-'+n).animate({
left: "+="+d
}, 'slow', function() { $(this).css('display', 'none'); animating = false; });
n = (n + delta) % $('div.slide').length;
n = n < 0 ? $('div.slide').length + n : n;
$('#slide-'+n).css('left', $('#slide-container').offset().left +(d*-1));
$('#slide-'+n).css('display', 'block');
$('#slide-'+n).animate({
left: 0
}, 'slow');
}
}
});
Check out the sample here.
(I know there's a way to figure out the "current slide" with a one liner equation, but I think I'm brain dead atm :P)
(Edited to account for repeatedly clicking)
Try something like this: http://fiddle.jshell.net/Shaz/dsBkf/