How to continuously rotate children in a jQuery animation? - javascript

I have a div with class 'bannergroup' that contains multiple divs 'banneritem'. I want these items to rotate (fade in then fade out) in place of each other.
I can have several divs with the class bannergroup and each one should rotate separately.
Here is the HTML:
<div class="bannergroup">
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
</div>
<div class="bannergroup">
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
</div>
My Jquery looks like:
$('.banneritem').css('display', 'none');
$('.bannergroup').children('.banneritem').each(function( i ) {
$(this).fadeIn().delay(4000).fadeOut();
});
The problem: the each statement continues to run before the previous div completes. I want it to wait until the previous child is gone. Also, I need this to continuously run. After a single time it stops. I can put this into a function, but I am not sure how to know to call it again.
EDIT: There are not always 4 child items. Also one group may have a different number of children than the others, but they should both rotate in-sync. It is ok if one completes before the other and then just restarts itself.

I have answered this question multiple times before. This time I will try wrapping it in a jQuery plugin. The .rotate() function will apply the effect you want to the children of the matched elements, a fade in/out effect per children in a continuous animation.
$.fn.rotate = function(){
return this.each(function() {
/* Cache element's children */
var $children = $(this).children();
/* Current element to display */
var position = -1;
/* IIFE */
!function loop() {
/* Get next element's position.
* Restarting from first children after the last one.
*/
position = (position + 1) % $children.length;
/* Fade element */
$children.eq(position).fadeIn(1000).delay(1000).fadeOut(1000, loop);
}();
});
};
Usage:
$(function(){
$(".banneritem").hide();
$(".bannergroup").rotate();
});
See it here.

jsFiddle example
$('div.bannergroup').each(function () {
$('div.banneritem', this).not(':first').hide();
var thisDiv = this;
setInterval(function () {
var idx = $('div.banneritem', thisDiv).index($('div.banneritem', thisDiv).filter(':visible'));
$('div.banneritem:eq(' + idx + ')', thisDiv).fadeOut(function () {
idx++;
if (idx == ($('div.banneritem', thisDiv).length)) idx = 0;
$('div.banneritem', thisDiv).eq(idx).fadeIn();
});
}, 2000);
});

You can solve this problem in 2 ways. The one below is the easiest, using the index to increase the delay per item.
$('.banneritem').css('display', 'none');
$('.bannergroup').children('.banneritem').each(function( i ) {
$(this).delay(4000 * i)).fadeIn().delay(4000 * (i+1)).fadeOut();
});

Related

Show only 10 items using jquery infinite scroll within the div

Hi I found lots of examples related to this question, but so far the examples that I see they don't match my needs.On my div at the moment I load all the list content retrieved from my function,My goal is I want to be able to only show 6 items and keep on appending the other 6 until the list is exhausted using the infinite scroll in jQuery.
This is how my list look within the div.
<div class="listOfAnything">
<div class="all">apple</div>
<div class="all">Banana</div>
<div class="all">Guava</div>
<div class="all">Pear</div>
<div class="all">mango</div>
<div class="all">Grapes</div>
<div class="all">Avocado</div>
<div class="all">Orange</div>
<div class="all">Lemon</div>
<div class="all">Nartjie</div>
<div class="all">Granadilla</div>
<div class="all">pawpaw</div>
<div class="all">Ginger</div>
<div class="all">Watermelon</div>
<div class="all">potato</div>
<div class="all">Sweet Potato</div>
<div class="all">Peach</div>
</div>
I've tried to follow the tutorials on http://scrollmagic.io/examples/advanced/infinite_scrolling.html but I had no luck because i got stuck here
function addBoxes (amount) {
for (i=1; i<=amount; i++) {
var randomColor = '#'+('00000'+ (Math.random()*0xFFFFFF<<0).toString(16)).slice(-6);
$("<div></div>")
.addClass("box1")
.css("background-color", randomColor)
.appendTo(".dynamicContent #content");
}
// "loading" done -> revert to normal state
scene.update(); // make sure the scene gets the new start position
$("#loader").removeClass("active");
}
// add some boxes to start with.
addBoxes(18);
Because I already have the content on my div.
Added the scroll function
function addBoxes (amount) {
for (i=1; i<=amount; i++) {
var randomColor = '#'+('00000'+ (Math.random()*0xFFFFFF<<0).toString(16)).slice(-6);
$("<div></div>")
.addClass("box1")
.css("background-color", randomColor)
.appendTo(".dynamicContent #content");
}
// "loading" done -> revert to normal state
scene.update(); // make sure the scene gets the new start position
$("#loader").removeClass("active");
}
// add some boxes to start with.
addBoxes(6);
// do things on mousescroll
$(window).bind('mousewheel DOMMouseScroll', function(event)
{
if (event.originalEvent.wheelDelta < 0 || event.originalEvent.detail > 0) {
setTimeout(function(){
addBoxes(6);
}, 1000);
}
});

