I want to create image gallery with infinite loop using jquery - javascript

I want to create an image gallery, I wrote for a slideshow, but I don't know how to code for the previous and next buttons. These should work like an infinite loop (last image jumps back to the first).
How should I get started? This is what I have so far:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#play").click(function () {
$("#img1").fadeOut(2000);
$("#img2").fadeIn();
$("#img2").fadeOut(4000);
$("#img3").fadeIn();
});
});
</script>
<body>
<div id=outer>
<div id=inner>
<img id="img1" src="img1.jpg"/>
<img id="img2" src="img2.jpg" style="display:none"/>
<img id="img3" src="img3.jpg" style="display:none"/>
</div>
<div id=button>
<button id="bwd"><<</button>
<button id="play"><></button>
<button id="fwd">>></button>
</div>
</div>
</body>

You can use setInterval() .
This link can help you to understand much more
Call function with setInterval in jQuery?
may be this can help you too :
http://jquery.malsup.com/cycle/

you're going to want to use the javascript timing function. Something like:
$('#play').click(function(){
window.setInterval(function(){
if($('#img1').is(:visible)){
$("#img2").show()
$("#img1").hide()
}
if($('#img2').is(:visible)){
$('#img3').show()
$('#img2').hide()
}
if($('#img3').is(:visible)){
$('#img1').show()
$('#img3').hide()
}
}, 1000);
});
You can also condense this logic down, but this gets you the basic idea. Then if you look carefully the functions for next is already in the code and it can be extracted out and reuses. Once you have the next function it's pretty straight forward that the back function will be the exact opposite.
To answer your question below you can change the img's to have the same class and then apply show and hide based on which one is visible and the image immediately after the visible one:
#find the one currently being shown
$(".images:visible")
#find the one after the visible one
$(".images:visible").next()
#keep an id on the last image so that you can do something like
if($('.images:visible') == $('#last_image')){
$('.images').first().show()
}

