Add pause function to slider - javascript

I have a very nice slider script here and already figured out to get bullets underneath it, but i just want to know.. is it possible to add some simple lines to it so that the image is pausing/on hold while on mouse over?
Here is my code now:
jQuery
<script type="text/javascript" charset="utf-8">
$(document).ready(function () {
$("#slideshow div:gt(0)").hide();
var index;
index = 0;
var totalslides;
totalslides = 2;
var nextSlide = function () {
$('#slideshow div').eq(index).fadeOut(1000);
$('#nav' + index).toggleClass('navselected');
index++;
if (index > totalslides - 1) { index = 0; }
$('#slideshow div').eq(index).fadeIn(3000);
$('#nav' + index).toggleClass('navselected');
}
var nextSlideTimer = setInterval(nextSlide, 7000);
function nav(selectedSlide) {
clearInterval(nextSlideTimer);
$('#slideshow div').eq(index).fadeOut(1000);
$('#nav' + index).toggleClass('navselected');
index = selectedSlide;
$('#slideshow div').eq(index).fadeIn(1000);
$('#nav' + index).toggleClass('navselected');
nextSlideTimer = setInterval(nextSlide, 4000);
}
$("#nav0").click(function () { nav(0); });
$("#nav1").click(function () { nav(1); });
});
</script>
CSS
<style>
#slideshow { position: relative; width: 960px; height: 300px; padding: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.4);}
#slideshow div { position: absolute; top: 10px ; left: 10px; right: 10px; bottom: 10px; }
#slideshow a {display: block;width:960px;height:300px; }
#slideshow a:hover{background-position: center bottom;}
#slideshownav a.navselected{color:#eb910c;}
#slideshownav {text-align:center; padding-top:8px;padding-bottom:20px;}
#slideshownav a {padding-right:10px;color:#748090;font-size:50px; text-decoration: none; }
#slideshownav a:hover {cursor:pointer;}
</style>
HTML
<div id="slideshow">
<div>IMAGE 1</div>
<div>IMAGE 2</div>
</div>
<div id="slideshownav">
<a id="nav0" class="navselected">°</a>
<a id="nav1">°</a>
</div>

You can use mouseover and mouseout:
$('#slideshow').mouseover(function () {
// Clear the interval.
clearInterval(nextSlideTimer);
}).mouseout(function () {
// Start it nextSlide again.
nextSlideTimer = setInterval(nextSlide, 3000);
});
Or better, you can use mouseenter and mouseleave (see jQuery docs for demo):
$('#slideshow').mouseenter(function () {
// Clear the interval.
clearInterval(nextSlideTimer);
}).mouseleave(function () {
// Start it nextSlide again.
nextSlideTimer = setInterval(nextSlide, 3000);
});
The second approach is better because, it doesn't fire much events when you are moving around the inner elements of the parent slider.

Add this inside of the document ready function, near the bottom:
$('#slideshow').on('mouseover mouseleave', function( event ) {
if ( event.type === 'mouseover') {
// stop slideshow timer
clearInterval(nextSlideTimer);
} else {
// add a shorter time delay
nextSlideTimer = setInterval(nextSlide, 4000);
}
});

Related

Simplify jquery slideup loop

