The second slideshow waiting for the first slideshow to finish - javascript

The second slideshow waits for the first slideshow to finish IN THIS FIDDLE
Imagine if I have to have four slideshows in one page: slideshow one, slideshow two, slideshow three, and slideshow four.
The wrapper of all of the slideshows have the same class and has no ID, and the slideshows are run with a same script:
Actually, only one slideshow (the first) which is going to be shown in the page, while the rest are still hidden. If only the second link which refers to the second slideshow is clicked then the second slideshow will be shown in the page while at the same time the first slideshow will be hidden automatically.
If the second slideshow is shown in a wrapper DIV by clicking its link soon after you load the page, the second slideshow is blank with no content. The problem of its blank is because the second slideshow is waiting for the first slideshow to finish in sliding all the contents inside it.
Here is my html code:
<!--SLIDESHOW ONE-->
<div class="bigandsmall">
<div class="bigPicture">
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg"></div>
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg"></div>
</div>
<div class="smallPicture">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg">
</div>
</div>
<!--END OF SLIDESHOW ONE-->
<!--SLIDESHOW TWO-->
<div class="bigandsmall">
<div class="bigPicture">
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg"></div>
<div class="easyzoom easyzoom--overlay">
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg"></div>
</div>
<div class="smallPicture">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_1.jpg">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_luna_2.jpg">
</div>
</div>
<!--END OF SLIDESHOW TWO-->
Here is the script that I use to run the all slideshows:
var $el = $('.bigandsmall'),
// SETUP ////////
F = 600 , // Fade Time
P = 5000 , // Pause Time
C = 0 , // Counter / Start Slide# (0 based)
///////////////////
$sl = $('.bigPicture > div'),
$th = $('.smallPicture > img'),
N = $sl.length,
T = 10000;
$sl.hide().eq(C).show();
$th.eq(C).addClass('on');
// ANIMATION
function anim() {
$sl.eq(C%N).stop(1).fadeTo(F,1).siblings().fadeTo(F,0);
$th.removeClass('on').eq(C%N).addClass('on');
}
// AUTO ANIMATE
function autoAnim() {
T = setTimeout(function() {
C++;
anim(); // Animate
autoAnim(); // Prepare another iteration
}, P+F);
}
autoAnim(); // Start loop
// HOVER PAUSE
$el.hover(function(e) {
return e.type==='mouseenter'? clearTimeout( T ) : autoAnim();
});
// HOVER THUMBNAILS
$th.on('mouseenter', function() {
C = $th.index( this );
anim();
});

If you rewrite it as a plugin instead, you can manage each slideshow independently:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/CH5YN/2/
Please note this is a just an example, not how you would normally write plugins cleanly. I did not attempt to cleanup the structure or code, just made it use separate instances and elements local to the container it is attached to. I styled them with a horrible yellow border so you can see the objects:
$.fn.slideThis = function () {
this.each(function () {
// Reference to current DOM object
var THIS = this;
// Current DOM object as jQuery object
var $this = $(this);
THIS.$sl = $this.find('.bigPicture > div'),
THIS.$th = $this.find('.smallPicture > img'),
THIS.N = THIS.$sl.length,
THIS.T = 10000;
THIS.C = 6;
THIS.$sl.hide().eq(THIS.C).show();
THIS.$th.eq(THIS.C).addClass('on');
THIS.P = 1000;
THIS.F = 1000;
$this.css({
border: "5px solid yellow"
});
// ANIMATION
THIS.anim = function () {
THIS.$sl.eq(THIS.C % THIS.N).stop(1).fadeTo(THIS.F, 1).siblings().fadeTo(THIS.F, 0);
THIS.$th.removeClass('on').eq(THIS.C % THIS.N).addClass('on');
}
// AUTO ANIMATE
THIS.autoAnim = function () {
THIS.T = setTimeout(function () {
THIS.C++;
THIS.anim(); // Animate
THIS.autoAnim(); // Prepare another iteration
}, THIS.P + THIS.F);
}
THIS.autoAnim(); // Start loop
// HOVER PAUSE
THIS.$sl.hover(function (e) {
return e.type === 'mouseenter' ? clearTimeout(THIS.T) : THIS.autoAnim();
});
// HOVER THUMBNAILS
THIS.$th.on('mouseenter', function () {
THIS.C = THIS.$th.index(this);
THIS.anim();
});
});
};
// Attach one of these to every matching element
$(".bigandsmall").slideThis();
I leave it to you read up on creating jQuery plugins and cleanup the code :)

