Transition List Item Scrolling - HTML - javascript

Here's the FIDDLE.
List item that appears on clicking the up and down arrows.
When I click on it. It appears instantly which I don't want it to be like that.
I wanted to add a transition to it but I don't have any clue whether to apply it on a li or a tag.
Besides I'm here hiding and revealing li items on click. But I need the transition like when I click on the up arrow, I want the hidden element to push the active element downwards and vice versa.
Someone help me in this.

I updated your FIDDLE
you may check it out.
var
cur = 2,
$container = $('.dropdown-container'),
$ul = $('.dropdown'),
$ul_length = $('.dropdown li').children().length,
$up = $('.up'),
$down = $('.down'),
changeLi = function (cur) {
var $cur_li = $('.dropdown li:nth-child(' + cur + ')');
$('.current_selected').removeClass('current_selected');
$cur_li.addClass('current_selected');
$container
.height($cur_li.outerHeight())
.width($cur_li.outerWidth());
$up.offset({
left: ($container.outerWidth() - $up.outerWidth()) / 2
});
$down.offset({
left: ($container.outerWidth() - $down.outerWidth()) / 2
});
$ul.animate({
top: -$cur_li.position().top
}, 200);
};
$up.on('click', function () {
cur--;
if (cur < 1) {
cur = 1;
return false;
}
changeLi(cur);
});
$down.on('click', function () {
cur++;
if (cur > $ul_length) {
cur = $ul_length;
return false;
}
changeLi(cur);
});
changeLi(cur);

You can add animatation like slideUp, slideDown etc.
var cur = 2;
$('.up').click(function() {
if(cur <= 0) return;
var last = cur;
cur --;
$('.dropdown li').eq(last).hide(500).addClass('hide');
$('.dropdown li').eq(cur).show(100).removeClass('hide');
});
$('.down').click(function() {
if(cur >= $('.dropdown li').length - 1) return;
var last = cur;
cur ++;
$('.dropdown li').eq(last).hide(500).addClass('hide');
$('.dropdown li').eq(cur).show(100).removeClass('hide');
});

Related

jQuery slider doesn't rotate

I have a slider rotator on my site but it doesn't rotate items automatically in the boxes - navigation works and rotate but I want it to rotate automatically, right after I enter the site.
This is my js:
$(document).ready(function() {
var nbr = 0;
$('.slider').each(function() {
var slider = $(this);
//get width and height of the wrapper and give it to the UL
var wrapperwidth = $(slider).width() * $(slider).find('ul > li').size();
$(slider).find('ul').css('width', wrapperwidth);
var wrapperheight = $(slider).height();
$(slider).find('ul').css('height', wrapperheight);
//set my li width
var width = $(slider).width();
$(slider).find('ul li').css('width', width);
//set my counter vars
var counter = $(slider).find('ul > li').size();
var decount = 1;
var autocount = 1;
if (counter > 1) {
//create my number navigation
var createNum = 1;
$(slider).after('<ul class="numbers"><li></li></ul>');
var numbers = $(slider).parent().find('.numbers');
$(numbers).find('li:first-child').html(createNum+'_'+nbr).addClass('activenum').attr('id', 'id1_'+nbr);
while ( createNum != counter) {
createNum++;
$(numbers).append("<li id='id"+createNum+"_"+nbr+"'>"+createNum+"_"+nbr+"</li>");
}
//get my number-width (number navigation should always be centered)
var numwidth = $(slider).find('.numbers li:first-child').width() * $(slider).find('.numbers li').size();
$(slider).find('.numbers').css('width', numwidth);
}
nbr++;
});
//make the number clickable
$(".numbers li").click(function() {
var slider = $(this).closest('.sliderWrapper');
var slider0 = $(slider).find('.slider');
var clickednum = $(this).html().split('_')[0] * - $(slider0).width() + $(slider0).width();
$(slider0).find('ul').animate({ left: clickednum }, 400, 'swing', function() { });
$(slider).find('.activenum').removeClass('activenum');
$(this).addClass('activenum');
decount = $(this).html();
});
rotateSwitch = function(sliderW, speed) {
var sliderWrap = sliderW;
play = setInterval(function() {
var nextNum = parseInt($($(sliderWrap).find(".numbers li.activenum")).html().split('_')[0])+1;
if (nextNum > $(sliderWrap).find(".numbers li").length) {
nextNum = 1;
}
//console.log("nextnum: "+nextNum+", numbers length: "+$(sliderWrap).find(".numbers li").length);
$(sliderWrap).find(".numbers li").each(function() {
if( parseInt($(this).html().split('_')[0]) == nextNum )
$(this).click();
});
}, speed);
};
makeAutoSlide = function(sliderWrap, speed) {
if ($(sliderWrap).length > 0 && $(sliderWrap).find(".numbers li").length > 1) {
rotateSwitch(sliderWrap, speed);
$(sliderWrap).find(".slider li").hover(function() {
if ($(sliderWrap).find(".numbers li").length > 1) {
clearInterval(play); //Stop the rotation
}
}, function() {
if ($(sliderWrap).find(".numbers li").length > 1) {
rotateSwitch(sliderWrap, speed); //Resume rotation timer
}
});
}
};
});
I'm not really sure if this is a problem with setInterval and clearInterval or I wrote something wrong.
I put code in jsFiddle, so you know how the structure looks like.
http://jsfiddle.net/gecbjerd/1/
I appreciate for help.
Cheers

