How to stop jquery animate at onclick? - javascript

I'm new in jquery, I don't know much about it, but I need it because I'm building a template...Here is situation, I have a div which I want to slide in to page ( from outside, top) when I click on link, and when I click anywhere else on the page to slide out... This is what I have:
var tmpl_name = '<?php echo $this->template ?>';
jQuery(document).ready(function() {
jQuery('#link').click(function() {
var topy = jQuery('#div');
topy.delay(0).animate({
top: parseInt(topy.css('top')) == 0 ? -topy.outerWidth() : 10
},500, 'easeInOutCirc', function() {jQuery(this);});
});
});
...and it works well,when I click on link div slide in to page, but I don't know how to achieve when I click anywhere else on page to slide out the div, I have tried to add:
jQuery('body').click(function() {
var topy = jQuery('#div');
topy.delay(0).animate({
top: parseInt(topy.css('top')) == 0 ? -topy.outerWidth() : -500
},1000, 'easeInOutCirc', function() {jQuery(this);});
});
...but problem is when I click on link to slide in div, div goes in and out of page ( probably because link is also in body and this second part of code affects it too.
Thanks for your time...Best regards

try:
jQuery(document).ready(function() {
jQuery('#link').click(function(e) {
e.preventDefault();
var topy = jQuery('#div');
topy.delay(0).animate({
top: parseInt(topy.css('top')) == 0 ? -topy.outerWidth() : 10
},500, 'easeInOutCirc', function() {jQuery(this);});
});
});
To kill the event propagation to the document object

The .stop() function can be chained at the beginning of your call as well at the end to stop any animations.
i.e. $("#element").stop().bounce().stop();

Related

Back to Top Button Issue (Potentially)?

I've got a back to top button that shows up on my webpage that I'm working on. When you scroll down and sometimes when it's clicked it jumps to the top and then jumps back to where you were on the page and then smoothly scrolls to the top like it's supposed to. Keep in mind that it does not do this all the time. Would this just be a lag or glitch issue or if there some error in my script?
$(function(){
$(document).on( 'scroll', function(){
if ($(window).scrollTop() > 615) {
$('.ion-android-arrow-dropup-circle').addClass('show');
} else {
$('.ion-android-arrow-dropup-circle').removeClass('show');
}
});
$('.ion-android-arrow-dropup-circle').on('click', scrollToTop);
});
function scrollToTop() {
verticalOffset = typeof(verticalOffset) != 'undefined' ? verticalOffset : 0;
element = $('body');
offset = element.offset();
offsetTop = offset.top;
$('html, body').animate({scrollTop: offsetTop}, 500, 'linear');
};
Searched 40+ questions and couldn't find an answer. Only saying this because if you don't and somebody finds one they always say, "You should have looked before asking." I see it all the time.
ANSWER TO MY OWN QUESTION
After going so long without responses I had moved on and decided not to worry about this issue at that time. Today, I was working on a different site using the same jQuery script and was having the same problem. I decided to try and fix it myself since I couldn't find help on the issue.
The solution was simple! I don't know how I missed it the first time around. All I did is take the above code and add one function to it:
$('.ion-android-arrow-dropup-circle').click(function(event) {
event.preventDefault()
});
I forgot all about needing to remove the default action of clicking a link which is jumping to the destination. It now works perfectly smooth and looks great, just like I wanted to begin with!
My fully updated script for your reference:
$(function(){
$(document).on( 'scroll', function(){
if ($(window).scrollTop() > 50) {
$('.ion-eject').addClass('show');
} else {
$('.ion-eject').removeClass('show');
}
});
$('.ion-eject').click(function(event) {
event.preventDefault()
});
$('.ion-eject').on('click', scrollToTop);
});
function scrollToTop() {
verticalOffset = typeof(verticalOffset) != 'undefined' ? verticalOffset : 0;
element = $('body');
offset = element.offset();
offsetTop = offset.top;
$('html, body').animate({scrollTop: offsetTop}, 200, 'linear');
};

Wow.js repeat animation every time you scroll up or down

I'm pretty new with Jquery. I would like that my animations with Wow.js could run more than once time. For instance: i scroll to the bottom of my page and see all the animations, and if i scroll back to the top i see again the animations like when you scroll down. I hope that I explained myself. I have already seen many websites that repeats the animations on theirs pages but unfortunately I don't remember them and I can't provide a link.
I have already tried this:
$(window).scroll(function(){
new WOW().init();
}
But it repeat the animations also if you scroll a little and it's pretty ugly to see. I try to explain me better: I have a with my animation and if it is focused the animation is triggered, then i scroll down to another div and the previous div is no more visible(not in the window viewport), then again i scroll back to my div with animation and the animation is triggered again.
I'm sorry for this messy question but I really don't know how to explain it.
Thanks in advance!
This example by Benoît Boucart shows how the animation can be "reset" when the user scrolls out of view and back in. The key here is the second function that removes the animation css class when the element scrolls out of view. I wish WOW.js would implement this, but they've indicated that they don't plan to.
http://codepen.io/benske/pen/yJoqz
Snippet:
// Showed...
$(".revealOnScroll:not(.animated)").each(function () {
var $this = $(this),
offsetTop = $this.offset().top;
if (scrolled + win_height_padded > offsetTop) {
if ($this.data('timeout')) {
window.setTimeout(function(){
$this.addClass('animated ' + $this.data('animation'));
}, parseInt($this.data('timeout'),10));
} else {
$this.addClass('animated ' + $this.data('animation'));
}
}
});
// Hidden...
$(".revealOnScroll.animated").each(function (index) {
var $this = $(this),
offsetTop = $this.offset().top;
if (scrolled + win_height_padded < offsetTop) {
$(this).removeClass('animated fadeInUp flipInX lightSpeedIn')
}
});
If a user wants to repeat the animation on both the events i.e.
onScrollUp
onScrollDown
then this will be a good solution for it:
First create an addBox function, it will help to push new elements into the WOW boxes array.
WOW.prototype.addBox = function(element){
this.boxes.push(element);
};
Then use jQuery and scrollspy plugin that helps to detect which element is out of the view and then push WOW as:
$('.wow').on('scrollSpy:exit',function(){
var element = $(this);
element.css({
'visibility' : 'hidden',
'animation-name' : 'none'
}).removeClass('animated');
wow.addBox(this);
});
Solution Courtesy: ugurerkan
Answer by #vivekk is correct I m just adding a working example so that people can easily get this
see the Demo fiddle
<script>
// Repeat demo content
var $body = $('body');
var $box = $('.box');
for (var i = 0; i < 20; i++) {
$box.clone().appendTo($body);
}
// Helper function for add element box list in WOW
WOW.prototype.addBox = function(element) {
this.boxes.push(element);
};
// Init WOW.js and get instance
var wow = new WOW();
wow.init();
// Attach scrollSpy to .wow elements for detect view exit events,
// then reset elements and add again for animation
$('.wow').on('scrollSpy:exit', function() {
$(this).css({
'visibility': 'hidden',
'animation-name': 'none'
}).removeClass('animated');
wow.addBox(this);
}).scrollSpy();
</script>

Using a jquery slider for text instead of images?

This may be a little too specific, but I have a jquery slider that I am using <p> classes instead of images to cycle through customer quotes. Basically the problem I am running into right now is when it is static and non moving (JS code is commeneted out) they are aligned how I want them to be. As soon as the JS is un commented, they stretch out of view and you just see a white box?
Any ideas?
How I want each panel to look like:
jsfiddle
So I sort of made this my Friday project. I've changed a whole lot of your code, and added a vertical-align to the quotes and authors.
Here's the fiddle http://jsfiddle.net/qLca2fz4/49/
I added a whole lot of variables to the top of the script so you could less typing throughout.
$(document).ready(function () {
//rotation speed and timer
var speed = 5000;
var run = setInterval(rotate, speed);
var slides = $('.slide');
var container = $('#slides ul');
var elm = container.find(':first-child').prop("tagName");
var item_width = container.width();
var previous = 'prev'; //id of previous button
var next = 'next'; //id of next button
Since you used a % based width I'm setting the pixel widths of the elements in case the screen is reszed
slides.width(item_width); //set the slides to the correct pixel width
container.parent().width(item_width);
container.width(slides.length * item_width); //set the slides container to the correct total width
As you had, I'm rearranging the slides in the event the back button is pressed
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
I combined the prev and next click events into a single function. It checks for the ID of the element targeted in the click event, then runs the proper previous or next functions. If you reset the setInterval after the click event your browser has trouble stopping it on hover.
//if user clicked on prev button
$('#buttons a').click(function (e) {
//slide the item
if (container.is(':animated')) {
return false;
}
if (e.target.id == previous) {
container.stop().animate({
'left': 0
}, 1500, function () {
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
});
}
if (e.target.id == next) {
container.stop().animate({
'left': item_width * -2
}, 1500, function () {
container.find(elm + ':last').after(container.find(elm + ':first'));
resetSlides();
});
}
//cancel the link behavior
return false;
});
I've found mouseenter and mouseleave to be a little more reliable than hover.
//if mouse hover, pause the auto rotation, otherwise rotate it
container.parent().mouseenter(function () {
clearInterval(run);
}).mouseleave(function () {
run = setInterval(rotate, speed);
});
I broke this in to its own function because it gets called in a number of different places.
function resetSlides() {
//and adjust the container so current is in the frame
container.css({
'left': -1 * item_width
});
}
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
And here's your rotation timer.
function rotate() {
$('#next').click();
}
It took me a little bit, but I think I figured out a few things.
http://jsfiddle.net/qLca2fz4/28/
First off, your console was throwing a few errors: first, that rotate wasn't defined and that an arrow gif didn't exist. Arrow gif was probably something you have stored locally, but I changed the 'rotate' error by changing the strings in the code here to your actual variables.
So, from:
run = setInterval('rotate()', speed);
We get:
run = setInterval(rotate, speed);
(No () based on the examples here: http://www.w3schools.com/jsref/met_win_setinterval.asp)
But I think a more important question is why your text wasn't showing up at all. It's because of the logic found here:
$('#slides ul').css({'left' : left_value});
You even say that this is setting the default placement for the code. But it isn't..."left_vaule" is the amount that you've calculated to push left during a slide. So if you inspect the element, you can see how the whole UL is basically shifted one slide's worth too far left, unable to be seen. So we get rid of 'left_value', and replace it with 0.
$('#slides ul').css({'left' : 0});
Now, there's nothing really handling how the pictures slide in, so that part's still rough, but this should be enough to start on.
Let me know if I misunderstood anything, or if you have any questions.
So, a few things:
1) I believe you are trying to get all of the lis to be side-by-side, not arranged up and down. There are a few ways to do this. I'd just make the ul have a width of 300%, and then make the lis each take up a third of that:
#slides ul {
....
width: 300%;
}
#slides li {
width: calc(100% / 3);
height:250px;
float:left;
}
2) You got this right, but JSFiddle automatically wraps all your JS inside a $(document).ready() handler, and your function, rotate needs to be outside, in the normal DOM. Just change that JSFiddle setting from 'onload' to 'no wrap - in head'
3) Grabbing the CSS value of an element doesn't always work, especially when you're dealing with animating elements. You already know the width of the li elements with your item_width variable. I'd just use that and change your code:
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
$('#slides ul').animate({'left' : left_indent}, 1500, function () {
to:
$('#slides ul').stop().animate({'left' : -item_width * 2}, 1500, function () {
4) Throw in the .stop() as seen in the above line. This prevents your animations from overlapping. An alternative, and perhaps cleaner way to do this, would be to simply return false at the beginning of your 'next' and 'prev' functions if #slides ul is being animated, like so:
if ($('#slides ul').is(':animated')) return false;
And I think that's everything. Here's the JSFiddle. Cheers!
EDIT:
Oh, and you may also want to clearInterval at the beginning of the next and prev functions and then reset it in the animation callback functions:
$('#prev').click(function() {
if ($('#slides ul').is(':animated')) return false;
clearInterval(run);
$('#slides ul').stop().animate({'left' : 0}, 1500,function(){
....
run = setInterval('rotate()', speed);
});
});

Change cursor when div scrolls up or down

I have a div that implements Scriptperlative's CursorDivScroll script. How can I implement two customized cursors in the div that is using the script; one that shows when scrolling down and one that shows when scrolling up? Here is the javascript and HTML that I have thus far. The javascript is just the CursorDivScroll script.
<script type='text/javascript' >
$(document).ready(function() {
CursorDivScroll( 'repertoirescroll', 40, 40 ).noHorizontal();
});
</script>
#repertoirescroll {
cursor: url(../images/arrow.png), auto;
position:relative;
}
Thanks for any help in advance. I think I need to implement an if statement that says if mousemove = mousedown use this cursor else if mousemove = up use this cursor...? Not sure how to do this.
Checking if the scrollTop is decreasing or increasing should tell you if it's scrolling up or down, and then just set the cursor based on that when scrolling, and use a timeout to reset the cursor when scrolling stops :
var top=0, timer;
$(window).on('scroll', function() {
clearTimeout(timer);
var scrollTop = $(this).scrollTop(),
cursor = scrollTop > top ? 'pointer' : 'wait';
$('body').css('cursor', cursor);
top = scrollTop;
timer = setTimeout(function() {
$('body').css('cursor', 'default');
}, 500);
});​
FIDDLE

click once for each letter

In my game you have to click the letters to spell the words. When a letter is clicked it animates to an area in the grid where the words are.
When I click a letter and it animates to the cell, I can click more than one. How would I limit it is only one letter per cell.
I was thinking maybe disabling the click function for as long as the animation takes but I don't know how I would implement this.
Can someone point me in the right direction?
Here is the click event...
$('.drag').on('click', function(e) {
e.preventDefault();
var target = $('.drop-box.spellword:not(.occupied):first');
var targetPos = target.position();
var currentPos = $(this).offset();
var b = $(this);
if (target.length) {
$(".minibutton").prop("disabled", true);
b.clone().addClass(
b.data("letter") == target.data("letter") ? "wordglow3" : "wordglow").appendTo("table").css({
background: "transparent",
position: "absolute",
top: currentPos.top,
left: currentPos.left
}).animate({
top: targetPos.top,
left: targetPos.left
}, "slow", function() {
$(this).css({
top: 0,
left: 0
}).appendTo(target);
target.addClass("occupied");
});
Looks like you give the target a class called "occupied" once the animation is done. Couldn't you give it the class "occupied" as soon as a letter is clicked instead?
if (target.length) {
target.addClass("occupied"); // add immediately here
I think you could move the addClass() method from the animate callback, so if you click twice you won't get the same cell, like:
var target = $('.drop-box.spellword:not(.occupied):first').addClass("occupied");
This is only viable thought if the class doesn't affect your styles.
Other way would be using a flag, so in the begining of the event you would ask if(!animating) and set animating = true at the begining of the animation, and animating = flase at the callback.
Lastly, to enable and disable the click event, you could make a separated function with your code like
var clickEventHandler = function(e) {
$('.drag').off("click")
//your current code
$('.drag').on(clickEventHandler);
}
$('.drag').on('click', clickEventHandler);
Good luck!
if you provided the letters with individual Ids you can remove the click attribute via jQuery with $('#letterId').removeAttr('onclick') while animation is in process - afterwards you can re-activate the Attribute if necessary.
Hope this helps. Greetz, Lupo

Categories

Resources