I did upto some point, I don't think you wrote the js code, but that's not my point. You are forgetting some functions, or are referring variables incorrectly.
This is what I got working:
http://jsfiddle.net/CWjS7/4/
JS
$sl = $('.bigPicture > div'),
$th = $('.smallPicture > img'),
N = $sl.length,
T = 10000;
C = 6;
$sl.hide().eq(C).show();
$th.eq(C).addClass('on');
P = 1000;
F = 1000;
// ANIMATION
function anim() {
$sl.eq(C%N).stop(1).fadeTo(F,1).siblings().fadeTo(F,0);
$th.removeClass('on').eq(C%N).addClass('on');
}
// AUTO ANIMATE
function autoAnim() {
T = setTimeout(function() {
C++;
anim(); // Animate
autoAnim(); // Prepare another iteration
}, P+F);
}
autoAnim(); // Start loop
// HOVER PAUSE
$sl.hover(function(e) {
return e.type==='mouseenter'? clearTimeout( T ) : autoAnim();
});
// HOVER THUMBNAILS
$th.on('mouseenter', function() {
C = $th.index( this );
anim();
});

Related

How to cycle through each div's display property to "display:none" to "display:block" in an endless loop with setTimeout?

I have a div that shows gif image and I have 4 gif image to cycle through with different duration in an endless loop(gif should cycle through 1 2 3 4 then 1 2 3 4 endlessly)
My gifplayer div: Other than the first div the other 4 divs initial display property is set to none
<div id="gifplayer"><img id="gif1" class="gifimg" src="gif1.gif">
<div id="gifplayer"><img id="gif2" class="gifimg" src="gif2.gif" style="display:none;>
<div id="gifplayer"><img id="gif3" class="gifimg" src="gif3.gif" style="display:none;>
<div id="gifplayer"><img id="gif4" class="gifimg" src="gif4.gif" style="display:none;>
Each gif has a different duration and I would like to play one another in an endless loop. Below is my jQuery and it works but only for the first time and also only the first gif is playing as expected 2nd, 3rd and 4th gifs are abruptly ending:
jQuery:
$(document).ready(function() {
setTimeout(function(){
$("#gif1").css("display","none")
$("#gif2").css("display","block")
$("#gif3").css("display","none")
$("#gif4").css("display","none")
}, 16000);
setTimeout(function(){
$("#gif1").css("display","none")
$("#gif2").css("display","none")
$("#gif3").css("display","block")
$("#gif4").css("display","none")
}, 18000);
setTimeout(function(){
$("#gif1").css("display","none")
$("#gif2").css("display","none")
$("#gif3").css("display","none")
$("#gif4").css("display","block")
}, 67800);
setTimeout(function(){
$("#gif1").css("display","block")
$("#gif2").css("display","none")
$("#gif3").css("display","none")
$("#gif4").css("display","none")
}, 16000);
})
Use the Modulo operator % to reset a i counter back to 0
Use classList 's .remove() and .add() methods
Use data-* attribute to store a desired ms duration time and later read it in JS using Element.dataset
const gifify = (EL) => {
const IMGS = EL.querySelectorAll("img");
const tot = IMGS.length;
let i = 0;
(cycle = () => {
const IMG = IMGS[i];
const dur = IMG.dataset.duration || 100; // ms (Fallback to 100ms)
IMGS.forEach(EL => EL.classList.remove("show")); // Hide all
IMG.classList.add("show"); // Show one
i += 1; // Increment index
i %= tot; // Loop index
setTimeout(cycle, dur );
})();
};
document.querySelectorAll(".gifify").forEach(gifify);
.gifify img { display: none; }
.gifify img.show { display: block; }
Infinite cycle trough images with different duration:
<div class="gifify">
<img data-duration="300" src="//www.placehold.it/100x100/0bf?text=1">
<img data-duration="500" src="//www.placehold.it/100x100/fb0?text=2">
<img data-duration="400" src="//www.placehold.it/100x100/f0b?text=3">
<img data-duration="100" src="//www.placehold.it/100x100/b0f?text=4">
</div>