Choose a random div and apply css class with timeout and loop this?

I have the following HTML structure:
<div class="change me">Item 1</div>
<div class="change me">Item 2</div>
<div class="change me">Item 3</div>
<div class="change me">Item 4</div>
<div class="change me">Item 5</div>
<div class="change me">Item 6</div>
And CSS:
body {
font-family: Helvetica, Arial, sans-serif;
font-size:20px;
}
div {
background-color: #fff;
display: block;
border-bottom: 1px solid #ccc;
background-image: url(http://cdn.sstatic.net/Img/mini-hero-bg.png?v=7f269bbbdb22);
}
.change {
background-image: none;
}
Now I would like to pic a random div with Javascript / jQuery and "remove" the class "change" so that the default background image of the specific div will be visible. My code looks like that atm:
var divs = $(".me").toArray();
var divlength = divs.length;
setInterval(function(){
var randomnum = Math.floor(Math.random()*divlength);
var randomdiv = divs[randomnum];
$(randomdiv).addTemporaryClass("change", 1000);
}, 1000);
$.fn.extend({
addTemporaryClass: function(className, duration) {
var elements = this;
setTimeout(function() {
elements.addClass(className);
}, duration);
return this.each(function() {
$(this).removeClass(className);
});
}
});
I need to improve this to achieve the following:
I would like to have a smoother change from no-background-image to the visibility of the default background-image. Some fading effect or something like that. Already tried to add some transition to the div CSS but with no success.
Sometimes there is no "change"-class removing and for some time no background-image of any div visible but I need at least one image being visible everytime
I need to start the "remove"-class-thing immediately on page load so that there is already one background-image of a random div visible
Here is the current fiddle: http://jsfiddle.net/uRd6N/500/
Thx for your help, I am a noobie and not really familiar with JS / jQuery. If you know a better way to do this whole thing you could tell me too.
Regards
I have taken a look, and updated your Fiddle at http://jsfiddle.net/uRd6N/513/
Some changes I made:
var randomnum = Math.floor(Math.random()*(divlength-1));
Remember, array indexes start at 0, not 1, therefore I made the random number decrement by 1, otherwise your last div in the array would never have been reached.
var divs = $(".me").toArray();
var divlength = divs.length;
I declared these two variables outside of the scope of the setInterval function, to optimize the code a little more.
clearTimeout(doChange);
var doChange = setTimeout(function() {
elements.addClass(className);
}, duration);
I assigned the setTimeout to a variable and cleared it upon each call of the function, to avoid bubbling.
I am still looking into the transition, however another issue I spot is that there is no control mechanism to make sure that the last selected random number does no occur again on the next pick. This will need to be controlled.
Update 1
I have added random first div with background image on load, and removed it with first interval.
Update 2 (Duplicate Random Number Control)
Alright, I have managed to piece together some very simply logic that checks if the chosen random number is a re occurrence of the last chose number, and it decrements or increments the random number by 1, but ALWAYS within the scope of the div count, so it's safe. It's nothing smart, or complex, just simple procedural code. I added console logs, open your console and take a look at it in action. Code is as follows:
console.log("Chosen number is "+randomnum);
if(randomnum == lastnum){
console.log("We have a duplicate ("+randomnum+")");
if( (randomnum-1) >= 0 ){
randomnum = (randomnum-1);
console.log("Duplicate solved, it is now "+randomnum);
}else if( (randomnum+1) <= (divlength) ){
randomnum = (randomnum+1);
console.log("Duplicate solved, it is now "+randomnum);
}
}
lastnum = randomnum;
See the final udpated fiddle at this url: http://jsfiddle.net/uRd6N/537/
Happy coding!

Give multiple divs the same function

I want to create multiple thumbnails with the same .class. The thumbnail div contains 3 other divs. The first on is an image, the second one is a description which appear on mouseenter and the third one is a bar which change the opacity.
When the mouse hovers above the .thumbnail both elements should execute their function.
My Problem is that now every thumbnail executes the function, so every thumbnail is now highlighted. How can I change this so only one Thumbnail highlights while hovering above it?
HTML:
<div class="thumbnail">
<div class="thumbnail_image">
<img src="img/Picture.png">
</div>
<div class="thumbnail_describe">
<p>Description</p>
</div>
<div class="thumbnail_footer">
<p>Text</p>
</div>
</div>
jQuery:
$(document) .ready(function() {
var $thumb = $('.thumbnail')
var $thumb_des = $('.thumbnail_describe')
var $thumb_ft = $('.thumbnail_footer')
//mouseover thumbnail_describe
$thumb.mouseenter(function() {
$thumb_des.fadeTo(300, 0.8);
});
$thumb.mouseleave(function() {
$thumb_des.fadeTo(300, 0);
});
//mouseover thumbnail_footer
$thumb.mouseenter(function() {
$thumb_ft.fadeTo(300, 1);
});
$thumb.mouseleave(function() {
$thumb_ft.fadeTo(300, 0.8);
});
});
You code behave like this because you apply the fadeTo function to the $thumb_des and $thumb_ft selectors which contain respectively all the descriptions and footers of the page.
Instead, you should select the description and footer of the thumbnail triggering the mouse event, inside the mousenter or mouseleave functions.
Another thing you could change to optimize your code is to use only once the event listening functions, and perform both actions on the description and on the footer at the same time:
$thumb.mouseenter(function() {
var $this = $(this)
$this.find('.thumbnail_describe').fadeTo(300, 0.8);
$this.find('.thumbnail_footer').fadeTo(300, 1);
});
full working jsfiddle: http://jsfiddle.net/Yaz8H/
When you do:
$thumb_des.fadeTo(300, 0.8);
it fades all nodes in $thumb_des. What you want is to fade only the one that corresponds to the correct node in $thumb.
Try this:
for (i = 0; i < $thumb.length; i++)
{
$thumb[i].mouseenter(function (des) {
return function() {
des.fadeTo(300, 0.8);
};
}($thumb_des[i]));
});
}
You'll want to access the child objects of that particular thumbnail, something like this would work:
$(this).children('.thumbnail_describe').fadeTo(300, 0.8);
Here is a fiddle example.

