JQuery makes excessive animation queues - javascript

So today I wanted to make a simple animation that would make the button grow when I hover over the button, and shrink when I take the mouse off the button. I tried using this simple JQuery code, but the problem is that if I put the animation speed on slow, running on and off the button multiple times would create multiple queues of the animations, which will run long after my mouse has already left the button.
Is there a way to kill the queue after shrinking it if the mouse leaves the button? Obviously I would like to kill the queue after the button shrinks for the animation to be effective.
Related HTML:
<div id="global-nav">
<ul id="top-nav">
<li class="nav-list"><a class="nav" href="http://images6.fanpop.com/image/photos/33400000/Cats-cats-33441067-1280-800.jpg">Link1</a></li>
|
<li class="nav-list"><a class="nav" href="http://images4.fanpop.com/image/photos/16100000/-cats-16140154-1920-1080.jpg">Link2</a></li>
|
<li class="nav-list"><a class="nav" href="http://learningfromdogs.files.wordpress.com/2010/09/cats-in-sink.jpg">Link3</a></li>
|
<li class="nav-list"><a class="nav" href="http://25.media.tumblr.com/55b8c778e82b28aef27be5d6da8eaa7e/tumblr_meysfu2tM91qzv52ko1_500.jpg">Link4</a></li>
</ul>
</div>
Related JavaScript:
$(document).ready(function() {
$(".nav").mouseover(function() {
$(this).animate({
paddingTop:'6px',
paddingRight:'4px',
paddingBottom:'6px',
paddingLeft:'4px'
},"slow");
}).mouseout(function() {
$(this).animate({
paddingTop:'3px',
paddingRight:'2px',
paddingBottom:'3px',
paddingLeft:'2px'
},"slow");
});
});
JSFiddle: http://jsfiddle.net/76tna/
Please excuse the other CSS, cat text, and HTML. I am referring to the buttons in the nav bar. (If you're curious, this is for my younger sister.)

You need to .stop() the current animation before starting the next one, otherwise it will queue as you currently observe.

TRY THIS FIDDLE
You need to use the stop function, but if you look at the docs you see that you have to remember to input true to the function to clear the queue because it defaults to false.
$(document).ready(function() {
$(".nav").stop(true).mouseenter(function() {
$(this).animate({
paddingTop:'6px',
paddingRight:'4px',
paddingBottom:'6px',
paddingLeft:'4px'
},"slow");
}).mouseout(function() {
$(this).stop(true).animate({
paddingTop:'3px',
paddingRight:'2px',
paddingBottom:'3px',
paddingLeft:'2px'
},"slow");
});
});

$(document).ready(function() {
$(".nav").mouseover(function() {
$(this).css({
paddingTop:'6px',
paddingRight:'4px',
paddingBottom:'6px',
paddingLeft:'4px',
transition: 'padding 0.3s ease'
});
}).mouseout(function() {
$(this).css({
paddingTop:'3px',
paddingRight:'2px',
paddingBottom:'3px',
paddingLeft:'2px',
transition: 'padding 0.3s ease'
});
});
});

Related

Remove click event on item with added class of 'selected'

I'm new here and new to JavaScript and JQuery.
I've been working on a little script to get a part of my page switching videos from Youtube.
The problem I have is when a thumbnail has the class of 'selected' added I want to disable the click function to stop the video reloading - is there a simple way around this?
I attempted to put another bit of JQuery in to find the item with the 'selected' class and return false but I know this is wrong because that will stop the default browser behaviour and not the click event.
Also I'd be very grateful for explanations on code suggestions and also suggestions to improve/streamline my JQuery code.
Thanks in advance!
HTML:
<iframe id="vid" width="980" height="551" src="http://www.youtube.com/embed/hziG9Nr6KHU?&rel=0&controls=4&wmode=transparent&modestbranding=1&rel=0&showinfo=1" frameborder="0" allowfullscreen></iframe>
<ul id="videos">
<li id="one">
<a class="selected" href="http://www.youtube.com/embed/hziG9Nr6KHU?&rel=0&controls=2&wmode=transparent&modestbranding=1&rel=0&showinfo=1&autoplay=1 ">
<img src="http://placehold.it/320x180" />
<span class="AGreg">Vid1</span>
</a>
</li>
<li id="two" class="left">
<a href="http://www.youtube.com/embed/V1bFr2SWP1I?&rel=0&controls=2&wmode=transparent&modestbranding=1&rel=0&showinfo=1&autoplay=1 ">
<img src="http://placehold.it/320x180" />
<span class="AGreg">Vid12</span>
</a>
</li>
<li id="three" class="left">
<a href="http://www.youtube.com/embed/XLgYAHHkPFs?&rel=0&controls=2&wmode=transparent&modestbranding=1&rel=0&showinfo=1&autoplay=1 ">
<img src="http://placehold.it/320x180" />
<span class="AGreg">Vid3</span>
</a></li>
</ul>
CSS:
iframe#vid{width:980px;height:551px;}
.selected img{
opacity: 0.4;
filter: alpha(opacity=40); /* For IE8 and earlier */}
#videos .cursorD a{cursor:default!important}
#videos a:hover img{
opacity: 0.4;
filter: alpha(opacity=40); /* For IE8 and earlier */}
ul#videos{margin:20px 0;padding:0;}
ul#videos img{}
ul#videos li{float:left;width:320px;}
ul#videos li.left{margin:0 0 0 10px}
JQUERY:
$(document).ready(function(){
$("ul#videos li a").click(function(){
$("iframe").attr("src", $(this).attr("href"));
$(this).closest('ul#videos').find('.selected').removeClass('selected');
$(this).parent().addClass('selected cursorD');
return false;
})
});
CODEPEN: http://codepen.io/PixelsPencil/pen/uljzy
You could remove the event handler on the clicked video like you want to, but that requires a bit of code. An easier and (i.m.h.o. more elegant) solution is to adjust your selector / event handler hookup so it only gets executed on elements that do not have the class "selected":
$(document).ready(function(){
$("ul#videos li a:not('.selected')").click(function(){
$("iframe").attr("src", $(this).attr("href"));
$(this).closest('ul#videos').find('.selected').removeClass('selected');
$(this).parent().addClass('selected cursorD');
return false;
})
});
I have to confess, I didn't test it and I'm not 100% sure on the evaluation priority of :xyz() type selectors. To be more certain of what is happening, you could either change the single selector to a selector chain:
$("ul#videos").find("li").find("a:not('.selected')").click( ... );
or even better, hook the event handler to a parent object, but only have it trigger on distinct elements (also expressed through a selector):
$("ul#videos").on("click", "li a:not('.selected')", function() { ... });
This has the added charm that the handler will automatically work for lis that are added after wiring the event handler.
This seemed to work - asked a few people for help and a colleague came up with this still not sure why/how this works but it does.
var VideoLoader = {
registerClickHandlers: function() {
$("ul#videos li a").click(VideoLoader.showSelectedVideo);
},
showSelectedVideo: function() {
if(!VideoLoader.checkVideoIsAlreadyPlaying(this)) {
$("iframe").attr("src", $(this).attr("href"));
$(this).closest('ul#videos').find('.selected').removeClass('selected cursorD');
$(this).parent().addClass('selected cursorD');
}
return false;
},
checkVideoIsAlreadyPlaying: function(clickedObject) {
return $(clickedObject).parent().hasClass("selected");
}
};
$(document).ready(VideoLoader.registerClickHandlers);
Updated my Codepen here: http://codepen.io/PixelsPencil/pen/uljzy
thanks for replying again! I've had a play and put something up on jsfiddle but think it's more broke now than it ever was haha. When I click something with notselected class all thumbs change class and when I click a selected class the video loads in the parent instead of switching the attr in the iframe - any ideas where I've gone wrong?? jsfiddle.net/wvPnA