Javascript slider shows white screens

Hi i'm building a javascript slider for my portfolio with Javascript. The slides work properly but when i add a fading transition i keep getting a white flash between the 2 slides. Anyone knows how to create a smooth fade between them?
I added a JSfiddle down below.
Here's my javascript:
$(function () {
var theInterval; // Slide speed
var images = new Array();
var counter = 1;
var defaultSettings = {
"sliderContainer": "#slider" // SliderContainer
, "pauseWithMouse": true // Turn on/off pause with mouse
, "sliderSpeed": 3000 // Slide speed
, "transitionSpeed": 200 // transition speed
};
// intialize slider
// if myImages exists then
images = myImages;
if (images.length > 0) {
$(defaultSettings.sliderContainer).append('<img id="sliderImg" width="900" src="' + images[0] + '" />');
startSlide(images);
}
function cycleImages(images) {
if (counter >= images.length) {
counter = 0;
}
console.log(counter);
document.getElementById("sliderImg").src = images[counter];
counter++;
var images = $('#sliderImg')
var now = images.filter(':visible')
var next = now.next().length ? now.next() : images.first()
var speed = defaultSettings.transitionSpeed; //Transition speed
now.fadeOut(speed);
next.fadeIn(speed);
}
function startSlide() {
console.log('start');
theInterval = setInterval(function () {
cycleImages(images);
}, defaultSettings.sliderSpeed);
// Set interval time
};
var stopSlide = function () { // Stop slides on hover
console.log('stop');
if (defaultSettings.pauseWithMouse) {
clearInterval(theInterval);
}
};
$('#sliderImg').on('mouseover', function () { // Stop slides on mouseover
stopSlide();
});
$('#sliderImg').on('mouseout', function () { // Continue with slides on mouseout
startSlide();
});
});
The JS Fiddle Link
This is happening because there is no background while the fade in occurs. The easiest way to fix this is to add a z-index property to the image or the slide.
For example give the first image an z-index of 1 and the second one a z-index of 2
Here is the code that you should implement:
var subs = $(this).find('#sliderImg');
var index = subs.eq(0).css('z-index');
subs.gt(0).each(function() {
$(this).css('z-index', ++index);
});
The idea is to access each element of the array via the tag you provided #sliderImg and using the jQuery method each to increase the z-index css property with 1.
Here is a working fiddle: Working Fiddle

Adding and removing a class to a list of divs for creating a content slider

I'm creating a very basic content slider in CSS3 however this question is regarding the jQuery part of it. My content structure is as follows:
<div class="slider>
<div class="container>
<div class="slides">
<div class="slide active"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
</div>
</div>
</div>
These slides have an opacity of 0 however when .active is added to slide, I change the opacity to 1. What I'm trying to accomplish is moving the active class to each div every x seconds.
if($('.slider').length) {
// Element exists
var height = $('.slide .col-md-8').outerHeight(),
slide = $('.slide'),
wait = 5000;
$('.slides').css('height', height);
slide.each(function() {
});
}
This is all I can come up with. I'm sorry if it's not enough, I'll also apologize if this is very easy to do and I'm just wasting your time. I've got to learn somewhere. I hope I don't get voted down, I'm trying to build up my rep with this awesome community of developers.
Threw together an example of a script that applies a class to elements in order over time, and loops. This can be implemented in what you currently have.
var i = 1; // Counter
$slides = $('.slides > .slide'); // Array of slides
$num = $slides.length; // Number of present slides
wait = 5000; // Wait time
setInterval(function() {
// If reached the last slide - reset to the first slide
if (i++ == $num) {
$('.slide').removeClass('active');
$($slides[0]).addClass('active');
i = 1;
}
else {
// Add the active class to the next slide
$('.active').removeClass("active").next().addClass('active');
}
}, wait); // Time per slide in ms
Fiddle
If I understand you correctly you just want to move the next slide up in the stack so to speak. This is how I would go about doing it. Working example on jsfiddle
if($('.slider').length) {
// Element exists
var height = $('.slide .col-md-8').outerHeight(),
slides = $('.slides'),
wait = 2000;
var slideInterval = setInterval(startSlideInterval, wait);
$(slides).find('.slide').on({
mouseover: function(){
clearInterval(slideInterval);
},
mouseout: function(){
slideInterval = setInterval(startSlideInterval, wait);
}
});
function startSlideInterval() {
var active = $(slides).find('div.active');
nextSlide = $(active).next('.slide');
lastSlide = $(slides).find('div.slide:last');
$(active).removeClass('active');
$(lastSlide).after($(active));
$(nextSlide).addClass('active');
}
}
I wasn't able to comment about pausing the timer, but I modified the code I had posted originally and also update the jsfiddle.

