A different approach to add/remove classes and animate elements - javascript

I have 5 list items, when one is clicked the only method I know is to animate all the elements then reanimate the selected element to the new width. Can anyone advise me how I can cut down this process so only the current active item gets animated and the class removed and then the new item gets animated and the active class added?
JS
var test = $('#test'),
test_li = test.children(),
small = 60,
large = 200;
test_li.on('click', function(e) {
if( !$(this).hasClass('active') ){
test_li.animate({ width: small }, 300).removeClass('active'); //animates every single li every time
$(this).animate({ width: large }, 300).addClass('active');
}
});​
Fiddle Here: http://jsfiddle.net/TSNtu/1/

var test = $('#test'),
test_li = test.children(),
small = 60,
large = 200;
test_li.on('click', function(e) {
// if clicked element is active itself then do nothing
if ($(this).hasClass('active')) return;
// remove active from others
$('.active', test).animate({
width: small
}, 300).removeClass('active');
// animate the clicked one
$(this).animate({
width: large
}, 300).addClass('active');
});
DEMO
With a single chain
var test = $('#test'),
test_li = test.children(),
small = 60,
large = 200;
test_li.on('click', function(e) {
// if clicked element is active itself then do nothing
if ($(this).hasClass('active')) return;
$(this) // clicked li
.animate({
width: large
}, 300)
.addClass('active')
.siblings('.active') // other li
.animate({
width: small
}, 300)
.removeClass('active');
});
DEMO

Related

