Delay on while loop function - javascript

I've tried to make an automated slider, although it seems my code isn't working - it either crashes the browser or it just executes very fast.
what I've been playing around with is the setTimeout, but it doesn't seem to work in a while-loop.
var playSlider = true;
if(playSlider) {
var i = $('#sliderwrapper ul li:visible').attr('data-number');
var lengthLi = $('#sliderwrapper ul li').size();
while(i<=lengthLi) {
var x = i + 1;
setTimeout(function(){
$('#sliderwrapper ul li[data-number=' + i + ']').fadeOut(450);
$('#sliderwrapper ul li[data-number=' + x + ']').fadeIn(600);
}, 3000);
i++;
}
}
HTML:
<ul>
<li data-number="1" data-description="Buy now!"><img src="images/slider1.png" border="0"></li>
<li data-number="2" data-description="Buy later!"><img src="images/slider2.png" border="0"></li>
<li data-number="3"><img src="images/slider3.png" border="0"></li>
<li data-number="4"><img src="images/slider4.png" border="0"></li>
<li data-number="5"><img src="images/slider5.png" border="0"></li>
<li data-number="6"><img src="images/slider2.png" border="0"></li>
<li data-number="7"><img src="images/slider3.png" border="0"></li>
<li data-number="8"><img src="images/slider5.png" border="0"></li>
<li data-number="9"><img src="images/slider1.png" border="0"></li>
</ul>

You can use the .delay("3000") to put pauses between JQuery commands

There were a couple of things that I changed...
var playSlider = true;
if(playSlider) {
var i = $('#sliderwrapper ul li:visible').attr('data-number');
var lengthLi = $('#sliderwrapper ul li').length();
while(i <= lengthLi) {
var x = i + 1;
setTimeout(function(){
$('#sliderwrapper ul li[data-number=' + i + ']').fadeOut(450);
$('#sliderwrapper ul li[data-number=' + x + ']').fadeIn(600);
}, 3000 * i);
i++;
}
}
I changed .size() to .length() to count the li elements (size is deprecated), and I changed the timeout to 3000 * i, otherwise they'd all fade out and in after 3 seconds, at the same time.

LIVE DEMO
var $li = $('#sliderwrapper ul li');
var N = $li.length;
var C = 0 ;
var intv ;
$li.hide().eq(C).show();
function loop(){
intv = setInterval(function(){
$li.eq( ++C % N ).fadeTo(500,1).siblings().fadeTo(500,0);
},3000);
}
loop();
$('#sliderwrapper').on('mouseenter mouseleave', function( e ){
var mEnt = e.type=='mouseenter' ? clearInterval( intv ) : loop() ;
});

Then a bit recursion will help you:
function rec(){
//your code and so on
setTimeout(function(){
rec();
},3000);
}

Related

Javascript / Add class to element with interval