Add CSS only when a section or is in range

I am trying to make a "sticky" image where all images of class ".img" add a css attribute and then remove it when it is not in range.
I do this by getting the ID of each of the images and pass it to a function that makes it fixed (addCSS). It works fine - the images stick right where they are supposed to smoothly, but when I try to scroll up, they keep their css. I want to remove the CSS property when the wScroll is outside the range.
$('.img').each(function () {
var sectionOffset = $(this).offset().top;
var attID = $(this).attr('id');attID = $("#"+attID.toString()+"");
if (wScroll >= sectionOffset && wScroll <= (sectionOffset + sectionHeight)) {
addCSS(attID);
}
});
function addCSS(element) {
element.css({
'position': 'fixed',
'top': stickyPosition - 75,
'left': OffsetLeft
});
}
function removeCSS(element) {
element.css({
'position': '',
'top': '',
'left': ''
});
}
I tried modifying it this way but it makes it jump :(
$('.img').each(function () {
var sectionOffset = $(this).offset().top;
var attID = $(this).attr('id');attID = $("#"+attID.toString()+"");
if (wScroll >= sectionOffset && wScroll <= (sectionOffset + sectionHeight)) {
addCSS(attID);
}
else if (wScroll > (sectionOffset + sectionHeight) || wScroll < sectionOffset) {
removeCSS(attID);
}
});
I managed to get it working smoothly without using an array, but the code is a bit long and I was hoping to simplify it without losing function.
Here is a simplified version: http://codepen.io/ebevers/pen/xwbdbP
for this, I just need the squares to jump back into place. Thanks!
Try this:
// Last section and current section
var last_section = -1;
var current_section = -1;
// Scroll
jQuery(window).scroll(function(){
// Get current section
for (var i = 0; i < jQuery('.row').length; i++) {
if (jQuery(this).scrollTop() >= jQuery('.row:eq('+i+')').position().top) {
current_section = i;
}
}
// If change
if (current_section != last_section) {
removeCSS(jQuery('.row:eq('+last_section+') .img'));
addCSS(jQuery('.row:eq('+current_section+') .img'));
last_section = current_section;
}
});
http://jsfiddle.net/c4z9satw/
Another way of doing it, but without globals and it relies on explicitly set identifiers.
Added CSS:
.active {
position: fixed;
top: 100px;
left: 100px;
}
JavaScript:
$(window).scroll(function() {
var rows = $(".row");
$(".img").each(function() {
var row = false, i, l, id;
for (i = 0, l = rows.length; i < l; i++) {
id = "#" + this.id.toString();
if ($(rows[i]).find(id)[0] != undefined) {
row = rows[i];
break;
}
}
if (!row)
return false;
if ((window.scrollY >= $(row).offset().top) && (window.scrollY < $(row).offset().top + $(row).outerHeight()))
$(this).addClass("active");
else
$(this).removeClass("active");
});
});
JSFiddle: http://jsfiddle.net/w7ru130s/2/

How to add next and previous buttons to a light-box using jquery

I have the following code to develop my light-box where i need my prev and next buttons work accordingly.I have break down the code till this far. Any help or suggestion would be appreciated.
$(function () {
$('.thumbnail li').click(function () {
var index = $(this).index();
$('.light-box li:eq(' + index + ')').css('display', 'block');
});
});
DEMO
You can use the following:
$(function () {
var currentIndex = 0,
lightboxLis = $(".light-box li");
$('.thumbnail li').click(function () {
currentIndex = $(this).index();
lightboxLis.hide();
lightboxLis.eq(currentIndex).show();
//put next prev show here otherwise it won't work due to your hover
//when you hover the next prev button in your old version you no longer hover the li so can't click on the button
$('.next, .prev').show();
//add the hide of next prev to when you close the lightbox
});
$('.next').click(function() {
currentIndex++;
if (currentIndex == lightboxLis.length) {
currentIndex = 0;
}
lightboxLis.hide();
lightboxLis.eq(currentIndex).show();
});
$('.prev').click(function() {
currentIndex--;
if (currentIndex < 0) {
currentIndex = lightboxLis.length - 1;
}
lightboxLis.hide();
lightboxLis.eq(currentIndex).show();
});
});
Example

Add Class to Menu Item When Scroll

I want the menu items to look like they are selected when you are scrolling through certain sections of a single page website
I tried capturing the position of each element and store it in a variable and then apply a class when the top of that element passes the top of the page.
Java Script:
var blockone = Math.abs($("#one").position().top);
var blocktwo = Math.abs($("#two").position().top);
var blockthr = Math.abs($("#thr").position().top);
var blockfou = Math.abs($("#fou").position().top);
var blockfiv = Math.abs($("#fiv").position().top);
var blocksix = Math.abs($("#six").position().top);
function removeSelected() {
$('#menu li').removeClass('selected');
}
$("#frame").scroll( function() {
$("#menu li:nth-child(1)").addClass('selected');
var value = $(this).scrollTop();
if ( value < blocktwo ){
removeSelected();
$("#menu li:nth-child(1)").addClass('selected');
} else if (value < blockthr){
removeSelected();
$("#menu li:nth-child(2)").addClass('selected');
} else if (value < blockfou){
removeSelected();
$("#menu li:nth-child(3)").addClass('selected');
} else if (value < blockfiv){
removeSelected();
$("#menu li:nth-child(4)").addClass('selected');
} else if (value < blocksix) {
removeSelected();
$("#menu li:nth-child(5)").addClass('selected');
} else {
removeSelected();
$("#menu li:last-child").addClass('selected');
}
});
What am I missing? I have a working jfiddle here: http://jsfiddle.net/zer0ruth/pgbef/1/
The only problem is that you bind the scroll even on #frame while it should be on window.
But well, I saw that only after playing around with you code, so I have a free optimised code for you: http://jsfiddle.net/pgbef/15/.
Saving you position in array is better than having 6 var and you can had a section without changing code:
var position = [];
$('.block').each(function(){
position.push(Math.abs($(this).position().top))
})
Then your scroll function is way shorter too!
$(window).scroll( function() {
var value = $(this).scrollTop() + $('#menu').height();
$.each(position, function(i){
if(this > value){
$('.selected').removeClass('selected');
$("#menu li").eq(i-1).addClass('selected');
return false;
}
})
});

.next() not working as intended

So,
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).prev().addClass('active');
}
works fine, it adds the class "active" to this previous div of the same kind.
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).next().addClass('active');
}
However, adds the class to the next div (as i intend for it to do) for about 0.5 of a second BUT then removes it.
Here's ALL of the jQuery (as per your comments below) - Please do not comment on my horrible code organization
$(window).load(function () {
// Initial variables
var numberSlides = 0;
var currentSlide = 1;
var ready = true;
var pageWidthR = $(document).width() - 352;
var pageWidthL = $(document).width() - 352;
// Update number of slides by number of .slide elements
$('#features-slider .slide').each(function () {
numberSlides++;
});
// Go through each slide and move it to the left of the screen
var i = 0;
$($('#features-slider .slide').get().reverse()).each(function () {
if (i == 0) {
} else {
var newWidth = i * 115;
$(this).css('left', '-' + newWidth + '%');
}
i++;
});
// Animate the first slide in
$('#features-slider .slide:last-child').addClass('active').animate({
left: 0
}, 1500);
// Remove the loading message
$('#loading').fadeOut(1000, function () {
$('#loading').remove();
// Now that we're done - we can show it
$('#features-slider').show();
});
/***** Left and Right buttons *****/
/* Right */
$('#rightbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != 1) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).removeClass('active');
$(this).prev().addClass('active');
}
});
}
});
/* Left */
$('#leftbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != numberSlides) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).next().addClass('active');
$(this).removeClass('active').not($(this).next());
}
});
}
});
});
$(document).ready(function () {
// Hide the slider and show a loading message while we do stuff and the images / DOM loads - Also disable overflow on the body so no horizontal scrollbar is shown
$('body').css('overflow-x', 'hidden');
$('#features-slider').hide();
$('#loading').html('<center> <img id="loader" src="/wp-content/themes/responsive/library/images/ajax-loader.gif" /> Loading</center>');
});
RESOLVED
New left button function :
$('#leftbutton').click(function(){
var numberSlides = 0;
$('#features-slider .slide').each(function(){
numberSlides++;
});
var index = $('.slide.active').index()+1;
if( !$('.slide').is(':animated') && index != numberSlides ){
var done = false;
$('#features-slider .slide').each(function(){
if($(this).hasClass('active')){
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
}
$(this).animate({left: newLeft+'%'}, 1500);
if($(this).hasClass('active') && done == false){
$(this).next().addClass('active');
$(this).removeClass('active');
done = true;
}
});
});
If you're iterating forward through the elements, then it should be clear what's going on - you add the "active" class to the next element, and then the next iteration takes it away.
This is just a guess however as you did not post enough code for me (or anybody else) to be sure.
edit — ok now that you've updated the question, it's clear that the guess was correct. The .each() function will iterate forward through the elements. When an element has the "active" class, and the code removes it and adds it to the next element, then on the next iteration the work is undone.
Since you are referencing this and by the behavior you're describing, you are likely iterating a loop for a list of elements. As a result, you are completing the action you want but the next iteration is removing the previous changes due to your usage of removing a class and then adding the class back.
As it stands now, your code does not illustrate how this occurence can be happening.
Update:
As suspected, you seem to be looping as signified by: each(function(){. While iterating through your objects the class is being pushed forward and is not acting as desired. You are stating add the class to the next element, but remove it from the current element, and this behavior continues through your iteration.
On a side note, update your code to call removeClass() on the current object first, before adding it to the next object:
if ($(this).hasClass('active')) {
$(this).removeClass('active').next().addClass('active');
}

Categories