Hi i have created Carousel without using any third party plugin.If you want please refer.Reference Link
Js Code is.
$(document).ready(function () {
var currentPosition = 0;
var slideWidth = 300;
var slides = $('.slide');
var numberOfSlides = slides.length;
var timer = 3000;
var img1, img2;
var sliderLink = $("#slider a");
var direction = 1;
// Remove scrollbar in JS
$('#slidesContainer').css('overflow', 'hidden');
// Wrap all .slides with #slideInner // Float left to display horizontally, readjust .slides width
slides.wrapAll('<div id="slideInner"></div>').css({
'float': 'left',
'width': slideWidth
});
// Set #slideInner width equal to total width of all slides
$('#slideInner').css('width', slideWidth * numberOfSlides);
// Insert left and right arrow controls in the DOM
$('#slideshow').prepend('<span class="control" id="leftControl">Move left</span>').append('<span class="control" id="rightControl">Move right</span>');
// Hide left arrow control on first load
// manageControls(currentPosition);
// manageSlide();
// Create event listeners for .controls clicks
$('#rightControl').bind('click', rightControl);
$('#leftControl').bind('click', leftControl);
function leftControl() {
var butonid = 0;
direction = 0;
$("#slideInner").stop();
$("#slideInner").dequeue();
$('#timer').stop();
$('#timer').dequeue();
$('#leftControl').unbind('click');
manageSlide(0, direction);
setTimeout(function () {
$('#leftControl').bind('click', leftControl);
}, timer, null);
}
function rightControl() {
var butonid = 1;
direction = 1;
$("#slideInner").stop();
$("#slideInner").dequeue();
$('#timer').stop();
$('#timer').dequeue();
$('#rightControl').unbind('click');
manageSlide(0, direction);
setTimeout(function () {
$('#rightControl').bind('click', rightControl);
}, timer, null);
}
var slideIndex = 0;
var data = $("#slideInner .slide").toArray();
$("#slideInner").empty();
function manageSlide(auto, idButtonid) {
$("#slideInner").empty();
// console.log(slideIndex);
if (idButtonid == 0) {
$("#slideInner").css({ 'marginLeft': "-300px" });
$(data).each(function (index) {
// if (index == slideIndex - 1) {
// $(this).show();
// } else {
$(this).hide();
// }
});
$(data[slideIndex - 1]).show();
if (slideIndex == numberOfSlides - 1) {
slideIndex = 0;
img1 = data[0];
img2 = data[numberOfSlides - 1];
$("#slideInner").append(img1);
$("#slideInner").append(img2);
$(img2).show();
$(img1).show();
} else {
img1 = data[slideIndex];
img2 = data[slideIndex + 1];
$("#slideInner").append(img2);
$("#slideInner").append(img1);
$(img1).show();
$(img2).show();
slideIndex = slideIndex + 1;
}
$('#slideInner').animate({
'marginLeft': "0px"
}, 'slow', function () {
$('#timer').animate({
opacity: 1
}, timer, function () {
console.log('leftControl');
manageSlide(1, direction);
});
});
}
// right move here
else if (idButtonid == 1) {
$("#slideInner").css({ 'marginLeft': "0px" });
$(data).each(function (index) {
if (index == slideIndex + 1) {
$(this).show();
} else {
$(this).hide();
}
});
if (slideIndex == numberOfSlides - 1) {
slideIndex = 0;
img1 = data[0];
img2 = data[numberOfSlides - 1];
$("#slideInner").append(img2);
$("#slideInner").append(img1);
$(img2).show();
$(img1).show();
} else {
img1 = data[slideIndex];
img2 = data[slideIndex + 1];
$("#slideInner").append(img1);
$("#slideInner").append(img2);
$(img1).show();
$(img2).show();
slideIndex = slideIndex + 1;
}
$('#slideInner').animate({
'marginLeft': slideWidth * (-1)
}, 'slow', function () {
console.log('rightControl');
$('#timer').animate({
opacity: 1
}, timer, function () {
manageSlide(1, direction);
});
});
}
if (auto == 1) {
sliderLink.each(function () {
$(this).removeClass();
if ($(this).text() == (slideIndex + 1)) {
$(this).addClass('active');
}
});
}
auto = 1;
}
$("#slider a").click(function () {
sliderLink.each(function () {
$(this).removeClass();
});
slideIndex = $(this).addClass('active').text() - 1;
$('#timer').stop();
$('#timer').dequeue();
$("#slideInner").stop();
$("#slideInner").dequeue();
manageSlide(0, direction);
});
manageSlide(1, direction);
});
Demo Link
Hope it helps you.

Related

jQuery SetTimeout for Show / Hide div does not work

I am writing a jQuery which is supposed show/hide a series of images after an image is clicked. It basically, hides the current image and shows the next one when onClick event.
The function I have written so far works except one feature: On image 3, I want to set a timer and then switch to image 4, even if the user hasn't click it.
I am using a setTimeout and the timeout triggers except that it does not switch to next image.
This is my function:
(function($) {
$(document).ready(function () {
var count = 0;
$('.squirrel').click(function () {
$(this).hide();
var next = $(this).next();
if (next.length == 0){
next = $(this).parent().find('.squirrel').first();
count = -1;
}
next.show();
if (count == 1) {
setTimeout(
function() {
alert("Should switch to 4 now but it doesn't work");
$(this).hide();
var next = $(this).next();
next.show();
count++;
}, 2000
);
} else {
count++;
}
});
});
})(jQuery);
This is the HTML:
<div id="squirrelContainer">
<img src="1.png" class="squirrel default">
<img src="2.png" class="squirrel">
<img src="3.png" class="squirrel" id = "3">
<img src="4.png" class="squirrel">
</div>
Here's a JSFiddle.
Because you are using the same image not the next one.
(function($) {
$(document).ready(function () {
var count = 0;
$('.squirrel').click(function ()
{
$(this).hide();
var next = $(this).next();
if (next.length == 0)
{
next = $(this).parent().find('.squirrel').first();
count = -1;
}
next.show();
if (count == 1)
{
let that = $(this).next();
setTimeout(
function()
{
console.log("Should switch to 4 now but it doesn't work");
that.hide();
var next = that.next();
next.show();
count++;
}, 2000
);
}
else
{
count++;
}
});
});
})(jQuery);
https://jsfiddle.net/dyt9opLz/