.effect('slide'... not showing next object

I was browsing around stackoverflow for slider and found this one http://jsfiddle.net/skram/tHZLY/2/ (Somehow I can't find the topic...)
code :
var $pages = $('.page');
$('#nxt').click(
function() {
var $cur = $('.active');
var $next = $cur.next();
if ($next.length == 0) return;
$cur.removeClass('active');
$next.addClass('active');
$('.page').not('.active').effect('slide',{direction:'right',mode:'hide'});
$('.active').effect('slide',{direction:'right',mode:'show'});
});
$('#prev').click(
function() {
var $cur = $('.active');
var $prev = $cur.prev('.page');
if ($prev.length == 0) return;
$cur.removeClass('active');
$prev.addClass('active');
$('.page').not('.active').animate({"width": 0}, "slow");
$('.active').animate({"width": 200}, "slow");
});
When I change .animate with .effect , next div is not showing.
JSFIDDLE with the change: http://jsfiddle.net/tHZLY/12/
The problem is that you're using 2 different methods to show/hide divs.
You should use either slide or width.
Width of not .active divs is initially set to 0px in CSS, so that they can be animated later on, using .animate({"width": 200}) . But it does not work with .effect('slide', ...) as it deos not actually affect the width property.
.animate({"width": 0}) does not make the element invisible, while you're applying .hide() on:
.effect('slide',{direction:'right',mode:'hide'});
Check this experiment .
To get this to work with .effect('slide', ...), you should remove width: 0px; from CSS of the divs, place all .page divs at one position (for demo purposes used simple position: absolute;) and do not mix 2 different show/hide methods on prev/next:
// hide not active divs:
$('.page:not(.active)').hide();
$('#nxt').click(function(){
var $cur = $('.page.active');
var $next = $cur.next('.page');
if ($next.length == 0) return;
$cur.removeClass('active').effect('slide',{direction:'left',mode:'hide'});
$next.addClass('active').effect('slide',{direction:'right',mode:'show'});
});
$('#prev').click(function() {
var $cur = $('.page.active');
var $prev = $cur.prev('.page');
if ($prev.length == 0) return;
// do not mix up .aniamte(width) with .effect(slide)!
$cur.removeClass('active').effect('slide',{direction:'right',mode:'hide'});
$prev.addClass('active').effect('slide',{direction:'left',mode:'show'});
});
DEMO

Not this selector on next element in jQuery chain

I'm having a chain of jQuery methods to find a ul in a li and animate the height of it.
$('.collapse-trigger').click(function() {
if($(this).next('.collapse-ul').height() == 0) {
$(this).css('background', '#000000');
var height = $(this).next('.collapse-ul').children().length;
$(this).next('.collapse-ul').animate({height: height*42}, 500); // multiply height with number of menupoints
}
else {
$(this).css('background', '#414141');
$(this).next('.collapse-ul').animate({height: 0}, 500);
}
});
with this I can collapse each ul and on a click again it animates back to 0. What I intend to do is, when one of the ul is animating out, the others animate back to zero.
I assume I need something like .not(this) but struggle with it.
My attempt:
$('this').next().not('.collapse-ul', this).animate({height: 0}, 500); // <-- inside the not method I don't know how to write it
Thanks
Try this : You can find the collapsible ul first and then filter it using .not()
$('.collapse-trigger').click(function() {
if($(this).next('.collapse-ul').height() == 0) {
$(this).css('background', '#000000');
var height = $(this).next('.collapse-ul').children().length;
var $collapseUl = $(this).next('.collapse-ul');
//filter current collapsible ul
$('.collapse-ul').not($collapseUl).animate({height: 0}, 500);
$collapseUl.animate({height: height*42}, 500); // multiply height with number of menupoints
}
else {
$(this).css('background', '#414141');
$(this).next('.collapse-ul').animate({height: 0}, 500);
}
});

Jquery animating width accordion style banner

I built this simple accordion style banner. Here's what it's supposed to do:
Grab <li> containing images from selected <ul>.
Divide them equally within the container (div.banner)
On 'mouseenter', add class .active to the hovered <li>
Shrink the other <li>s widths (half their original width).
Enlarge active <li> to new width (remainder after halving the others)
On 'mouseleave', all return to original widths.
Works fine until you swipe over multiple panes quickly. If you do, the last of the floated <li>'s break to the next line. It appears the total width of the panes is exceeding their container.
Rounding error while animating? Does it have something to do with animate's default 'swing' easing?
Fiddle: http://jsfiddle.net/UNFc4/
var banner = $('.banner');
var list_items = banner.find('li');
var banner_width = $(banner).width();
var num_of_images = $(banner).find('li').length;
var original_width = banner_width / num_of_images;
var half_width = (banner_width / num_of_images) / 2;
var init = function () {
$(list_items).css('width', original_width);
$(list_items).on('mouseenter', function () {
$(this).addClass('active');
doAnimation();
});
$(list_items).on('mouseleave', function () {
resetAnimation();
$(this).removeClass('active');
});
}
var doAnimation = function () {
$(list_items).not(".active").stop().animate({
width: half_width + "px"
}, 500);
$(".active").stop().animate({
width: (original_width + (half_width * (num_of_images - 1))) + "px"
}, 500);
}
var resetAnimation = function () {
$(list_items).stop().animate({
width: original_width + "px"
}, 500);
}
init();
I could fix it by changing this line, slowing the animation of the others, giving things time to equal out. But, I'd rather solve what's going on here, hopefully learning a bit more about how jQuery's animate() works.
$(list_items).not(".active").stop().animate({
width: half_width + "px"
}, 480); // changed 500 to 480
For those interested, I realized I only needed the reset on the banner area. Now it works, as described, without all the jitteriness and the subsequent layout mis-alignments.
New Fiddle: http://jsfiddle.net/UNFc4/1/
$(list_items).on('mouseenter', function () {
$(this).addClass('active');
doAnimation();
});
$(list_items).on('mouseleave', function () {
$(this).removeClass('active');
doAnimation();
});
$(banner).on('mouseleave', function () {
resetAnimation();
});

JQuery Slide Smoothing

The slide animation is not smooth, I googled a bit and found out that I need to set a fixed width for my container but the container's width is set to fill up between 2 other divs.
$('.content_block .content_block_title').on("click", function(event) {
var target = event.target || event.srcElement;
var child = $(target).next();
child.css('width', child.width()); //tried with this but it didnt make the anim smoother.
if (!child.is(':hidden'))
child.slideUp(350);
else
child.slideDown(150);
});
if (!child.is(':hidden'))
child.animate({
height: "350px"
}, 5000, function() {
// Animation complete.
});
else
child.animate({
height: "150px"
}, 5000, function() {
// Animation complete.
});

Return Multiple li's as a "slide"

I'm putting together a quick little status board that shows active and upcoming github issues.
I have them all pulled in and formatted as a simple list and found a nice jQuery plugin that cycles through each item as a sort of slideshow. However, it was requested that it show multiple issues at once to fill up the screen more.
So on each slide swap it would display, say 5 LI items at once versus just 1. And then swap to show the next 5 and so on.
HTML
...
<ul id="issue-list">
<li class="issue"></li>
...
<li class="issue"></li>
</ul>
...
<script type="text/javascript">
$(function() {
$('#issue-list').swapmyli({
swapTime: 900, // Speed of effect in animation
transitionTime: 700, // Speed of Transition of ul (height transformation)
time: 4000, // How long each slide will show
timer: 1, // Show (1) /Hide (0) the timer.
css: 0 // Apply plugin css on the list elements.
});
});
</script>
JS
(function(e) {
e.fn.swapmyli = function(t) {
function s() {
var e = i.parent().find(".timer span");
e.animate({
width: "100%"
}, r);
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
i.animate({
height: n
}, t.transitionTime);
i.find("li").hide();
e.animate({
width: "0%"
}, 60);
i.find("li:first").remove().appendTo(i).fadeIn(t.swapTime)
}
var n = {
swapTime: 300,
transitionTime: 900,
time: 2e3,
timer: 1,
css: 1
};
var t = e.extend(n, t);
var r = t.time - t.swapTime;
var i = this;
i.wrap('<div class="swapmyli clearfix"></div>');
i.after('<div class="timer"><span></span></div><br class="clear" />');
e(window).load(function() {
var e = i.find("li:first").outerHeight(true);
i.height(e);
i.find("li").hide();
s()
});
if (t.timer == 0) {
i.parent().find(".timer").hide()
}
if (t.css == 0) {
i.parent().addClass("nocss")
}
setInterval(s, t.time)
}
})(jQuery)
I'm not sure if outerHeight() will function correctly with slice, but you may try changing these lines:
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
To the following:
var n = i.find("li").slice(0, 4).outerHeight(true);
i.find("li").slice(0, 4).fadeOut(120);
That's sort of a quick answer, but hopefully you're catching my drift. Probably need to play around with it a little bit :)

Categories

Resources