Rotate images as well as the description and link

I would like to make some changes on a code and add some more options:
1- Rotate the images with the description of each one as well as the link,
2- Add the effect fadeOut while the image is disappearing.
Here is my little code:
var images = new Array ('BMW.png', 'Maybach.png', 'Mercedes-Benz.png', 'Mini.png', 'Jaguar.png', 'Toyota.png');
var descs = new Array ('BMW', 'Maybach', 'Mercedes-Benz', 'Mini', 'Jaguar', 'Toyota');
var links = new Array ('www.url1.com', 'www.url2.com', 'www.url3.com', 'www.url4.com', 'www.url5.com', 'www.url6.com');
var index = 1;
function rotateImage()
{
$('#myImage').fadeOut('fast', function()
{
$(this).attr('src', images[index]);
$(this).fadeIn(2000, function()
{
if (index == images.length-1)
{
index = 0;
}
else
{
index++;
}
});
});
}
$(document).ready(function()
{
setInterval (rotateImage, 7000);
});
</script>
</head>
<body>
<div id="test">
<a href="www.url1.com">
<img class="rotate" id="myImage" src="BMW.png" width="800" height="300" alt="image test" />
</a>
<div class="rotate" id="myDesc" style="margin-top: -30px; margin-left: 30px;"></div>
</div>
uhm... something like this?
(Array is ZERO base so... initial index is 0 [with 1 you start with "Maybach.png" not "BMW.png" ]).
"Add the effect fadeOut while the image is disappearing" - if the image is disappearing is already doing a fade out... you should explain this point...
However...
var images = ['http://placehold.it/150x100', 'http://placehold.it/120x150', 'http://placehold.it/90x120', 'http://placehold.it/100x100', 'http://placehold.it/100x150', 'http://placehold.it/150x100'],
descs = ['BMW', 'Maybach', 'Mercedes-Benz', 'Mini', 'Jaguar', 'Toyota'],
links = ['www.url1.com', 'www.url2.com', 'www.url3.com', 'www.url4.com', 'www.url5.com', 'www.url6.com'],
index = 0; //start from first image
function rotateImage()
{
$('#test').fadeOut('fast', function() //fadeout all block (if display none collapse your graphics use animate and "opacity") to hide without change display
{
$(this).find("a").attr('href', links[index]); //add href to url
$(this).find("img").attr('src', images[index]); //add src to image
$(this).find("#myDesc").text(descs[index]); //add description in desc div
$(this).delay(500).fadeIn(2000, function() //delay (a little bit) to wait image load (for bigger image you need longer delay)
{
if (index == images.length-1)
{
index = 0;
}
else
{
index++;
}
});
});
}
$(document).ready(function()
{
rotateImage(); //fire first time and then use Setinterval for loop
setInterval (rotateImage, 7000);
});
Example HERE jsfiddler
I hope this can help.
Simple image preload:
<img src="path/placeholder.gif" data-src="path/realImage.jpg" style="display:none" />
so the image that be loaded is a gif of trasparent singol pixel. when you need to preload you only need to place data-src in src and than show image... (do this when the prev image of your animation was displayed for prevent the load gap when this image will display)

JQuery Slider animation only happens for one cycle

