jquery prevent redirect until after animation - javascript

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();
});

Related

Making Reusable Function in Jquery

I use this code frequently and it makes my website slowly load.
$('#start').click(function() {
$('html,body').animate({
scrollTop : $('.scroll').offset().top
},1500);//end animate
});//end click
I used to change the #start and .scroll everytime. Any tips?
Wrap it in a function.
function foo(startElem, scrollElem) {
$(startElem).click(function() {
$('html,body').animate({
scrollTop : $(scrollElem).offset().top
},1500);//end animate
});
}
Then call it when you need it.
foo('#start', '.scroll');
Read more here.
Yeah it is with passing some parameters
Refer this example
function scrollCommon(startElem, scrollElem) {
$(startElem).click(function() {
$('html,body').animate({
scrollTop : $(scrollElem).offset().top
},1500);//end animate
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="main">
<ul>
<li>One</li>
<li>Two</li>
</ul>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<div class="one">
<b>One</b><br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>
</div>
<div class="two">
<b>Two</b>
<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>Lorem<br>
</div>
</div>
Besides the question wether this really has an Impact to your loading time, here another way to set this thing up, using event delegation:
$(document).on('click', '[data-scroll-target]', function(e){
$('html,body').animate({
scrollTop: $( this.dataset.scrollTarget ).offset().top
});
});
#start has now become obsolete, every node with a data-scroll-target-attribute will have this functionality
<div data-scroll-target=".scroll">#start</div>
...
<div class="scroll"> target </div>
https://jsfiddle.net/dsx8o04u/

Scrolling to a specific div using window.onload without adding to the web address

I am creating a page with 5 divs. I am using the following JavaScript code to smoothly move between them horizontaly :
$(function () {
$('ul.nav a').bind('click', function (event) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollLeft: $($anchor.attr('href')).offset().left
}, 1500,'easeInOutExpo');
event.preventDefault();
});
});
The Divs are something like this:
<div class="section white" id="section5">
<h2>Technologies</h2>
<p>
text
</p>
<ul class="nav">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
I want to start with div # 3 on page load. The only solution that worked is the onload function:
window.onload = window.location.hash = 'section3';
but unfortunately when I load the page the url address is
http://localhost:51551/trial1/MainPage.aspx#section3
even when I click on another page anchors (div) and go there the URL is stuck to MainPage.aspx#section3.
I tried the solutions here: jQuery: how to scroll to certain anchor/div on page load?
But I think because I am already using Javascript to navigate the divs, its not working. I want to Either:
Remove the address #section3 part and keep using the onload
function
Even better navigate to section3 at start and have
the url change when I change the section
I am using Visual Studio 2010 Express, with ASP.NET, JS and C#. on Windows 8.1
First the following important distinction:
jQuery's #section1 selector looks for an HTML element with ID "section1", i.e. <div id="section1"></div>
The a href's #section1 URL hash looks for an anchor with name "section1", i.e. <a name="section1"></a>
This is a major difference that you need to check and understand. So you would normally need:
<a name="section1"></a>
<div id="section1">... your content here ...</div>
But since you are scrolling horizontally, I am going to do this without the <a name=...></a> part and deal with the hash in the window load handler, as I will explain further down.
Next is, I would avoid naming a JavaScript variable "event" as that looks an awful lot like a keyword, so try renaming it to ev.
If you want the click handler (the function you bind to the click event) to not follow the link clicked on, that function should return false:
$('ul.nav a').click(function (ev) {
var anchor = $(this);
$('.viewport').stop().animate({
scrollLeft: $($(anchor).attr('href')).offset().left
}, 1500,'easeInOutExpo');
// Add the section ID to the URL
window.location.hash = $(anchor).attr('href').substring(1);
ev.preventDefault();
return false;
});
Then, I'd suggest you to move the <ul class="nav">...</ul> outside of the section divs, so you don't have to repeat it inside your divs. Because you seem to be scrolling left/right, I assume you are floating your section divs next to each other in a wide container:
<div class="viewport">
<div class="container clearfix">
<div class="section" id="section1">
<h2>Technologies</h2>
<p>Text</p>
</div>
<div class="section" id="section2">
... content ...
</div>
<div class="section" id="section3">
... content ...
</div>
</div>
</div>
<ul class="nav">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Using the following CSS (as an example for 3 600px divs floated next to each other inside a 1800px container, wrapped by a 600px viewport):
.viewport {
width: 600px;
overflow: hidden;
overflow-x: scroll;
}
.container {
width: 1800px;
}
.section {
float: left;
width: 600px;
}
For the clearfix class, refer to Bootstrap's clearfix.
Because you are scrolling horizontally, I think the <a name=...></a> things won't work, so I'd do an onload check for the hash, and scroll there when accessing the page with a preset hash. This has been done in the window load handler in the next snippet, together with starting in section 3 when there is no hash specified:
As for starting in section 3 on load, have this in your $(window).load() handler, for example:
$(window).load(function() {
var startSection = window.location.hash;
if (startSection == "") startSection = '#section3';
$('.viewport').scrollLeft($(startSection).offset().left);
window.location.hash = startSection;
});
Disclaimer: untested code! :) But please try these, and it should get you pretty close to what you are trying to achieve.
Hope this helps!
Why don't you scroll to that div on window load? And change bind with on, as of jQuery 1.7 .on() is the preferred method for attaching event handlers to a document
So your code should be something like this
$(document).ready( function(){
$('ul.nav a ').on('click ', function (event) {
var $anchor = $(this);
$('html, body ').stop().animate({
scrollLeft: $($anchor.attr('href')).offset().left
}, 1500, 'easeInOutExpo ');
event.preventDefault();
});
});
$(window).on('load', function () {
$('html, body').stop().animate({
scrollLeft: $('#section3').offset().left
}, 1500, 'easeInOutExpo ');
});

