JQuery animate() not working as intended in conjunction with removeClass() - javascript

I've been trying to implement my own carousel as a way to teach myself javascript and have come across a problem where the animation prior to my removeClass call doesn't occur but the animation for bringing in the next element works as intended.
I realize this sounds quite vague so I've reproduced my problem with jsfiddle: http://jsfiddle.net/f57N3/
I've also included the relevant code below. Any help would be greatly appreciated!
HTML:
<div class="button-container">
<button id="b2">Next</button>
</div>
<div class="container">
<div class="box active-box" id="box1">
thingy
</div>
<div class="box" id="box2">
other thingy
</div>
<div class="box" id="box3">
another thingy
</div>
</div>
CSS:
.box{
display: none;
position: relative;
opacity: 0;
width: 350px;
height: 200px;
background-color: blue;
color: white;
border: 5px solid black;
}
.active-box{
display: block;
opacity: 1;
}
.container{
width: 850px;
height: 500px;
margin: 0px auto;
background-color: #003399;
}
Javascript:
// Functionality for 'Next' button
$("#b2").click(function(){
var thisBox = $(".active-box");
var nextBox = thisBox.next();
if(nextBox.length == 0){
nextBox = $(".box").first();
}
// Set pre-animation conditions
thisBox.css("margin-left", "0px");
thisBox.css("opacity", "1");
// Animate this box and remove active class
thisBox.animate({marginLeft: "-=300px", opacity: "0"}, 800).removeClass("active-box");
//Set pre-animation conditions
nextBox.css("margin-left", "300px");
nextBox.css("opacity", "0");
// Animate this box and add active class
nextBox.animate({marginLeft: "-=300px", opacity: "1"}, 800).addClass("active-box");
});
Any help would be greatly appreciated!

Animate has a complete function you can pass to it http://api.jquery.com/animate/
What was happening was that the removeClass was firing straight away. only removing in the complete seems to solve that. Also moving the following into that makes it run smoother.
// Functionality for 'Next' button
$("#b2").click(function () {
var thisBox = $(".active-box");
var nextBox = thisBox.next();
if (nextBox.length == 0) {
nextBox = $(".box").first();
}
// Set pre-animation conditions
thisBox.css("margin-left", "0px");
thisBox.css("opacity", "1");
// Animate this box and remove active class
thisBox.animate({
marginLeft: "-=300px",
opacity: "0"
}, 800, 'swing', function () {
thisBox.removeClass("active-box");
//Set pre-animation conditions
nextBox.css("margin-left", "300px");
nextBox.css("opacity", "0");
// Animate this box and add active class
nextBox.animate({
marginLeft: "-=300px",
opacity: "1"
}, 800).addClass("active-box");
})
});
Demo: http://jsfiddle.net/robschmuecker/f57N3/1/

You can do this maybe :
Javascript :
$("#b2").click(function(){
var thisBox = $(".active-box");
var nextBox = thisBox.next();
if(nextBox.length == 0){
nextBox = $(".box").first();
}
// Set pre-animation conditions
thisBox.css("margin-left", "0px");
thisBox.css("opacity", "1");
// Animate this box and remove active class
thisBox.animate({marginLeft: "-=300px", opacity: "0"}, 800);
thisBox.removeClass("active-box");
//Set pre-animation conditions
nextBox.css("margin-left", "300px");
nextBox.css("opacity", "0");
// Animate this box and add active class
nextBox.animate({marginLeft: "-=300px", opacity: "1"}, 800);
nextBox.addClass("active-box");
});

Related

Toggle method without show/hide option