Ive been attempting to create my own Javascript slider plugin, (I realise there are many out there, but i wanted to treat it as a learning exercise),
an example can be seen here: http://jsfiddle.net/6GTGU/
the problem I'm having is that the animation goes round once, and then stops, Ive tried to examine this to see what i have done wrong but i can't find any reason for it, if anyone can help me i would be very grateful.
HTML
<div id="cjwSlider">
<div style="background-color: #6495ed"></div>
<div style="background-color: #62ed43"></div>
<div style="background-color: #ed5943"></div>
</div>
JAVASCRIPT
var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');
$(document).ready(function () {
sliderItems.each(function( index ) {
$(this).css('z-index', index);
});
window.setInterval(function(){
var maxValue = findMaxZIndex();
var currentItem = sliderItems.filter(function() {
return $(this).css('z-index') == maxValue;
});
currentItem.addClass("hiddenDiv").delay(1000).queue(function() {
sliderItems.each(function( index ) {
$(this).css('z-index', parseInt($(this).css('z-index')) + 1);
});
currentItem.css('z-index', 0);
currentItem.removeAttr('class');
});
}, 4000);
});
function findMaxZIndex() {
var maxValue = undefined;
$(sliderItems).each(function() {
var val = $(this).css('z-index');
val = parseInt(val, 10);
if (maxValue === undefined || maxValue < val) {
maxValue = val;
}
});
return maxValue;
}
PLUGIN DEMO IN ACTION
You said you want a plugin so here you go.
It even stops on mouseenter. (I personally hate when I cannot stop a gallery by just hovering it.)
I don't understand the need of z-index at all, so you can calmly remove it all from your HTML and don't bother at all.
<div class="cjwFader" id="el1">
<div style="background: red;"> 1 </div>
<div style="background: green;"> 2 </div>
<div style="background: gold;"> 3 </div>
</div>
CSS:
(the only needed, but you can also make jQ apply the children position)
.cjwFader > div {
position: absolute;
}
And finally the plugin:
(function($){
$.fn.cjwFader = function(opts){
// Default Settings
var S = $.extend({
fade: 400,
wait: 2000,
startAt: 0
//, need more? add more.
},opts);
return $(this).each(function(){
var that = $(this),
child = $('>*',that),
nOfChildren = child.length,
sI;
function animate(){
child.eq( S.startAt = ++S.startAt % nOfChildren )
.fadeTo( S.fade,1 )
.siblings().stop().fadeTo(S.fade,0);
}
function loop(){
sI=setInterval( animate, S.wait+S.fade );
}loop();
child.hover(function(e){
return e.type==='mouseenter'? clearInterval(sI) : loop();
}).eq(S.startAt).show().siblings().hide();
});
};
})(jQuery);
Plugin usage:
$(function(){ // DOM ready
// $('#el1').cjwFader(); // Use default plugin settings
$('#el1').cjwFader({ // Let's apply some custom stuff
startAt : 1,
fade : 1000,
wait: 700
});
});
Here is the working slideshow: http://jsfiddle.net/6GTGU/7/
I've updated the HTML slightly to remove the initialization code from your JS. You may decide to revert that back
HTML
<div id="cjwSlider">
<div style="background-color: #6495ed; z-index: 0;"></div>
<div style="background-color: #62ed43; z-index: 1;"></div>
<div style="background-color: #ed5943; z-index: 2;"></div>
</div>
I had to remove a lot of JS code to nail down the problem. I think the current JS is all you may need and don't need to go back to your original one:
var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');
$(document).ready(function () {
window.setInterval(function () {
var maxValue = $('#cjwSlider').find('div').length - 1;
var currentItem = sliderItems.filter(function () {
return $(this).css('z-index') == maxValue;
});
currentItem.addClass("hiddenDiv").delay(1000).queue(function () {
sliderItems.each(function (index) {
$(this).css('z-index', parseInt($(this).css('z-index')) + 1);
});
currentItem.css('z-index', 0);
currentItem.removeAttr('class');
$(this).dequeue();
});
}, 4000);
});
The crux of the problem was the missing call to dequeue() at the end of the function that was queued up. The function executed fine for the first time but then stayed at the head of the queue and prevented execution of functions queued later on. This is why your animation played for one cycle but not after that.

Categories

Resources