Javascript odd behaviour on mouse scroll up / down classes - javascript

I'm hoping a Javascript wiz can help a fellow citizen out with resolving a problem. I've a fairly straight forward function. When I scroll down by 1px I would like to apply a bounceDown class, this will run for 5 seconds and the class will then disappear for future running of the same function.
When I scroll up from that current scroll position I would like the bounceUp effect to apply. However the issue is I think the bounceUp effect only works once you scroll past the original scroll but in addition to this if the previous function is still running on it's 5 second transition then it gets jumpy as it's trying to run two classes at the same time so there almost needs to be a delay applied.
Does anyone think they can help, I'd gratefully appreciate it.
<script>
(function($){
$.fn.extend({
addTemporaryClass: function(className, duration) {
var elements = this;
setTimeout(function() {
elements.removeClass(className);
}, duration);
return this.each(function() {
$(this).addClass(className);
});
}
});
})(jQuery);
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 1) {
$(".spanner").addTemporaryClass("BounceDown", 5000);
}
else if (scroll <= 1) {
$(".spanner").addTemporaryClass("BounceUp", 5000);
}
});
</script>

What about a boolean variable that is 'true' when addTemporaryClass is running? So:
(function($){
var classAdded = false; //New
$.fn.extend({
addTemporaryClass: function(className, duration) {
classAdded = true; //New
var elements = this;
setTimeout(function() {
elements.removeClass(className);
classAdded = false; //New
}, duration);
return this.each(function() {
$(this).addClass(className);
});
}
});
})(jQuery);
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 1 /*New*/ && !classAdded /*New*/) {
$(".spanner").addTemporaryClass("BounceDown", 5000);
}
else if (scroll <= 1 /*New*/ && !classAdded /*New*/) {
$(".spanner").addTemporaryClass("BounceUp", 5000);
}
});

Related

Scroll to previous div

based on this thread I added a scroll up to next div, like this:
var f = jQuery('.p');
var nxt = f;
jQuery(".next").click(function() {
if (nxt.next('.scroller').length > 0) {
nxt = nxt.next('.scroller');
} else {
nxt = f;
}
jQuery('html,body').animate({
scrollTop: nxt.offset().top
},
'slow');
});
var f = jQuery('.p');
var prev = f;
jQuery(".previous").click(function() {
if (prev.prev('.scroller').length > 0) {
prev = prev.prev('.scroller');
} else {
prev = f;
}
jQuery('html,body').animate({
scrollTop: prev.offset().top
},
'slow');
});
So this scrolls up and down very nicely.
The problem though, is that when the user scrolls, the script doesn't notice it. That is, the user scrolls from div1 to div4, when the user click on my "next"-button, he or she gets scrolled to div2. How can I solve this?
I checked into this but I cannot combine it with the above. There must be an easier way, right?
Any help much appreciated!
Oh... I think I might have solved it myself like this:
var jQuerycurrentElement = jQuery(".scroller").first();
jQuery(".next").click(function () {
var jQuerynextElement = jQuerycurrentElement.next(".scroller");
// Check if next element actually exists
if(jQuerynextElement.length) {
// If yes, update:
// 1. $currentElement
// 2. Scroll position
jQuerycurrentElement = jQuerynextElement;
jQuery('html, body').stop(true).animate({
scrollTop: jQuerynextElement.offset().top
}, 100);
}
return false;
});
jQuery(".previous").click(function () {
var jQueryprevElement = jQuerycurrentElement.prev(".scroller");
// Check if previous element actually exists
if(jQueryprevElement.length) {
// If yes, update:
// 1. $currentElement
// 2. Scroll position
jQuerycurrentElement = jQueryprevElement;
jQuery('html, body').stop(true).animate({
scrollTop: jQueryprevElement.offset().top
}, 100);
}
return false;
});
The above is based on this.
The only problem here is that when parts of a div is scrolled into view, the next and previous buttons sometimes behave strange. For example, when being between div2 and div3 and div 3 is most visible, the previous click can take the user back to div1, which feels not so logical. Can we adjust this somehow? I suppose I would have to do something with the offset but I am unsure.

Shopify javascript/jQuery condition for scrollTop not working