How to use .toggle() method but not for show and hide purposes?
For example, when I click on a certain div I would like to animate it's position
$(div).animate({"left":"+=50px"}); and then on the second click to return the div on the same position $(div).animate({"left":"-=50px"}).
I know there is other solution but I would like to achieve this with .toggle() without hiding an showing the div. Any ideas?
$("#myDiv").toggle(function() {
$(this).stop().animate({
left:"+=50"
}, 500);
}, function() {
$(this).stop().animate({
left:"-=50"
}, 500);
});
#myDiv{
background-color:black;
width:100px;
height:100px;
position:absolute;
left:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div id="myDiv"></div>
hope this answer your question. However, jQuery 1.9 and newer do not allow this feature.
there is no toggle function using click since 1.9 . But you can still doing this using two ways:
for more explaination
$(function(){
//basic method
var clicked = false;
$('#mydiv1').click(function(){
if(clicked){
clicked = false;
$(this).animate({"left":"+=50px"});
}else{
clicked=true;
$(this).animate({"left":"-=50px"});
}
});
//create new function like old built-in function
$.fn.clickToggle = function(func1, func2) {
var funcs = [func1, func2];
this.data('toggleclicked', 0);
this.click(function() {
var data = $(this).data();
var tc = data.toggleclicked;
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % 2;
});
return this;
};
$('#mydiv2').clickToggle(function(){
$(this).animate({"left":"+=50px"});
}, function(){
$(this).animate({"left":"-=50px"});
});
});
#mydiv1{
background-color: yellow;
width: 50px;
height: 50px;
position: absolute;
left: 100px;
}
#mydiv2{
background-color: blue;
width: 50px;
height: 50px;
position: absolute;
left: 200px;
top: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="mydiv1"></div>
<div id="mydiv2"></div>
</div>

how to create a sliding menu which will fill the window width except by puller button width?

I am trying to create a sliding menu which will fill the window width minus the puller button width. I want the menu out of the window when web page load and there is a button which will go left when the page loads. When user clicks on the button the menu should come to window and button goes right.
I have created an animation video here which will show you what I want.
In the jsfiddle the menu just fades out, But I want the menu to slide from left to right when clicked on button with .puller class.
See the code at jsfiddle
Demo on jsfiddle
$(document).ready(function() {
var stickyNavTop = ($('.container')).offset().top;
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.container').addClass('fixed');
} else {
$('.container').removeClass('fixed');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
}).resize(function() {
stickyNav();
}).load(function() {
stickyNav();
});
$(".dropdown").click(function() {
$(".dpitem").slideToggle(300);
});
var calcWidth = function() {
var pullerDimensions = $('.puller').width();
$('#cpcc,.dpitem').width($(window).width() - pullerDimensions);
}
$(document).ready(function() {
calcWidth();
});
$(window).resize(function() {
calcWidth();
}).load(function() {
calcWidth();
});
var cPcc = document.getElementById ("cpcc");
var cpHeight = function() {
var cpBtnHolder = $(cPcc).height();
$('.content').css("padding-top",cpBtnHolder);
}
setInterval(function() {
cpHeight();
calcPHeight();
pp();
}, 0)
var calcPHeight = function() {
var toolsDimensions = $('#cpcc').height();
$('.puller').height(toolsDimensions);
$('.puller').css("line-height",toolsDimensions +"px");
}
$(document).ready(function() {
calcPHeight();
});
$(window).resize(function() {
calcPHeight();
}).load(function() {
calcPHeight();
});
var Pwidth = $('#cpcc').width();
var PSpce = $(window).width()-Pwidth;
$(".puller").click(function() {
$(".container").toggle( function() {
$(".container").css({
transform: "translate3d("+"-"+Pwidth+"px, 0, 0)"
});
}, function () {
$(".container").css({
transform: "translate3d(-0, 0, 0)"
});
});
});
});
Calc is your friend. You can use that along with 'transition' to achieve the intended effect. Check out this simplified example.
http://codepen.io/anon/pen/gPBQOb
Good practice is to toggle a class which will override the position property in this case left. It should also toggle your chevron image to point left and right.
Your example is using a lot of js calculations and has to recalculate with window size changes. This example uses js only to toggle a css class on click and the rest in managed purely with css. Much simpler in my opinion.
HTML
<div class="maincontent"></div>
<div class="menu">
<div class="button"></div>
</div>
CSS
.maincontent{
background-color: green;
height: 2000px;
width: 100%;
}
.menu{
background-color: red;
width: 100%;
height: 200px;
position: fixed;
top: 0px;
left: 0px;
transition: left 1s;
}
.menu.collapse{
left: calc(-100% + 30px)
}
.button{
background-color: yellow;
height: 100%;
width: 30px;
position: absolute;
right: 0px;
}
JS
$('.button').click(
function(){
$('.menu').toggleClass('collapse')
})

Count back percentage using JQuery