Using Javascript if statements with and operator and selectors to create navigation bar

i'm trying to create my own navigation bar using Javascript, this is what I have so far.
$(document).ready(function() {
<nav class="menuL">
<ul id="menu">
<li><span></span>portfolio</li>
<ul id="submenu">
<li id="first">Wine</li>
<li id="second">Landscape</li>
<li id="third">Divers</li>
</ul>
<script>
$('#submenu').hide();
</script>
<script>
if ($('#portmenu').mouseover() || $('#first').mouseover() || $('#second').mouseover() || $('#third').mouseout()) {
$('#submenu').show();
} else {
$('#submenu').hide();
}
});
</script>
The submenu is infact being hidden but when I hover over portmenu, the submenu does not appear.. any ideas on what is wrong? I'm new to javascript so I have no idea if im using the selectors, OR operators and the if statements correctly.
Basically what I'm trying to do is, if the main portmenu is hovered over or if first, second and third are being hovered over, then show the sub menu. Otherwise, hide it. I'm trying to do this because if I just create a function which shows the submenu if portmenu is being hovered over, then the moment I hover of the text 'portfolio' the submenu goes away.
You can do it CSS only:
#menu > #submenu{
display: none;
}
#menu:hover > #submenu{
display: block;
}
DEMO: http://jsfiddle.net/Wp5sF/
jsFiddle Demo
You should probably do something more along these lines by taking advantage of jQuery's hover:
$('#submenu').hide();
$('#portmenu, #first, #second, #third').hover(function(){
//in
$('#submenu').show();
},function(){
//out
$('#submenu').hide();
});
Here is my suggestion to fix your code.
(Demo here)
$(document).ready(function(){
$('#submenu').hide();
$('#menu').on('mouseover', function (){$('#submenu').show()});
$('#menu').on('mouseout', function (){$('#submenu').hide()});
});