I am making a javascript/jQuery condition to make the header drop down once a user clicks a button ("Buy Now") only when they can't see the header (200px down). My problem is that when the user scrolls more than 200px even if they scroll back up the code still exectues. Here is my code, thanks.
$(function() {
$(document).scroll(function() {
var y = $(window).scrollTop();
console.log(y);
if (y >= 200) {
$('.product__add-to-cart-button').click(function() {
// your statements;
$(".site-header").addClass("site-header--fixedd").removeClass("site-header--transparent");
$("#crazy-pineapple, #coco-twist, #crunchy-joy, #nutty-chia").css('margin-top', 143);
setTimeout(function() {
$(".site-header__cart-bubble").removeClass("bubblenormal").addClass("bubblevisible");
}, 300);
setTimeout(function() {
$(".site-header__cart-bubble").removeClass("bubblevisible").addClass("bubblenormal");
}, 700);
setTimeout(function() {
$(".site-header").removeClass("site-header--fixedd");
$(".site-header").addClass("site-header--fixeddd");
}, 1200);
setTimeout(function() {
$("#crazy-pineapple, #coco-twist, #crunchy-joy, #nutty-chia").css('margin-top', 0);
$(".site-header").addClass("site-header--transparent");
$(".site-header").removeClass("site-header--fixedd");
$(".site-header").removeClass("site-header--fixeddd");
}, 1600);
});
}
});
});
There are a few big NO's in your code.
You should NEVER add a event handler in a scroll/resize function! Why? Because you keep stacking them once you do the resizing/scrolling.
At the moment you apply multiply click events to .product__add-to-cart-button which I assume you don't want.
In addition there is no point to your scroll event at the moment. You can just create an if statement inside the click event if the scrollTop() is bigger than 200 and you can remove the scroll event all together.
In addition you must get the habit of caching objects if you plan to use them multiply times. Any object used more than once must be cached.
And here is how should your code look if we take in consideration all of the above remarks:
$(function() {
var $win = $(window);
var $siteHeader = $(".site-header");
var $siteHeaderCartBuble = $(".site-header__cart-bubble");
var $group = $("#crazy-pineapple, #coco-twist, #crunchy-joy, #nutty-chia");
$('.product__add-to-cart-button').on('click',function() {
if ($win.scrollTop() <= 200) {
return false
};
$siteHeader
.addClass("site-header--fixedd")
.removeClass("site-header--transparent");
$group.css('margin-top', 143);
setTimeout(function() {
$siteHeaderCartBuble
.removeClass("bubblenormal")
.addClass("bubblevisible");
}, 300);
setTimeout(function() {
$siteHeaderCartBuble
.removeClass("bubblevisible")
.addClass("bubblenormal");
}, 700);
setTimeout(function() {
$siteHeader
.removeClass("site-header--fixedd")
.addClass("site-header--fixeddd");
}, 1200);
setTimeout(function() {
$group.css('margin-top', 0);
$siteHeader
.addClass("site-header--transparent")
.removeClass("site-header--fixedd")
.removeClass("site-header--fixeddd");
}, 1600);
});
})

Can you target an element by its dynamically changing opacity?

Through the use of a function in jQuery, along with my HTML & CSS, I have a series of different colored divs that change their opacity to appear as though the opaque div moves from left to right. I want the user to be able to click a red button to stop the animation on a square of his/her choosing. Right now I can get the animation to stop (albeit after it finishes its queued animations), but I am having trouble getting the square that has its opacity at 1 (at the time of the button click) stay at opacity 1. Any help would be greatly appreciated.
Here is a jsfiddle http://jsfiddle.net/seifs4/krm6uenj/
$(document).ready(function () {
$.fn.extend({
brighten: function(){
$(this).fadeTo(150, 1);
}
});
$.fn.extend({
fade: function(){
$(this).fadeTo(150, 0.2);
}
});
function animateSequence() {
$('.game-square').each(function (i) {
$(this).delay((i++) * 145).brighten();
$(this).delay((i++) * 5).fade();
});
}
animateSequence()
var interval=setInterval(animateSequence, 1700);
$('#red-button').click(function(){
$('.game-square').each(function(){
if ($('.game-square', this).not().css('opacity') == 0.2){
$(this).css('opacity', '1');
}
});
clearInterval(interval);
});
});
You maybe need something like this:
function animateSequence(){
this.current = 0;
this.squares = $(".game-square");
this.animate = function(){
this.squares.eq(this.current).fadeTo(150, 1, function(){
$(this).fadeTo(150, 0.2)
});
this.current = this.current >= this.squares.length - 1 ? 0 : this.current + 1;
};
this.start = function(){
this.running = setInterval(this.animate.bind(this), 150)
};
this.stop = function(){
this.running = clearInterval(this.running);
this.squares.eq(this.current).stop().css("opacity",1);
alert("Current color: " + this.squares.eq(this.current).attr("class"))
}
}
Demo
This is the advantage of working with objects, a way very readable, simple and orderly.
I will take a different and less complex approach. Perhaps it has even better performance.
Demo http://jsfiddle.net/LkatLkz2/8/
This is the whole code. I use css for animation effect, and class changing opacity.
var sqrs = $('.game-square'),
len = sqrs.length,
i=0,
looping = true;
setInterval(function(){
if (!looping) return;
sqrs.removeClass('full').eq(i).addClass('full');
i = ++i % len;
},400);
$("#red-button").click(function () {
looping = !looping;
});
The JQuery .stop() function help you to stop the animation. I know this is not the best solution for your problem because your opacity stay "1" only a short time.
$('#red-button').click(function(){
clearInterval(interval);
$('.game-square').stop();//this stop the animation
$('.game-square').each(function(){
if ($(this).not().css('opacity') > '0.2'){// I changed this logic
$(this).css('opacity', '1');
}
});
});