I have the code below where I'd like to the numbers count back to 0% once hover the object out. Also I can't figure our how to make the value disappear again as it was on load. Could you please help me solve this.
Thanks in advance.
HTML
<div class="container">
<div class="fill" data-width="80%"></div>
</div>
<div class="container">
<div class="fill" data-width="50%"></div>
</div>
CSS
.container {
position: relative;
width: 300px;
height: 30px;
background-color: blue;
margin: 10px auto;
}
.fill {
height: 100%;
width: 0;
background-color: red;
line-height: 30px;
text-align: left;
z-index: 1;
text-align: right;
}
JQuery
$(function() {
$('.container').hover( function(){
var width=$(this).find(".fill").data('width');
$(this).find(".fill").animate({ width: width }, {
duration:800,
step: function(now, fx) {
$(this).html(Math.round(now) + '%');
}
});
},
function(){
$(this).find(".fill").animate({ "width": "0px" }, 800);
});
});
jsFiddle http://jsfiddle.net/zp8pe069/
jsBin demo
CSS: set overflow: hidden to .fill to prevent the text being visible after the animation ends.
HTML: remove % from the data attribute
JS and here you go. all you need:
$('.container').hover(function( e ){
var $fill = $(this).find(".fill");
var width = $fill.data('width');
$fill.stop().animate({width: e.type=="mouseenter" ? width+"%" : "0%" }, {
duration : 800,
step : function(now) {
$(this).html(Math.round(now) + '%') ;
}
});
});
Note also the use of the .stop() method, if you hover multiple time hysterically :) it'll prevent endless animations.

Prevent animation during animation

I'm trying to do an animation, everything works fine but I can't seem to prevent user from clicking during the animation and breaking the page layout.
I have managed to stop user when the divs are moving but I can't prevent when one div is expanded.
This is my fiddle: http://fiddle.jshell.net/p2fo4ek0/18/
<div class="internet_wrap">
<div class="internet tel" id="off_wrap">
<div class="package" id="one">
<div class="inner_package">
<div class="title">title</div>
</div>
</div>
<div class="package" id="two">
<div class="inner_package">
<div class="title">title</div>
</div>
</div>
<div class="package" id="three">
<div class="inner_package">
<div class="title">title</div>
</div>
</div>
</div>
</div>
var animating = false;
var clickedDiv, prevDiv, distance;
$('#off_wrap').on('click', '.package', function (e) {
e.stopPropagation();
if(animating == false) {
animating = true;
clickedDiv = $(this).closest('.package'),
prevDiv = $("#off_wrap > :first-child"),
distance = clickedDiv.offset().left - prevDiv.offset().left;
if (!clickedDiv.is(":first-child")) {
$.when(clickedDiv.animate({
left: -distance
}, 2000),
prevDiv.animate({
left: distance
}, 2000)).done(function () {
prevDiv.css('left', '0px');
clickedDiv.css('left', '0px');
//clickedDiv.css('width', $(window).width() - (clickedDiv.offset().left * 2));
clickedDiv.css('z-index', '10000000');
clickedDiv.css('overflow', 'visible');
clickedDiv.find(".inner_package").animate({width: 260}, 2000); //regullo kte
prevDiv.insertBefore(clickedDiv);
clickedDiv.prependTo("#off_wrap");
animating = false;
});
} else {
clickedDiv.css('z-index', '1000');
clickedDiv.find(".inner_package").css('transition', 'all 2s ease-in');
clickedDiv.find(".inner_package").css('width', '260px');
}
}
});
$(document).click(function() {
animating = false;
if(animating == false) {
clickedDiv.css('z-index', '1');
clickedDiv.find(".inner_package").css('transition', 'all 2s ease-in');
clickedDiv.find(".inner_package").css('width', '60px');
animating = false;
}
});
.internet {
text-align:center;
background: none repeat scroll 0% 0% rgba(248, 0, 140, 0.5);
padding-bottom:10px;
position: relative;
}
.internet .package {
display: inline-block;
/*border: 1px solid #FFFC00;*/
height: 60px;
width: 60px;
border-radius: 30px;
margin: 20px;
background:#fff;
color: rgba(0, 178, 248, 1);
position: relative;
cursor: pointer;
vertical-align:middle;
}
.inner_package {
display: inline-block;
width: 60px;
transition: all 2s ease-in;
background: #fff;
border-radius: 30px;
height: 60px;
}
It looks like you've put a lot of code in already attempting to fix the issue. I'm also a little confused as to what the issue is, as your jsFiddle doesn't give me trouble with clicking during the animation. Perhaps it's only certain situations you're speaking of.
Either way, I saw this.
$(document).click(function() {
animating = false;
if(animating == false) {
clickedDiv.css('z-index', '1');
clickedDiv.find(".inner_package").css('transition', 'all 2s ease-in');
clickedDiv.find(".inner_package").css('width', '60px');
animating = false;
}
});
That animating = false; both before the if statement and inside the if statement function seems redundant, and I suspect one of them needs to read animating = true; Let me know if that fixes your problem or not.
UPDATE: While I don't understand the animations themselves, I can say this. Your using animation as a control against multiple animations running. You have a statement that seems like it might be your problem.
if(animating == false) {
animating = true;
//do stuff
animating = false;
}
This may be your problem. Try getting more specific logic. like
if(animatingOne == false && animatingTwo == false && animatingThree == false) {
//logic to find out which animation is triggered
//turn the appropriate animation variable to true
//turn if off when done
}
If this doesn't work, keep playing with logic. I suspect that one variable animating is unable to accommodate the complexity of what you're doing.