I am currently working on a text slider using jquery.
The code relies on slide toggle and fade working together.
The sample code is here https://codepen.io/fja3omega/pen/GwVYXM
My jQuery is:
jQuery( document ).ready(function() {
jQuery.fn.slideFadeToggle = function(speed, easing, callback) {
return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
};
var counted = 1;
jQuery(".slidem").find( "#rotate1" ).slideFadeToggle();
setInterval(function(){
counted = counted + 1;
torotate = "#rotate" + counted;
if(counted!=5) {
jQuery(".slidem").find( torotate ).slideFadeToggle();
} else {
counted = 1;
jQuery(".slidem .rotater" ).show();
jQuery(".slidem").find( "#rotate1" ).slideFadeToggle();
jQuery(".slidem").find( "#rotate5" ).show();
}
}, 3000);
});
I was wondering if there was a way to shorten or simplify the jQuery.
Yes, you can simplify and improve your code removing all the unnecessary id and class attributes. Also you might make your code more abstract to support any number of "slides" not only 5.
See the snippet below:
jQuery(document).ready(function() {
jQuery.fn.slideFadeToggle = function(speed, easing, callback) {
return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
};
var n = 0, slides = jQuery('.slidem > div');
(function slide() {
n = n * (n < slides.length) || +!slides.show();
slides.eq(n++).slideFadeToggle();
setTimeout(slide, 1000);
})()
});
.irotate {
text-align: center;
margin: 0 auto;
padding: 10% 0;
display: block;
}
.thisis {
display: inline-block;
vertical-align: middle;
height: 20px;
}
.slidem {
overflow: hidden;
text-align: center;
min-width: 90px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="irotate">
<div class="thisis">This is a </div>
<div class="thisis slidem">
<div> </div>
<div>simple</div>
<div>super easy</div>
<div>fun</div>
<div>working</div>
</div>
<div class="thisis"> Text Slider</div>
</div>

setInterval issue in custom jquery image slider with both auto slide and buttons

I am creating a custom image slider with custom slide effect in jQuery which has both next & previous buttons and also slides automatically with 5 seconds timeout. Although it works nicely in a quick look but sometimes( I dont know exactly when, maybe when I press the buttons or if I leave it open for some time and minimize the window) the iterval bugs and the slides change after 1 second or less. Also when i press the button i tell it to 1) clear iterval 2) change slide 3) set interval again which means that after i change a slide with the button the timer is set to 5 seconds from the start but this is not happening all the times.Here is the code.
$(document).ready(function() {
'use strict';
var $carousel = $('.carousel');
var $nextBtn = $('#next');
var $prevBtn = $('#prev');
var animationSpeed = 1000;
var pause = 5000;
var interval;
function nextSlide() {
$('.carousel__list').animate({
left: '-200%'
}, 500, function() {
$('.carousel__list').css('left', '-100%');
$('.carousel__item').last().after($('.carousel__item').first());
});
}
function prevSlide() {
$('.carousel__list').animate({
left: '0%'
}, 400, function() {
$('.carousel__list').css('left', '-100%');
$('.carousel__item').first().before($('.carousel__item').last());
});
}
function startSlider() {
interval = setInterval(function() {
nextSlide();
}, pause);
}
function stopSlider() {
clearInterval(interval);
}
$carousel.on('mouseenter', stopSlider).on('mouseleave', startSlider);
startSlider();
$nextBtn.on('click', function() {
stopSlider();
nextSlide();
startSlider();
});
$prevBtn.on('click', function() {
stopSlider();
prevSlide();
startSlider();
});
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.carousel {
width: 100%;
height: 65vh;
overflow: hidden;
position: relative;
}
.carousel__list {
width: 400%;
height: 100%;
left: -100%;
position: relative;
list-style: none;
}
.carousel__item {
width: calc(100% / 4);
height: 100%;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" style="background-color: red"></li>
<li class="carousel__item" style="background-color: green"></li>
<li class="carousel__item" style="background-color: blue"></li>
<li class="carousel__item" style="background-color: yellow"></li>
</ul>
</section>
<button id="prev">PREVIOUS</button>
<button id="next">NEXT</button>
And here is a codepen: https://codepen.io/anon/pen/erpyJj
You are creating more intervals than you think and you don't actually clear each one because you overwrite the interval variable and then you don't a have a reference to the previous intervals, which may still be active.
What you could do is put every interval you create in an array, then when you need to stop all intervals, iterate through that array, clear each interval and empty the array.
// ...
var intervals = [];
// ...
function stopSlider() {
console.log("stopSlider() intervals (Before clear): ", intervals);
intervals.forEach(function(interval) {
clearInterval(interval); // stop one interval
});
intervals = []; // clear the array
console.log("stopSlider() intervals (After clear): ", intervals);
}
Here is your demo with many console logs. You can see that it doesn't matter how much you click on any button, the slider only automatically slides every 5 s.
$(document).ready(function() {
"use strict";
//cache dom elements
var $carousel = $(".carousel");
var $nextBtn = $("#next");
var $prevBtn = $("#prev");
var animationSpeed = 1000;
var pause = 5000;
var intervals = [];
function nextSlide() {
console.log("nextSlide() intervals: ", intervals);
$(".carousel__list").animate({
left: "-200%"
}, 500, function() {
$(".carousel__list").css("left", "-100%");
$(".carousel__item")
.last()
.after($(".carousel__item").first());
});
}
function prevSlide() {
console.log("prevSlide() intervals: ", intervals);
$(".carousel__list").animate({
left: "0%"
}, 400, function() {
$(".carousel__list").css("left", "-100%");
$(".carousel__item")
.first()
.before($(".carousel__item").last());
});
}
function startSlider() {
console.log("startSlider() interval (BEFORE): ", intervals);
var interval = setInterval(function() {
nextSlide();
}, pause);
intervals.push(interval);
console.log("startSlider() interval (AFTER): ", intervals);
}
function stopSlider() {
console.log("stopSlider() intervals (Before clear): ", intervals);
intervals.forEach(function(interval) {
clearInterval(interval); // stop one interval
});
intervals = []; // clear the array
console.log("stopSlider() intervals (After clear): ", intervals);
}
$carousel.on("mouseenter", stopSlider).on("mouseleave", startSlider);
startSlider();
$nextBtn.on("click", function() {
stopSlider();
nextSlide();
startSlider();
});
$prevBtn.on("click", function() {
stopSlider();
prevSlide();
startSlider();
});
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.carousel {
width: 100%;
height: 20vh;
overflow: hidden;
position: relative;
}
.carousel__list {
width: 400%;
height: 100%;
left: -100%;
position: relative;
list-style: none;
}
.carousel__item {
width: calc(100% / 4);
height: 100%;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" style="background-color: red"></li>
<li class="carousel__item" style="background-color: green"></li>
<li class="carousel__item" style="background-color: blue"></li>
<li class="carousel__item" style="background-color: yellow"></li>
</ul>
</section>
<button id="prev">PREVIOUS</button>
<button id="next">NEXT</button>

Creating a dynamic width items for carousel slider

I'm currently in the middle making my carousel responsive. So far I've managed to make it responsive only if the user resizes and refreshes browser only then it will resize programmatically. How can I make it resize without having to refresh the browser.
Update:
I tried working with the answers below. Currently it stays on a fixed value even if I resize browser. Inside my css there is no fixed value placed
$(document).ready(function() {
var sliderWidth = 0;
var sliderContainer = $('.slider-container');
var slider = $('.slider-container .slider');
var sliderItems = $('.slider li');
var sliderContainerWidth = sliderContainer.width();
sliderItems.width(sliderContainerWidth / 2);
$('.slider-container ul.slider').children().each(function() {
sliderWidth += $(this).outerWidth();
slider.width(sliderWidth + 1000);
});
$('.btns .prev').on('click', function() {
prevSlide();
})
function prevSlide() {
var sliderItemsWidth = sliderItems.width();
var leftIndent = parseInt($(sliderItems).css('left')) - sliderItemsWidth;
function animate() {
$('.slider-container .slider:not(:animated)').animate({
'left': leftIndent
}, 100)
}
animate();
}
})
.wrapper {
max-width: 1280px;
margin: 0 auto;
background-color: #ccc;
}
.wrapper .slider-container {
float: left;
position: relative;
overflow: hidden;
width: 100%;
background-color: beige;
}
.wrapper .slider-container .slider {
display: flex;
flex-wrap: wrap;
position: relative;
}
.wrapper .slider-container .slider li {
height: 300px;
background-color: #ccc;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="slider-container">
<ul class="slider">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<ul class="btns">
<li class="prev">prev</li>
<li class="next">next</li>
</ul>
</div>
</div>
As per my comments, you can put the resizing bits into a function and call that on window resize:
$(document).ready(function() {
var sliderContainer = $('.slider-container');
var slider = $('.slider-container .slider');
var sliderItems = $('.slider li');
function resize() {
var sliderWidth = 0;
var sliderContainerWidth = sliderContainer.width();
sliderItems.width(sliderContainerWidth / 2);
$('.slider-container ul.slider').children().each(function() {
sliderWidth += $(this).outerWidth();
slider.width(sliderWidth + 1000);
});
}
$('.btns .prev').on('click', function() {
prevSlide();
})
function prevSlide() {
var sliderItemsWidth = sliderItems.width();
var leftIndent = parseInt($(sliderItems).css('left')) - sliderItemsWidth;
function animate() {
$('.slider-container .slider:not(:animated)').animate({
'left': leftIndent
}, 100)
}
animate();
}
resize(); // call onload
$(window).on('resize', function () {
resize(); // call when browser is resized
});
})

Fading multiple divs with JS

I have two or in future may be more divs with background images in css. I would like to fade them in and out in a loop.
I am trying to do something like this but it doesn`t work.
$(window).load(function(){
var divs = $('.fade');
function fade() {
var current = $('.current');
var currentIndex = divs.index(current),
nextIndex = currentIndex + 1;
if (nextIndex >= divs.length) {
nextIndex = 0;
}
var next = divs.eq(nextIndex);
next.stop().fadeIn(2000, function() {
$(this).addClass('current');
});
current.stop().fadeOut(2000, function() {
$(this).removeClass('current');
setTimeout(fade, 2500);
});
}
fade();
#one {
background-image: url("Test_bg.jpg");
margin-top: -150px;
min-height: 100%;
background-attachment: fixed;
}
#two {
background-image: url("Test_bg1.jpg");
margin-top: -150px;
min-height: 100%;
display: block;
background-attachment: fixed;
}
<div id="one" class="fade current">
</div>
<div id="two" class="fade">
</div>
You are mising }) at the end with causes syntax error
$(window).load(function(){
var divs = $('.fade');
function fade() {
var current = $('.current');
var currentIndex = divs.index(current),
nextIndex = currentIndex + 1;
if (nextIndex >= divs.length) {
nextIndex = 0;
}
var next = divs.eq(nextIndex);
next.stop().fadeIn(2000, function() {
$(this).addClass('current');
});
current.stop().fadeOut(2000, function() {
$(this).removeClass('current');
setTimeout(fade, 2500);
});
}
fade();
})
#one {
color: red
}
#two {
color: blue
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="one" class="fade current">a
</div>
<div id="two" class="fade">b
</div>

How to make sure items are added to the end of a moving list?

When the user clicks "Music", "Movie", or "Computer", an item is supposed to be added to the end of that moving list. Instead, the item gets added at the beginning... and if you click the next or previous button and then try adding an item, the item will get added at a seemingly random place.
How can this be fixed...?
http://jsfiddle.net/neowot/dawvjcta/1/
HTML
<div id="choices">
<ul id="MusicDiv"><li>Music</li></ul>
<ul id="MovieDiv"><li>Movie</li></ul>
<ul id="ComputerDiv"><li>Computer</li></ul>
</div>
<div id="container">
Previous
Next
<div class="carousel">
<ul>
<li><a>x</a>1</li>
<li><a>x</a>2</li>
<li><a>x</a>3</li>
<li><a>x</a>4</li>
<li><a>x</a>5</li>
<li><a>x</a>6</li>
<li><a>x</a>7</li>
<li><a>x</a>8</li>
<li><a>x</a>9</li>
<li><a>x</a>10</li>
<li><a>x</a>11</li>
<li><a>x</a>12</li>
</ul>
</div>
</div>
CSS
#MusicDiv {
background-color:lightblue;
width:100px;
text-align:center;
}
#MovieDiv {
background-color:lightgreen;
width:100px;
text-align:center;
}
#ComputerDiv {
background-color:orange;
width:100px;
text-align:center;
}
#choices li:hover {
cursor:pointer;
}
#container {
width:auto;
height:100px;
background-color:grey;
}
.carousel {
padding-top: 20px;
width: 357px;
overflow: hidden;
height: 50px;
position: relative;
}
.carousel ul {
position: relative;
list-style: none;
list-style-type: none;
margin: 0;
height: 50px;
padding: 0;
}
.carousel ul li {
position: absolute;
height: 25px;
width: 50px;
float: left;
margin-right: 1px;
background: #f2f2f2;
text-align: center;
padding-top: 25px;
}
.carousel a {
color:red;
position:absolute;
top:0;
right:5px;
cursor:pointer;
}
JS
$(document).ready(function() {
$(document).on('click', '#MusicDiv li', function(event) {
alert('TestMusic');
$('<li>Music</li>').appendTo('.carousel ul');
$(".carousel ul").find('li').last().focus();
});
$(document).on('click', '#MovieDiv li', function(event) {
alert('TestMovie');
$('<li>Movie</li>').appendTo('.carousel ul');
$(".carousel ul").find('li').last().focus();
});
$(document).on('click', '#ComputerDiv li', function(event) {
alert('TestComputer');
$('<li>Comp</li>').appendTo('.carousel ul');
$(".carousel ul").find('li').last().focus();
});
$(document).on('click', '.carousel ul li a', function(event) {
alert('TestXButton');
$(this).parent().fadeOut();
});
$(function(){
var carousel = $('.carousel ul');
var carouselChild = carousel.find('li');
var clickCount = 0;
var canClick = true;
function numberOfElements() {
var carWidth=carousel.parent().width();
var elemWidth=carouselChild.width();
return Math.floor(carWidth/elemWidth);
}
var moveWith=numberOfElements();
itemWidth = carousel.find('li:first').width()+1; //Including margin
//Set Carousel width so it won't wrap
carousel.width(itemWidth*carouselChild.length);
//Place the child elements to their original locations.
refreshChildPosition();
//Set the event handlers for buttons.
$('.btnNext').click(function(){
if(canClick){
canClick = false;
//Animate the slider to left as item width
carousel.stop(false, true).animate({
left : '-='+itemWidth*moveWith
},600, function(){
//Find the first item and append it as the last item.
for (var i=0; i<moveWith; i++) {
clickCount++;
lastItem = carousel.find('li:first');
lastItem.remove().appendTo(carousel);
lastItem.css('left', (((carouselChild.length-1+clickCount)*(itemWidth))));
}
//refreshChildPosition();
canClick = true;
});
}
});
$('.btnPrevious').click(function(){
if(canClick){
canClick = false;
//Find the first item and append it as the last item.
for (var i=0; i<moveWith; i++) {
clickCount--;
lastItem = carousel.find('li:last');
lastItem.remove().prependTo(carousel);
console.log(itemWidth*(clickCount));
lastItem.css('left', itemWidth*clickCount);
}
//Animate the slider to right as item width
carousel.finish(true).animate({
left: '+='+itemWidth*numberOfElements()
},300, function(){
canClick = true;
});
}
});
function refreshChildPosition(){
carouselChild.each(function(){
$(this).css('left', itemWidth*carouselChild.index($(this)));
});
}
});
});
The items are properly inserted into the DOM. However, you don't set their position. After inserting them you need to call the function refreshChildPosition(). And you need to extend it to update the carouselChild collection at the beginning:
function refreshChildPosition(){
carouselChild = carousel.find('li'); // this is new
carouselChild.each(function(){
$(this).css('left', itemWidth*carouselChild.index($(this)));
});
}
Of course you need to make the function accessible in the outer scope. If you want to make only minor changes, I suggest you add a variable in the outer scope that you assign it to from the scope in which refreshChildPosition() is defined:
$(document).ready(function() {
var refresh;
// ...
// the click handlers (now calling refresh() at the end)
// ...
$(function(){
var carousel = $('.carousel ul');
var carouselChild = carousel.find('li');
var clickCount = 0;
var canClick = true;
refresh = refreshChildPosition; // <-- give it to the outer scope
// ... rest of your code
This is certainly not the nicest solution but at least it solves your immediate problem.

Categories