Animate an element in real time

I need to know the position of an img in real time in order to change its position while is going up or down. The target is animate it to the bottom 40px at the beginning and animate it to the top later.
My code up to now is the following:
var pos = $('header img').offset().top;
if( pos == 0) {
$('header img').animate({"top": "+=40px"}, 6000);
}else{
$('header img').animate({"top": "-=40px"}, 6000);
}
Any idea?
You can use progress option to detect the position live. I also made some changes so you don't have to use so much duplicated code:
$('#startAnimation').on('click', function () {
var pos = $('header #img').offset().top;
if (pos == 0) {
doAnimate("+=40px");
} else {
doAnimate("-=40px");
}
});
function doAnimate(to) {
$('header #img').animate({
top: to
}, {
duration: 6000,
progress: function (promise) {
console.log('offset top: ' + $('header #img').offset().top);
}
});
}
Fiddle: http://jsfiddle.net/z3jk1g0z/
You could also change it to use start and complete options in animate. More information: http://api.jquery.com/animate/
EDIT: wrong Fiddle

Slow/unresponsive animation with jQuery animation

I am writing a small jQuery function and I seem to be having trouble.
What I am trying to do here is when the user scrolls down the page by 90px, a div tag should animate down (from top:-50px to top:0), and vice-versa when they scroll back to the top of the page.
The problem I am having is that the animation seems to be very slow and unresponsive at times. I test in 3 different browsers and different computers but I am having no joy.
Here is my code:
// Show div
var scrollValue = "90";
// Animate functions
var showHead = function (){
$(".element").animate({top: "0"}, 250);
}
var hideHead = function (){
$(".element").animate({top: "-50px"}, 250);
}
$(window).scroll(function() {
if ($(this).scrollTop() > scrollValue) {
showHead();
} else {
hideHead();
}
});
The .element properties:
.element { positoin:fixed; top:-50px; }
Could anyone figure out why my code the hide/showHead functions are so sloppy?
Thanks,
Peter
The scroll event is triggered several times and even though it is rate-limited it keeps being a rather intensive operation. Actually, you may be queuing several animations and the fx stack may be growing very quickly.
One possibility you can try is stopping all previous animations before triggering a new one. You can do this by using .stop().
$(".element").stop().animate({top: "0"}, 250);
The .stop() function also provides some other options which you can use to tweak it even more.
Try this one :
$(window).scroll(function() {
if (window.scrollY > scrollValue) {
showHead();
} else {
hideHead();
}
});
scroll events occurred many time durring user scrolling.
You need to check if your animation is in progress before starting the animation again.
Try this :
// Show div
var scrollValue = "90";
var inProgress = false;
// Animate functions
var showHead = function () {
if(inProgress)
return false;
//Animate only if the animation is not in progress
inProgress = true;
$(".element").animate({
top: "0"
},250,function(){
inProgress = false; //Reset when animation is done
});
}
var hideHead = function () {
if(inProgress)
return false;
//Animate only if the animation is not in progress
inProgress = true;
$(".element").animate({
top: "-50px"
}, 250,function(){
inProgress = false; //Reset when animation is done
});
}
$(window).scroll(function () {
if ($(this).scrollTop() > scrollValue) {
showHead();
} else {
hideHead();
}
});
Assuming you have position:fixed (or some other sort of styling making the bar visible when necessary):
var scrollheight = 90;
var $el = $('.element');
function showHead(){
$el.stop().animate({
top: '0px'
}, 250);
}
function hideHead(){
$el.stop().animate({
top: '-50px'
}, 250);
}
$(window).scroll(function(){
if ($(window).scrollTop() > scrollheight){
showHead();
}else{
hideHead();
}
});
example: http://jsfiddle.net/L4LfL/
try using queue: false and as Alexander said use .stop()
here jsfiddle
http://jsfiddle.net/hwbPz/

Categories