Javascript Slideshow slides overlapping when auto play

I was making this automatic slideshow and it got this issue. I got 4 slides. When autoplay the first time it's overlapping the slide 4 with slide 2 and 3, it's only happen one time after site load. when the slideshow goes for the second time and when I use the dots in the bottom it's working perfectly fine without any issues.
$(document).ready(function(){
$("#slideshow > div:gt(0)").hide();
var slidesl = $('.slideitem').length
var d = "<li class=\"dot active-dot\">•</li>";
for (var i = 1; i < slidesl; i++) {
d = d+"<li class=\"dot\">•</li>";
}
var dots = "<ul class=\"slider-dots\">" + d + "</ul\>";
$("#slideshow").append(dots);
$("#slideshow > div:gt(0)").hide();
var interval = setInterval(slide, 3000);
function intslide(func) {
if (func == 'start') {
interval = setInterval(slide, 3000);
} else {
clearInterval(interval);
}
}
function slide() {
sact('next',0, 1200);
}
function sact(a, ix, it) {
var currentSlide = $('.current');
var nextSlide = currentSlide.next('.slideitem');
var prevSlide = currentSlide.prev('.slideitem');
var reqSlide = $('.slideitem').eq(ix);
var currentDot = $('.active-dot');
var nextDot = currentDot.next();
var prevDot = currentDot.prev();
var reqDot = $('.dot').eq(ix);
if (nextSlide.length == 0) {
nextDot = $('.dot').first();
nextSlide = $('.slideitem').first();
}
if (prevSlide.length == 0) {
prevDot = $('.dot').last();
prevSlide = $('.slideitem').last();
}
if (a == 'next') {
var Slide = nextSlide;
var Dot = nextDot;
}
else if (a == 'prev') {
var Slide = prevSlide;
var Dot = prevDot;
}
else {
var Slide = reqSlide;
var Dot = reqDot;
}
currentSlide.fadeOut(it).removeClass('current');
Slide.fadeIn(it).addClass('current');
currentDot.removeClass('active-dot');
Dot.addClass('active-dot');
}
$('.next').on('click', function(){
intslide('stop');
sact('next', 0, 400);
intslide('start');
});//next
$('.prev').on('click', function(){
intslide('stop');
sact('prev', 0, 400);
intslide('start');
});//prev
$('.dot').on('click', function(){
intslide('stop');
var index = $(this).index();
sact('dot', index, 400);
intslide('start');
});//prev
//slideshow
});
Here is the fiddle - https://jsfiddle.net/Udara_Samapth/c1zevrLj/23/
There are multiple things I noticed which are making your slides overlapping. Looking at your jquery/JS in a first place you are using jquery hide method but inside function sact() you are using fadeIn() and fadeOut() functions which adds opacity classes.
currentSlide.fadeOut(it).removeClass('current');
Slide.fadeIn(it).addClass('current');
That makes top and bottom items to start mixing at some point of opacity.
To handle this there are two solutions in my mind right now.
The easiest one is to add background color to item.
.slideshow .slideitem {
display: none;
background: #FFF;
}
Another effort is to control opacity timings which needs some work on your JS portion. you can do that by adding delay on fadeIn() and fadeOut() functions.
Here is the working link for you.
https://jsfiddle.net/liquidcharcoal/gqyjph1a/13/

Jquery Slider refuses to reset