jquery hide/show based on scroll

So I was given a web template that uses a jquery library called sticky, and it "sticks" the navigation (starts at the bottom and moves up) at the top of the page, as you scroll.
I want to be able to plop a logo onto the navigation once it hits its resting place (post scroll). Similar to this website - http://99u.com/. Once you scroll past the image header, the logo fade's in to the nav bar and then stays on the page. Anyhow, here is the excerpt of the jquery code:
<script>
$(window).load(function() {
$('nav').sticky({ topSpacing:0, className: 'sticky', wrapperClassName: 'my-wrapper' });
});
</script>
And here is the excerpt of the html:
<div with image slideshow></div>
<nav>
<div class="container">
<div class="thirteen columns">
<ul id="nav" class="links">
<li id="sticker"><img src="[image i want to display after scroll]" /></li>
<li>About</li>
<li>Contests</li>
<li>etc.</li>
</ul>
</div>
</div>
</nav>
<div's and the rest of the page's content></div>
This whole template is responsive. Any help would be appreciated, or if someone can point me in the right direction. Thanks!
Take a look at scrollTop and offset.
This is untested but it would look something like this:
$(window).scroll(function(){
if($("#nav").offset().top <= $(window).scrollTop)
$("#nav").css({"position":"fixed","top":"0px", "left":"0px"});
else
$("#nav").css({"position":"relative"});
});
Basically, as the user scrolls, check the windows scroll position and if it passes the top of the nav, switch the nav over to fixed positioning. In my code above, the check on the way back may need a little tweaking but when they scroll to a position less than the height of the nav, put the nav back to relative positioning.
Also instead of switching to position fixed you could show/hide a totally separate nav, might actually make life easier.
-Ken
You can test the position property of the menu and when it changes, hide/show the image via adding/removing a class:
CSS:
#sticker.hidden { width:0; height:0; border:0; padding:0; margin:0; }
#sticker.hidden * { display:none; }
Javascript:
$(window).load(function () {
$('nav').sticky({
topSpacing: 0,
className: 'sticky',
wrapperClassName: 'my-wrapper'
});
var elem = $('#sticker');
var nav = $('nav');
var pos = nav.css('position');
$(window).scroll(function(){
if (nav.css('position')!=pos) { // if changed
if (pos=='fixed') {
elem.addClass('hidden');
} else {
elem.removeClass('hidden');
}
pos = nav.css('position');
}
});
});
jsfiddle
Thanks for the suggestions. They both helped! Here is what i ended up doing:
<script>
$(window).load(function() {
$('#sticker').css({'display':'none'});
$('nav').sticky({ topSpacing:0, className: 'sticky', wrapperClassName: 'my-wrapper' });
$(this).scroll(function() {
if($('nav').offset().top <= $(window).scrollTop()) {
$('#sticker').fadeIn('fast');
} else {
$('#sticker').css({'display':'none'});
}
});
});
</script>

Menu performance issue