Javascript isn't my forte, so I'm looking for help : How would you write a function which add a Class to 3 elements with interval ?
<ul>
<li class="panel">Item 1</li>
<li class="panel">Item 2</li>
<li class="panel">Item 3</li>
</ul>
The idea is to add an .--active class on the 1st item when document is ready and remove it after 2sec to add it to the 2nd item and so on.
If you're using jQuery you could loop through the li's using the index, and reset the index to 0 when you reach the last li element :
if( $('li.panel.active').index() == lis_count-1 )
active_li_index = 0;
else
active_li_index++;
Hope this helps.
jQuery solution:
$(function(){
var lis_count = $('li.panel').length;
var active_li_index = 0;
setInterval(function(){
if( $('li.panel.active').index() == lis_count-1 )
active_li_index = 0;
else
active_li_index++;
$('li.panel.active').removeClass('active');
$('li.panel').eq(active_li_index).addClass('active');
}, 1000);
})
.active{
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="panel active">Item 1</li>
<li class="panel">Item 2</li>
<li class="panel">Item 3</li>
</ul>
Pure JS solution:
document.addEventListener('DOMContentLoaded', function(){
var lis = Array.prototype.slice.call( document.querySelectorAll('li.panel'));
var lis_count = lis.length;
var active_li_index = 0;
setInterval(function(){
var active_li = document.querySelector('li.panel.active');
if( lis.indexOf(active_li) == lis_count-1 )
active_li_index = 0;
else
active_li_index++;
active_li.classList.remove('active');
document.querySelectorAll('li.panel')[active_li_index].classList.add('active');
}, 1000);
}, false);
.active{
background-color: yellow;
}
<ul>
<li class="panel active">Item 1</li>
<li class="panel">Item 2</li>
<li class="panel">Item 3</li>
</ul>
Without jQuery:
function showGarland () {
var itemClass = 'panel';
var activeClass = '--active';
var wait = 2000; // 2 seconds
function toggleActive (element, index, maxIndex) {
setTimeout(function(){
element.classList.add(activeClass);
setTimeout(function(){
element.classList.remove(activeClass);
if (index == maxIndex) {
runLoop();
}
}, wait);
}, wait * index);
}
function runLoop () {
var allItems = document.getElementsByClassName(itemClass);
for (var index = 0; index < allItems.length; index++) {
var element = allItems[index];
toggleActive(element, index, allItems.length - 1);
}
}
runLoop();
}
window.addEventListener('load', showGarland);
.--active {
color:red;
}
<ul>
<li class="panel">Item 1</li>
<li class="panel">Item 2</li>
<li class="panel">Item 3</li>
</ul>
since you use jQuery you can do :
jQuery(() => { // callback when DOM is ready
$('.panel1').addClass('active'); // add your class
setTimeout(() => { // function that execute the callback after 2000ms (2s)
$('.panel1).removeClass('active'); // remove your class active
}, 2000);
});
you should use different class for your differents div
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- <div class="hide">
text
</div> -->
<ul id="Items">
<li class="panel">Item 1</li>
<li class="panel hide">Item 2</li>
<li class="panel hide">Item 3</li>
</ul>
<style>
.hide{
visibility: hidden;
}
</style>
<script>
$(document).ready(function() {
var listItems = $("#Items li");
// alert(listItems);
listItems.each(function(idx, li) {
var product = $(li);
setInterval(function(){
product.css( "visibility", "visible" );
$(li).next().css( "visibility", "hidden" );
$(li).prev().css( "visibility", "hidden" );
}, 2000);
});
});
</script>
The above one works fine for two elements, but for the third element its showing quickly without displayinh the second element.
You can use something like this, you need to call toggleClass with the index you want to start, The functions addClass and removeClass supports multiple elements and multiple classes.
// Add class to element
// support multiple classes
function addClass(elements, className){
// split classes
var classArray = className.split(' ');
var els = [];
// If element does not have length property
if(elements.length == undefined)
els[0] = elements
else
els = elements;
for(e=0; e<els.length; e++){
var element = els[e];
for(i=0; i<classArray.length; i++){
if(element.className.indexOf(classArray[i])==-1){
element.className += ' ' + classArray[i];
}
}
}
}
// Remove class to element
// support multiple classes
function removeClass(elements, className){
var classArray = className.split(' ');
var els = [];
// If elements does not have length property
if(elements.length == undefined)
els[0] = elements
else
els = elements;
for(e=0; e<els.length; e++){
var element = els[e];
for(i= 0; i<classArray.length; i++){
element.className = element.className.replace(classArray[i], '').trim();
}
}
}
function toggleClass(index){
// get active elements and remove active class
removeClass(document.getElementsByClassName('active'), 'active');
// add class to element at index
addClass(document.getElementsByClassName('panel')[index], 'active');
// test if index should increment or reset
if(index<document.getElementsByClassName('panel').length - 1){
index++;
}else{
index = 0;
}
// wait 2sec until execute toggleClass again
setTimeout(toggleClass, 2000, index);
}
toggleClass(0);
.active {
color: green;
}
<ul>
<li class="panel">Item 1</li>
<li class="panel active">Item 2</li>
<li class="panel">Item 3</li>
</ul>
Edit: By the way beware with method classList since you'll need to polyfill for browser compatibility
window.addEventListener("load",function change(i=0){
var els=document.getElementsByClassName("panel");
if(els[i-1]) els[i-1].classList.toggle("active");
els[i].classList.toggle("active");
if(i<els.length-1) setTimeout(change,2000,i+1);
});
You could use a recursive approach to iterate over the class elements slowly and toggle their active class...
Without jQuery:
function showGarland () {
var itemClass = 'panel';
var activeClass = '--active';
var wait = 2000; // 2 seconds
function toggleActive (element, index, maxIndex) {
setTimeout(function(){
element.classList.add(activeClass);
setTimeout(function(){
element.classList.remove(activeClass);
if (index == maxIndex) {
runLoop();
}
}, wait);
}, wait * index);
}
function runLoop () {
var allItems = document.getElementsByClassName(itemClass);
for (var index = 0; index < allItems.length; index++) {
var element = allItems[index];
toggleActive(element, index, allItems.length - 1);
}
}
runLoop();
}
window.addEventListener('load', showGarland);
.--active {
color:red;
}
<ul>
<li class="panel">Item 1</li>
<li class="panel">Item 2</li>
<li class="panel">Item 3</li>
</ul>

Triggers not working properly in Jquery slideshow

I made a slideshow in jquery but I am having a hard time to make a proper algorithm for triggers to become functional.
Any help in this regard would be highly appreciated.
Demo available here
HTML
<div class=slide-show>
<div id=slide1><h1>1</h1></div>
<div id=slide2><h1>2</h1></div>
<div id=slide3><h1>3</h1></div>
<div id=slide4><h1>4</h1></div>
</div>
<div class=slide-controls>
<div class=slide-controls-wrap>
<ul style="float:left;">
<li class=slide-cont id=1></li>
<li class=slide-cont id=2></li>
<li class=slide-cont id=3></li>
<li class=slide-cont id=4></li>
</ul>
<ul style="float:right;margin-right:50px;margin-top:2px;">
<li class=left-arrow></li>
<li class=right-arrow></li>
</ul>
</div>
</div>
JQUERY
$(document).ready(function () {
var delayInterval = 5000;
var delay = setTimeout;
function slide_show(cont) {
if (cont > 4) cont = 1;
$("#slide" + cont).fadeIn(1500);
$("#" + cont).css("background-position", '-69px -94px');
delay(function () {
$("#slide" + cont).fadeOut(1500);
$("#" + cont).css("background-position", '-19px -94px');
$('#1').click(function () {
slide_show(1);
});
$('#2').click(function () {
slide_show(2);
});
$('#3').click(function () {
slide_show(3);
});
$('#4').click(function () {
slide_show(4);
});
slide_show(cont + 1);
//$("#5").css("background-position",'-69px -94px');
}, delayInterval);
}
slide_show(1);
});
Thanks in advance.
Demo: http://codepen.io/anon/pen/azpwMy
Here is a better function for you :)
$(document).ready(function(){
$('.slide-cont').click(function(){
var slideId = $(this).attr('id');
currentSlide = slideId - 1;
$(slides).hide();
$('#slide' + slideId).fadeIn(1500);
})
})
var slides = $('.slide-show div');
currentSlide = 0;
function changeSlide(n) {
currentSlide += n;
if (currentSlide > slides.length - 1)
currentSlide = 0;
else if(currentSlide < 0)
currentSlide = slides.length -1;
$(slides).hide();
$(slides[currentSlide]).fadeIn(1500);
}
If you want to go one to the right you call with changeSlide(1), to the left changeSlide(-1)
To change the current slide based on time.
//Go one slide to the right every 2 seconds
setInterval(function(){changeSlide(1)}, 2000);
Hope i helped!

menu traversing on next and prev button click

can any one optimize this code i am new to jquery .
i want add class on next and previous button click.any way i wrote this code it's working for me but if any one optimize this code using jquery predefined methods .then it will more helpful..
Thanks in advance
$(document).ready(function () {
var length = $('#slides li').size() - 1;
var curren = 0;
console.log(length);
$('.next').on('click', function () {
if (curren >= 0 && curren < length) {
curren++;
$('.selected').removeClass('selected');
$('#slides li:eq(' + curren + ')').addClass('selected');
}
});
$('.prev').on('click', function () {
if (curren >= 1) {
curren--;
$('.selected').removeClass('selected');
$('#slides li:eq(' + curren + ')').addClass('selected');
}
});
});
my html code
<ul id="slides">
<li class="selected">first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
<li>five</li>
<li>six</li>
</ul>
You should have a look at $.next and $.prev.
Your code can easily be altered into something along these lines:
$(".next").on("click", function() {
var selected = $("#slides li.selected");
var next = selected.next();
if(next.length){next.addClass("selected");selected.removeClass("selected");}
});
$(".prev").on("click", function() {
var selected = $("#slides li.selected");
var prev = selected.prev();
if(prev.length){prev.addClass("selected");selected.removeClass("selected");}
});
Example can be found here: jsbin

Add and remove class from list using jquery

I have an unordered HTML list such as this:
<ul>
<li class="current"></li>
<li></li>
<li></li>
</ul>
Using jquery, I would like to automatically remove the current class from the first li element and add it to the second class. After a short period of time I would like to remove the class from the second li element and add it to the third. I would like for this to repeat as well.
I have this so far but it's not at all what I need:
$("ul li:first-child").addClass('current').delay(1000).queue(function(next){
$(this).removeClass('current');
$(this).next().addClass('current')
next();
});
If you want to be able to stop and start it:
var myInterval;
var myFunc = function() {
var cur = $('ul li.current');
if(cur.index() == $('ul li').length - 1) {
cur.removeClass('current');
$('ul li:first').addClass('current');
} else {
cur.removeClass('current').next().addClass('current');
}
};
//Start Interval
myInterval = setInterval(myFunc, 1000);
Then, to stop/start:
clearInterval(myInterval);
myInterval = setInterval(myFunc, 1000);
jsFiddle
var $li = $('ul li'), i = 0;
setInterval(function(){
i++;
if( $li.length === i ) i = 0;
$li.removeClass('current').eq(i).addClass('current')
}, 1000);
http://jsfiddle.net/mr7J6/
Try this:
var idx = 1;
setInterval(function () {
$('ul li').removeClass('current').eq(idx).addClass('current');
idx++;
if (idx == $('ul li').length) idx = 0;
}, 1000);
jsFiddle example
$(function(){
move();
});
function move(){
$("ul li.current").delay(1000).queue(function(next){
$(this).removeClass('current');
if($(this).next().addClass('current').length){
move();
}
});
}
If you need it to wrap around, you can do it using the modulus operator like this:
$(document).ready(function() {
var targets = $('ul li');
var len = targets.length;
var i = 0;
setInterval(function() {
// remove from current
$('li.highlight').removeClass('highlight');
i = (i + 1) % len;
targets.eq(i).addClass('highlight');
}, 1000);
});
Demo
Add and remove class unorder list current class using the jQuery click event.
**
Working Example
**
$(document).on('ready', function() {
$('.list-1 li').each(function(){
var t = $(this);
t.find('a').click(function(){
$('li.current').removeClass('current');
t.addClass('current');
});
});
});
.list-1 li a{text-decoration:none; color:#444; background:#ddd; padding:5px 15px 10px;}
.list-1 li.current a{background:tomato; color:#fff;}
.list-1{display:flex; flex-wrap:wrap;min-width:140px}
.list-1 li{padding:5px;margin:0 0 15px;display:block;}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-inline list-1">
<li class="current">Exapmle 1</li>
<li>Exapmle 2</li>
<li>Exapmle 3</li>
<li>Exapmle 4</li>
<li>Exapmle 5</li>
<li>Exapmle 6</li>
<li>Exapmle 7</li>
<li>Exapmle 8</li>
<li>Exapmle 9</li>
</ul>

My slider works when it's context specific, but when I try to make it context agnostic it breaks. What's wrong with my code?

Here's the jQuery I'm dealing with. The loop() function works brilliantly when I input the proper id's and such, but now that I've wrapped it in the Slider() function, it's broken. I don't know how to fix it. Any help? (jsfiddle http://jsfiddle.net/yramagicman/Uc8LW/8/)
$(document).ready(function () {
function Slider(wrapper, kids) {
this.wrapper = wrapper;
this.kids = kids;
this.loop = function(wrapper, kids) {
var count = $(wrapper).children().length,
fade = 1000,
selector = [],
delay = 1000;
console.log(count); //logs 0
for (var i = 1; i < count + 1; i++) {
selector[i] = $(wrapper + ' ' + kids + ':nth-child(' + i + ')');
selector[i].addClass('hidden');
console.log(selector[i]);
}
var z =1;
console.log(selector[z]); //logs undefined
selector[z].each(function () { //uncaught type error
$(this).addClass('visible').fadeIn(fade).delay(delay).fadeOut(fade, function () {
$(this).hide().remove().appendTo(wrapper);
}); //end callback
});
};
$(wrapper).children().addClass('hidden');
//setInterval(loop, 1000); //commented out for debugging. Don't want a loop doing nothing.
loop();
}
Slider('#slider', 'li');
}); // end ready
The related html
<ul id="slider">
<li> item 1</li>
<li> item 2</li>
<li> item 3</li>
<li> item 4</li>
</ul>
and css
.hidden{
position: absolute;
left: -10000px;
top: -10000px;
}
.visible{
position: static;
}
I figured it out! Here's the code.
$(document).ready(function () {
var loop = function (wrapper, kids, fade, delay) {
var count = $(wrapper).children().length,
selector = [];
$(wrapper).children().fadeOut(0);
for (var i = 1; i < count + 1; i++) {
selector[i] = $(wrapper + ' ' + kids + ':nth-child(' + i + ')');
}
var z = 1;
selector[z].each(function () {
$(this).fadeIn(fade).delay(delay).fadeOut(fade, function () {
$(this).remove().appendTo(wrapper);
}); //end callback
});
};
setInterval(function () {
loop('#slider', 'li', 2000, 7000);
}, 0);
});
// end ready
All HTML is the same as in the question.

Categories