Window.resize doesn't work unless page is reloaded

I have this responsive layout. What I want to achieve is that at "desktop" size, once a menu link is clicked it will navigate to that part of the page. I want the same thing for "mobile" size. Also, once the menu links are clicked, the menu will slideUp.
I have both of these things working, however it only works when the page is reloaded. To summarize, here are the problems:
At desktop size: navigation is fine, but when resized to mobile the menu doesn't show.
At mobile size: navigation works fine, when resized to desktop it also works fine, but the menu keeps on toggling.
I created a jsFiddle for it. Here is my code:
HTML
<div id="head" class="clearfix">
Pull Menu
<div class="menu-wrap clearfix">
<div class="nav">
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</div>
</div>
</div>
<div id="test1" class="section">Test1</div>
<div id="test2" class="section">Test2</div>
<div id="test3" class="section">Test3</div>
JavaScript
var respMenu = function(event) {
var menu = $('.menu-wrap');
if ($(window).width() < 501) {
$("#pull").on('click', function() {
menu.slideToggle('slow');
});
$(".nav ul li a").click(function() {
menu.slideUp('slow');
});
}
else{
}
return false;
event.preventDefault();
};
var onClick = function() {
$('a').bind('click',function(event){
var $anchor = $(this);
if ($(window).width() > 500) {
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top - 90 }, 1000,'easeInOutExpo');
}
else{
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top - 50 }, 1000,'easeInOutExpo');
}
event.preventDefault();
});
};
$(window).load(function(){
respMenu();
onClick();
});
$(window).resize(function(){
respMenu();
onClick();
});
The issue is that you bind a new handler to the click event each time your window is re-sized and you never unbind them. So the handlers number keep increasing, which means that multiple events will be fired after a click once you've re-sized the window.
So what you can do is to unbind the handlers using the unbind or off methods.
Take a look here: http://jsfiddle.net/yohanrobert/p987prdd/

JQuery makes excessive animation queues

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'
});
});
});

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.

Categories

Resources