Back button after a slide

i need to have a back button on my slide to return to the previous div. I did several test but without success.
there is my JS
function SlideOut(element) {
$(".opened").removeClass("opened");
$("#" + element).addClass("opened");
$("#content").removeClass().addClass(element);
}
$("#content div").click(function () {
var move = $(this).attr('data-move');
SlideOut(move);
});
There is the demo link:
http://jsfiddle.net/VA5Pv/
thanks
You could create a history. I edited the fiddle with some dirty code but the idea is there:
var history = [];
var last;
$("#content div").click(function () {
var move = $(this).attr('data-move');
if (last) history.push(last);
last = move;
SlideOut(move);
});
$("#back").click(function () {
SlideOut(history.pop());
return false;
});
http://jsfiddle.net/VA5Pv/1/
Basically: store the "move" variable in a history array. When you want to go back, pop the last value out of the history array.
Reset
If you just want to return to the initial state (no slides opened), just add the following:
$('button.close').click(function() {
$('.opened').removeClass('opened');
});
Tracking a full history is overkill in this case.
Demo: http://jsfiddle.net/VA5Pv/4/
History
Several answers suggested using a history. Most of them used an array which keeps track of the slides the user opened and then simply pop from that to "go back".
var history = [];
$('#content div').click(function() {
var move = $(this).attr('data-move');
history.push(move);
SlideOut();
});
$('button.close').click(function() {
history.pop();
SlideOut();
});
function SlideOut() {
var element = history[history.length - 1];
// ... same as before ...
}
This would be necessary if you wanted to allow the user to open any number of slides in any order and always present them with a button to go back to the previously opened slide.
Sequence
Another solution could have been to store all the slide IDs in an array and keep a counter that tells you at which slide you are. Going back would mean decrementing the counter if it is not already at zero and then switching to that particular slide.
This would be useful if you were trying to create something like a presentation where each slide is opened in sequence and the transitions are entirely linear.
This is why I asked you to clarify what you were trying to build. Depending on the use case, the solutions could have been vastly different and far more complex than what you were actually looking for.
Thanks for accepting my answer and welcome to StackOverflow. Feel free to upvote any answers you found helpful even if they did not answer your question sufficiently.
try the following:
$('.anim button').click(function(){$(this).parent().removeClass('opened');});
I assigned this to the button in div rouge. But the target could be anything in that div you want the user to click on ...
see here: JSfiddle
Here is the DEMO
<div id="fullContainer">
<div id="right" class="anim"></div>
<div id="rouge" class="anim">Hello world!
<button class="close">Close</button>
</div>
</div>
<div id="centerContainer">
<div id="relativeContainer">
<div id="content">
<div data-move="right">Open Right</div>
<div data-move="rouge">Open Rouge</div>
<div id="back">Back</div>
</div>
function SlideOut(element) {
if(element == undefined) {
$('#back').hide();
}
$(".opened").removeClass("opened");
$("#" + element).addClass("opened");
$("#content").removeClass().addClass(element);
}
$("#content div").click(function () {
var move = $(this).attr('data-move');
$('#back').show();
SlideOut(move);
});

