Not this selector on next element in jQuery chain - javascript

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);
}
});

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

get height of LI using jQuery so news ticker scrolls up the exact amount needed

I am using a script from
http://www.yourinspirationweb.com/en/jquery-how-to-create-a-news-ticker-with-just-a-few-javascript-lines/
which is a great newsticker, designed to scroll up just one article at a time, then append it again at the end in a continuous loop. But the limitation of this script is that the news items in each have to be the same height as eachother, which isn't always possible.
I have been trying to modify the script so that it will automatically get the outerheight of '#ticker li:first'. and scroll it so that marginTop equals the negative of that outerheight. rather than the default '-120px'. But i've realised it's written as CSS style, i don't know how to rewrite it. Help!
here's the original script:
$(function()
{
var ticker = function()
{
setTimeout(function(){
$('#ticker li:first').animate( {marginTop: '-120px'}, 800, function()
{
$(this).detach().appendTo('ul#ticker').removeAttr('style');
});
ticker();
}, 4000);
};
ticker();
});
This should do the trick. Just put the height into a variable, multiply by -1 (to make the negative number you need), and then drop it into the marginTop property:
$(function() {
var ticker = function() {
setTimeout(function() {
// get the height of the li element, multiply by -1 to be negative
var h = parseInt($("#ticker li:first").outerHeight()) * -1;
$('#ticker li:first').animate( {marginTop: h + 'px'}, 800, function() {
$(this).detach().appendTo('ul#ticker').removeAttr('style');
});
ticker();
}, 4000);
};
ticker();
});
To retrieve the outerHeight (including border, padding, and optionally margin) of an html element using jQuery, do $(element).outerHeight()
To retrieve the innerHeight of an html element using jQuery, do $(element).innerHeight()
$(function()
{
var ticker = function()
{
setTimeout(function(){
var oHeight = $('#ticker li:first').outerHeight();
$('#ticker li:first').animate( {marginTop: -oHeight}, 800, function()
{
$(this).detach().appendTo('ul#ticker').removeAttr('style');
});
ticker();
}, 4000);
};
ticker();
});
The default unit is pixels so you don't have to worry about appending px to the value.

A different approach to add/remove classes and animate elements

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

Help with modifying my custom JQuery slider to allow continous scrolling

You can view my custom slider here: http://www.awaismuzaffar.com/examples/index.html
And below is the JQuery code for it:
$(document).ready(function() {
// Slider Function
var slideWidth = $('div.slide').width();
// Set the left position of each div element
$('div.slide').each(function(index){
$(this).css('left', index * slideWidth ); // Multiply each div element by the index(0, 1 etc) so each div is placed inline
});
// Next step is to animate the div elements
var clickCount = 1;
var slideCount = $('div.slide').length;
// Set the previous button to hide when loading with the first slide
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc');
}
$('a#next-button').click(function() {
if(clickCount < slideCount) {
$('div.slide').animate({"left":"-=" + slideWidth}, 'slow');
$('a#previous-button').css('background-color', '#ffffff');
clickCount++;
}
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
$('a#previous-button').click(function() {
if(clickCount > 1){
$('div.slide').animate({"left":"+=" + slideWidth}, 'slow');
$('a#next-button').css('background-color', '#ffffff');
clickCount--;
}
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
});
I am trying to modify this slider to allow continous scrolling.
I am not sure exactly how to achieve this, I am assuming I need to use append, but I am not sure how to make use of it.
Thanks.
You're doing things a little manually, I'm thinking someone else might've solved the problem. But in any case, in your click next button, you'd need to load in additional content when you hit the end. So if I were you, I'd do something like this:
$('a#next-button').click(function() {
...
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc');
$.get(moreContentUrl, objectRepresentingCurrentScrollPosition, loadContent);
spinner.show(); // show some kind of spinner here (you can also hook up a default spinner on all ajax events with a global ajax handler
}
});
function loadContent(response) {
// append your content (your controller should return just the <div class="slide" /> elements, and give them a class="slide newSlide" so you can distinguish them below
// you can also do client side templating here. would be more efficient, then just return the items as objects instead of html
$('#slide-container').append(response.itemsHtml);
// slide all new divs right
$('div.newSlide').animate({"left":"+=" + slideWidth}, 'fast');
$('div.newSlide').removeClass('newSlide');
// update variables and un-grey the next button
$('a#previous-button').css('background-color', '#ffffff');
slideCount += response.itemCount;
// hide the spinner shown when starting the load
spinner.hide();
}
Give it a shot, hope it works. Now, to clean up that code a little bit, I'd suggest using css classes instead of inline background colors, etc.
Here's a solution (somewhat like Shaz's), just less code :):
$(document).ready(function(){
$('#previous-button').click(function(){slidePanel(-1)});
$('#next-button').click(function(){slidePanel(1)});
var n = 0;
var animating = false;
$('#slide-'+n).css('display', 'block');
function slidePanel(delta)
{
if(!animating)
{
animating = true;
var d = (delta > 0 ? $('#slide-'+n).width()*-1 : $('#slide-'+n).width());
$('#slide-'+n).animate({
left: "+="+d
}, 'slow', function() { $(this).css('display', 'none'); animating = false; });
n = (n + delta) % $('div.slide').length;
n = n < 0 ? $('div.slide').length + n : n;
$('#slide-'+n).css('left', $('#slide-container').offset().left +(d*-1));
$('#slide-'+n).css('display', 'block');
$('#slide-'+n).animate({
left: 0
}, 'slow');
}
}
});
Check out the sample here.
(I know there's a way to figure out the "current slide" with a one liner equation, but I think I'm brain dead atm :P)
(Edited to account for repeatedly clicking)
Try something like this: http://fiddle.jshell.net/Shaz/dsBkf/

Jquery: how to: when UL is shown, have first LI animate 'left' 20px, then to 0px, then have the second LI do that, then third, etc

When UL.chapters is 'slideDown', have the first 'chapters LI' animate the 'left' property to 20px, then animate back to 0px, then have the second LI do the same thing, then have the third, and so-on. with my code, they all animate directly after UL.chapters slides down, how do I make them do their animation 1 at a time, with the second not starting until the first has finished, etc.
$('h1').click(function() {
$('UL.chapters').slideDown(500);
$('.chapters LI').each(function() {
$(this).animate({'left':'20px'});
$(this).animate({'left':'0px'});
});
});
code updated.
Try this:
$(function() {
$('h1').click(function() {
$('.chapters').slideDown(500, function() {
doSlide($('.chapters li:first'));
});
});
});
function doSlide(current) {
$(current).animate({
'left': '20px'
}, function() {
$(current).animate({
'left': '0px'
}, function() {
doSlide($(current).next('li'));
});
});
}
This calls the slide animation function on the first <li> and then in the callback for the animation that slides it back to the starting position, it calls the function on the next <li>.
Here's a demo of it in action: http://jsfiddle.net/CBNgR/
Have you noticed the 4th line of your code is $('chapters LI') instead of $('.chapters LI')?
Also you're repeating yourself here. Try this:
$('h1').click(function() {
$('UL.chapters').slideDown(500);
$('.chapters LI').each(function() {
$(this).animate({'left':'20px'});
$(this).animate({'left':'0px'});
});
});
Also make sure that your LIs are set to position absolutely, or else your left animate will have issues.

Categories

Resources