I am currently a starter in query and trying to make a carousel, it works so far, but continues on after the slides and refuses to reset to the first slide after all slides have been moved, means my margin goes into endless numbers. This is what I have so far:
`
var timeout;
var currentSlide = 1;
var slideWidth = $('.slide').width();
var slideGroup = $('#slider').children('.slide-group');
var slides = $(slideGroup).find('.slide');
var hmm = $(slides).length;
console.log(hmm);
function move(newSlide) {
autoMove();
if($(slideGroup).is(':animated') || currentSlide === newSlide) {
return;
}
if(newSlide > currentSlide) {
$(slideGroup).animate({'margin-left': '-='+slideWidth}, 1000);
}
if(newSlide === 0) {
$(slideGroup).css({'margin-left': 0});
}
};
function autoMove(){
clearTimeout(timeout);
timeout = setTimeout(function(){
if(currentSlide < ($(slides).length -1)){
move(currentSlide +1)
}if(currentSlide > ($(slides).length -1)) {
move(0);
}
}, 4000);
}
move();`

jQuery animate array skip to last

I am trying to animate an array of images using Jquery. When I have one element in the array it works fine but when I have more then one element it just animates the last element of the array.
I set the src of the img tag and move it to the right. The moveRight function move the image to the right and call moveLeft to move it to the left. The moveLeft function moves the image to the left and fade it.
$.each(imageArray, function (i, val) {
$("#b").attr("src", imageArray[i].src);
moveRight();
}
function moveRight(){
$("#b").animate({left: "+=500"}, 2000, moveLeft)
}
function moveLeft(){
$("#b").animate({left: "-=500"}, 2000,fade)
}
Is there a way each image can be moved right and left / or just left or right instead of having the last one moving only. I am trying to figure out what is wrong with my code.
I think the best thing you can do is to use a recursive method. Here is an example (check jsFiddle):
var MyApp = {
Items: {
Elements: $('div'),
Loaded: 0
},
Start: function(){
if( this.Items.Elements.length == this.Items.Loaded ) return; // return.. or play a sound, then return to stop iterations
this.Items.Elements.eq(this.Items.Loaded).animate({ left: '50%' }, {
duration: 1000,
complete: function(){
MyApp.Items.Loaded++;
MyApp.Start();
}
});
}
};
$(function(){
MyApp.Start();
});
It's an example but you can do it easily by this way.
How about this variant: http://jsbin.com/xezetuboye/1/edit?html,js,output ?
var arr = [
'http://e404.pw/pictures/evernote-logo.png',
'http://e404.pw/pictures/font-face.png',
'http://e404.pw/pictures/html-coder.jpg'
];
var count = 0;
function setImg(){
if(arr.length <= count){ return; }
$("#b").attr("src", arr[count]);
moveRight();
count++;
}
function moveRight(){
$("#b").animate({left: "+=500"}, 2000, moveLeft);
}
function moveLeft(){
$("#b").animate({left: "-=500"}, 2000, setImg);
}
setImg();
Try utilizing .queue(). Note, if changing src of same img element , would have to wait until each image loaded.
var imageArray = [
"http://lorempixel.com/100/100/cats",
"http://lorempixel.com/100/100/animals",
"http://lorempixel.com/100/100/technics",
"http://lorempixel.com/100/100/nature"
];
var b = $("#b");
var cycle = function cycle() {
return b.queue("slide", $.map(imageArray, function(val, i) {
return function(next) {
$(this).fadeOut(50).attr("src", val);
this.onload = function() {
return $(this).fadeIn(50, function() {
return moveRight.call(this).then(function() {
return moveLeft.call(this)
}).then(next);
});
}
}
})).dequeue("slide");
};
function moveRight() {
return $(this).animate({
left: "500"
}, 2000).promise()
}
function moveLeft() {
return $(this).animate({
left: 0
}, 2000).promise()
}
var infiniteCycle = function infiniteCycle() {
return cycle().promise("slide").then(infiniteCycle)
};
infiniteCycle();
#b {
position: relative;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<img id="b" />
Here's a very basic example of what you're trying to achieve. From here you can try and animate the transition, switch it so buttons activate a left/right change. I would suggest playing around with this until you comfortable with the basic functionality. From there you can look into plugins/libraries that can help you. http://jsfiddle.net/306Lqov5/1/
HTML
<img id="b" src="http://placehold.it/100/100&text=Image 1" />
JavaScript
var images = [
'http://placehold.it/100/100&text=Image 1',
'http://placehold.it/100/100&text=Image 2',
'http://placehold.it/100/100&text=Image 3',
'http://placehold.it/100/100&text=Image 4'
];
var index = 1, //start at one since we have the first image in by defualt
img = $('#b');
setInterval(function(){
img.attr('src', images[index]);
index++; //index = index + 1;
if (index == images.length){ //if we've reached the length of the array reset to zero
index = 0;
}
},2000); //switch ever 2 seconds

.next() not working as intended

So,
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).prev().addClass('active');
}
works fine, it adds the class "active" to this previous div of the same kind.
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).next().addClass('active');
}
However, adds the class to the next div (as i intend for it to do) for about 0.5 of a second BUT then removes it.
Here's ALL of the jQuery (as per your comments below) - Please do not comment on my horrible code organization
$(window).load(function () {
// Initial variables
var numberSlides = 0;
var currentSlide = 1;
var ready = true;
var pageWidthR = $(document).width() - 352;
var pageWidthL = $(document).width() - 352;
// Update number of slides by number of .slide elements
$('#features-slider .slide').each(function () {
numberSlides++;
});
// Go through each slide and move it to the left of the screen
var i = 0;
$($('#features-slider .slide').get().reverse()).each(function () {
if (i == 0) {
} else {
var newWidth = i * 115;
$(this).css('left', '-' + newWidth + '%');
}
i++;
});
// Animate the first slide in
$('#features-slider .slide:last-child').addClass('active').animate({
left: 0
}, 1500);
// Remove the loading message
$('#loading').fadeOut(1000, function () {
$('#loading').remove();
// Now that we're done - we can show it
$('#features-slider').show();
});
/***** Left and Right buttons *****/
/* Right */
$('#rightbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != 1) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).removeClass('active');
$(this).prev().addClass('active');
}
});
}
});
/* Left */
$('#leftbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != numberSlides) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).next().addClass('active');
$(this).removeClass('active').not($(this).next());
}
});
}
});
});
$(document).ready(function () {
// Hide the slider and show a loading message while we do stuff and the images / DOM loads - Also disable overflow on the body so no horizontal scrollbar is shown
$('body').css('overflow-x', 'hidden');
$('#features-slider').hide();
$('#loading').html('<center> <img id="loader" src="/wp-content/themes/responsive/library/images/ajax-loader.gif" /> Loading</center>');
});
RESOLVED
New left button function :
$('#leftbutton').click(function(){
var numberSlides = 0;
$('#features-slider .slide').each(function(){
numberSlides++;
});
var index = $('.slide.active').index()+1;
if( !$('.slide').is(':animated') && index != numberSlides ){
var done = false;
$('#features-slider .slide').each(function(){
if($(this).hasClass('active')){
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
}
$(this).animate({left: newLeft+'%'}, 1500);
if($(this).hasClass('active') && done == false){
$(this).next().addClass('active');
$(this).removeClass('active');
done = true;
}
});
});
If you're iterating forward through the elements, then it should be clear what's going on - you add the "active" class to the next element, and then the next iteration takes it away.
This is just a guess however as you did not post enough code for me (or anybody else) to be sure.
edit — ok now that you've updated the question, it's clear that the guess was correct. The .each() function will iterate forward through the elements. When an element has the "active" class, and the code removes it and adds it to the next element, then on the next iteration the work is undone.
Since you are referencing this and by the behavior you're describing, you are likely iterating a loop for a list of elements. As a result, you are completing the action you want but the next iteration is removing the previous changes due to your usage of removing a class and then adding the class back.
As it stands now, your code does not illustrate how this occurence can be happening.
Update:
As suspected, you seem to be looping as signified by: each(function(){. While iterating through your objects the class is being pushed forward and is not acting as desired. You are stating add the class to the next element, but remove it from the current element, and this behavior continues through your iteration.
On a side note, update your code to call removeClass() on the current object first, before adding it to the next object:
if ($(this).hasClass('active')) {
$(this).removeClass('active').next().addClass('active');
}

Categories