Cycle visibility for layers

I have 10 divs with class "animate" and IDs from "one" to "ten", for example:
<div class="animate" id="six">
bla bla content
</div>
I need to cycle the visibility of these ten layers in a continuous loop.
The method doesn't have to be very efficient, it just has to work OK.
I have tried running them through a for loop and fade in then fade out them one by one but they all became visible at the same time then faded out together at each iteration.
The code I used for that:
layer_ids = ['one','two','three','four','five','six','seven','eight','nine','ten'];
for(i = 0; i < 300; i++)
{
animate_id = layer_ids[i%10];
element_selector = '.animate#'+animate_id;
$(element_selector).fadeIn(1500).delay(1000).fadeOut(1500);
}
I expected that at the first iteration the first one would be shown then hidden, then the second one, etc.
How can I show then hide them in sequence?
Another thing I'd like to know is how I can run this continuously. I tried with a while(1) but the page froze.
Would rather do this without 3rd party plugins if possible.
Smoothly transitions between content.
Use the setInterval milliseconds value to decide how long you would like to display each section.
Add as many DIVs as needed to the HTML, the code will count them.
Demo: http://jsfiddle.net/wdm954/QDQhu/4/
Any specific reason you want to do this with cycle?
Think the same could be accomplished with much less code:
var els = $("div.animate").hide();
function rotate(){
for (var i=0;i<els.length;i++){
$(els[i]).delay(i*1000).fadeIn(1500).delay(1000).fadeOut(1500);
}
setTimeout(rotate, i*1000);
}
rotate();
Example on jsfiddle, and it isn't restricted to the number of elements.
Version 1, fades in the next element while the currently visible element is still fading out. This looks nice if they're positioned on top of each other.
var roller = $('.animate'),
curr = roller.length-1;
function fadeOut() {
roller.eq(curr).fadeOut(1500, fadeIn);
}
function fadeIn() {
curr = (curr+1) % roller.length;
roller.eq(curr).fadeIn(1500, fadeOut);
}
fadeOut();
http://jsfiddle.net/kaFnb/2/
Version 2, fades the next element in only once the previous element has been faded out. This works well when the content isn't positioned on top of each other (like in the fiddle example).
var roller = $('.animate'),
curr = roller.length-1;
function toggleNextRoller() {
roller.eq(curr).fadeOut(1500);
curr = (curr+1) % roller.length;
roller.eq(curr).fadeIn(1500, toggleNextRoller);
}
toggleNextRoller();
http://jsfiddle.net/kaFnb/1/
I put together a little example for you. hope it helps:
$(function () {
function animateBoxes(targetElement, delay) {
var anims = targetElement;
var numnberOfAnims = anims.size();
anims.eq(0).addClass('visible').fadeIn();
setInterval(function () {
$('.visible').fadeOut(function () {
$(this).removeClass('visible').next().addClass('visible').fadeIn();
if ($(this).index() + 1 == numnberOfAnims) {
anims.eq(0).addClass('visible').fadeIn();
}
});
}, delay);
}
animateBoxes($('.animate'), 2000);
});
Html:
<div class="animate visible">
Content 1
</div>
<div class="animate">
Content 2
</div>
<div class="animate">
Content 3
</div>
<div class="animate">
Content 4
</div>
<div class="animate">
Content 5
</div>
CSS:
.animate
{
display:none;
border:solid 1px red;
padding:30px;
width:300px;
}

Categories