Show/hide elements when other elements change class - jQuery

I have a content wrapper which has several sections in it, each section with a different id.
The sections can be accessed with a menu navigation which triggers a transform operation who uses translate3d to go between the sections, on horizontal, using an class named active to show which section should be displayed.
I placed two anchors with absolute position towards the content wrapper, something like arrows in a slideshow one on the left and one on the right.
Here is how the code looks
<div id="wrapper">
<a class="left-arrow" href="#"></a>
<a class="right-arrow" href="#"></a>
<header>
<nav id="main">
<a class="active" href="#!/one">one</a>
two
three
four
</nav>
</header>
<div class="content_wrapper" style="display: block; transform: translate3d(0px, 0px, 0px);">
<section id="one" class="active">content one</section>
<section id="two">content two</section>
<section id="three">content three</section>
<section id="four">content four</section>
</div>
</div>
the CSS
.left-arrow{ background: url('../img/left-arrow.png') left top no-repeat; height: 64px; width: 16px; display: block; position: absolute; top: 180px; left: 0; z-index: 10;}
.right-arrow{ background: url('../img/right-arrow.png') right top no-repeat; height: 64px; width: 16px; display: block; position: absolute; top: 180px; right: 0; z-index: 10;}
My problem is that I don't know how to hide the left arrow when the first section has the class active, and the right arrow when the last section has the class active. I tried with on and change but obviously I failed, I'm a rookie to jQuery element and event manipulation. Which selector should I use and which event? Can someone please give me some directions?
here is the jQuery part
(function (e) {
var r = !1;
e(window).on("hashchange", function (i) {
var s = e("section#" + document.location.hash.replace("#!/", ""));
if (!r && !s.hasClass("active")) {
r = !0;
e('nav#main a[href="' + document.location.hash + '"]').addClass("active").siblings().removeClass("active");
e("section.active").animate({
scrollTop: 0
}, 300);
e("section.active").children("footer").children("div.box").hide();
s.addClass("active").siblings().removeClass("active");
if (Modernizr.csstransitions && Modernizr.csstransforms3d) e("div.content_wrapper").transition({
transform: "translate3d(-" + 1e3 * s.index() + "px, 0, 0)"
}, {
duration: 800,
easing: "cubic-bezier(0.770, 0.000, 0.175, 1.000)"
}, function () {
r = !1
});
else {
e("div.content_wrapper").animate({
left: "-" + 1e3 * s.index() + "px"
}, {
duration: 800,
queue: !0
});
r = !1
}
}
});
})
Would add a class to all the sections so you can add or remove and not have to focus on specific ID being first/last
<section id="one" class="content active">content one</section>
function setArrowState(){
var $content=$('.content');
$('.left-arrow')[ $content.first().is('.active') ? 'hide' :'show' ]();
$('.right-arrow')[ $content.last().is('.active') ? 'hide' :'show' ]();
}
$(function(){
/* set arrows on page load*/
setArrowState();
});
EDIT: In haschange code shown, call setArrowState() on line after .addClass("active").siblings().removeClass("active");
You just need to have a variable know which is the element selected, so you can remove the class, and then set on the click event to add the class.
var menu1 = document.querySelector('#main1');
var menu2 = document.querySelector('#main2');
// etc
var selected = menu1;
var activeClass = function()
{
$(selected).removeClass('active');
$(this).addClass('active');
selected = this;
};
menu1.onclick = activeClass;
menu2.onclick = activeClass;

Categories