I have this HTML code :
<ul class="menu">
<li>Home <span class="icon home"></span><div class="clear"></div></li>
<li class="sub">Projects <span class="icon project"></span>
<div class="clear"></div>
<ul class="sub-menu">
<li>Mfrsht.com</li>
<li>Mawsuaty.com</li>
<li>Dzlng.com</li>
<li>Money(Ctrl)</li>
</ul>
</li>
<li>Ideas <span class="icon idea"></span><div class="clear"></div></li>
<li>Services <span class="icon service"></span><div class="clear"></div></li>
<li>About us <span class="icon about"></span><div class="clear"></div></li>
<li>Contact <span class="icon contact"></span><div class="clear"></div></li>
</ul>
and this Javascript code :
$(".menu > li").not(".menu > li.sub").css( {backgroundPosition: "0px 0px", height: "30px"} )
.mouseover(function(){
$(this).stop().animate({backgroundPosition:"(-167px 0px)", height: "36px"}, {duration:500})
})
.mouseout(function(){
$(this).stop().animate({backgroundPosition:"(0px 0px)", height: "30px"}, {duration:200, complete:function(){ $(this).css({backgroundPosition: "0px 0px"})
}})
})
$(".menu > li.sub").css( {backgroundPosition: "0px 0px"} )
.mouseover(function(){
$(this).stop().animate({backgroundPosition:"(-167px 0px)"}, {duration:500})
})
.mouseout(function(){
$(this).stop().animate({backgroundPosition:"(0px 0px)"}, {duration:200, complete:function(){ $(this).css({backgroundPosition: "0px 0px"})
}})
})
$(".sub").hover(function() {
$(this).animate({height: "150px"}, "slow", "", function () {
$(this).children("ul.sub-menu").slideDown("slow");
});
}, function() {
$(this).animate({height: "30px"}, "slow");
$(this).children("ul.sub-menu").slideUp("slow");
});
the Menu is working fine but sometimes I found it lag or there is some lateness so I want to improve it and make it better.
Note: I'm using background position plugin.
DEMO
Any suggestions? or do you think this good and no need to modify it?
Couple of things to consider:
Use mouseenter / mouseleave instead of mouseover / mouseout to actually get handlers fired when necessary (since you don't care if muse moves cursor within area of menu item - only which item cursor entered and leaved).
Use .stop(true) before running new animations in event handlers. You're already doing it in couple of places, but you've missed some spots (and you're not clearing the animation queue). Try to randomly move cursor around whole menu, then stop and watch the chaos. Event handlers are firing here and there, some items are "hovering", some items are showing submenus, just to be hidden a sec later. By passing true to stop function, you're telling jQuery to clear animation queue for matched object.
You might also consider using second argument for .stop(), which will tell jQuery to just go ahead and set state in which object would be after completting whole animation. That (passing that second argument) would however depend on how you tweak your code, so don't just do that - check if that's a desirable effect in here.

jquery prevent redirect until after animation

This code works perfectly except when you click on a link, The page is redirected before jquery has a change to visually animate the margin back to zero. Is there a way to prevent the redirect until after jquery animates the margin back to zero?
HTML
<div id="sidebar">
<div class="navigation">
<ul>
<li><img src="dbs/images/home.png" title="" width="40" height="38" />به عقب</li>
<li>فیلم ها</li>
<li>وزارتخانه ها ایران زنده</li>
<li>پرستش</li>
<li>جوانان</li>
<li>کودکان</li>
<li>پزوهش ها</li>
<li>دانشکده مسیح</li>
<li>زنان</li>
<li>کلیپ های سری</li>
</ul>
</div>
</div>
JS
$('.navigation a li').click(function () {
$('.slider').animate({
marginLeft: 0
}, 500);
});
.animate() takes a callback function like so:
$('.navigation a li').click(function () {
$('.slider').animate({
marginLeft: 0
}, 500,function() {
//thing to do when you animation is finished e.g.
location.href = 'http://redirect.to.url';
});
});
For complete documentation, check out the (extremely useful) jQuery docs:
http://api.jquery.com/animate/
Firstly, your HTML is invalid. Put the links inside the list items, not the other way around. Adjust your selector accordingly (.navigation li a).
Next, now that you're setting the event on the link rather than the list item, make your handler:
Prevent the default event
Add a callback to the animation, so that when the animation is over the page goes to this.getAttribute('href').
That should do it.
Stop the event propagation from li click handler.
$('.navigation a li').click(function (e) {
$('.slider').animate({
marginLeft: 0
}, 500);
e.stopPropagation();
});

Categories

Resources