Smooth javascript navigation stops working after first click - javascript

This webpage http://www.eboxlab.net/ has a menu on the left side. What I need to achieve is to be able to go to a page section when the respective menu option is pressed. Here is my code (pretty sure it's quite bad, but I will clean it up later, after I make it work):
navigateMe();
navInit = 1;
navNext = 2;
function navigateMe() {
step = jQuery('ul#navigation li').size();
looper = setInterval(function(){
if(navNext > step + 1) {
navInit = 1;
navNext = 1;
}
var refLink = jQuery('ul#navigation li:nth-child(' + navInit + ') a').attr('href').replace('#', '');
var divLink = jQuery("div[id='" + refLink + "']").offset().top;
jQuery('ul#navigation li:nth-child(' + navInit + ') a').on('click', function() {
jQuery('html, body').animate({
scrollTop: divLink
}, 500);
});
navInit = navNext;
navNext = navNext + 1;
}, 0);
}
However the problem is that it only works once. After you click menu once, it doesn't slide up or down anymore. Please tell me what's wrong with it.
Many thanks in advance.

Related

Imprecise values from scrollTop() depending on scroll speed

I am currently working on a Parallax Effect using jQuery. For that I am using a JS Class.
When I was first testing the code I thought everything was working fine. However I just found out that the parallax_container divs are behaving differently based on how fast the user is scolling. I am pretty sure that this happens because the window.scroll function just is not accurate enough to use it in this case. Thats why I changed the code and added the setInterval function the change the scrollTop Variable as often as possible, but this didn't change my problem.
Did I take the wrong approach, or is there a clever way to get the scroll Postion in a "linear" way no matter how fast the user scrolls ?
I added the part of the code that seems important to me, but i can post more if needed.
Codepen Example
jQuery(document).ready(function () {
jQuery("." + elemCssClass).addClass("parallax_container");
jQuery("." + elemCssClass).css("position", "relative");
jQuery(".parallax_container").each(function (index) {
jQuery(this).attr('id', 'parallax_' + (index + 1));
});
var lastScrollTop = 0;
var scrollDirect;
var initialTop = parseInt(jQuery("." + elemCssClass).css("top"));
var scr;
setInterval(function () {
scr = jQuery(window).scrollTop()
}, 0.00005);
jQuery(window).scroll(function () {
if (mediaQuery.matches) {
return;
}
if (scr > lastScrollTop) {
scrollDirect = "down"
} else {
scrollDirect = "up"
}
lastScrollTop = st;
var elem = document.querySelector("." + elemParentCssClass);
var visible = ctrl.isInViewport(elem);
if (visible) {
if (scr === 0) {
jQuery("." + elemCssClass).css('top', initialTop);
}
var diff = scr - initY;
var ratio = jQuery("." + elemCssClass).css('top');
// Hier wird der Speed der im VC eingestellt ist angewendet.
// Es wird gechekct ob nach oben oder unten gescrolled wird und entweder + oder - gerechnet
if (scrollDirect === "up") {
jQuery("." + elemCssClass).css({
top: "+=" + elemSpeed + 'px'
});
}
if (scrollDirect === "down") {
jQuery("." + elemCssClass).css({
top: "-=" + elemSpeed + 'px'
});
}
}
else {
jQuery("." + elemCssClass).css('top', 0);
}
var initY = jQuery("." + elemParentCssClass).offset().top
var height = jQuery("." + elemParentCssClass).height()
var endY = initY + jQuery("." + elemParentCssClass).height()
}) //window.scroll()
}) // document.ready()

how to use setInterval to continue animation while mouse is over div

I am trying to modify a slideshow to continuously animate while the mouse is over the back or next arrow. If the mouse leaves, I would like the animation to stop where it is.
I found this post and this post which are helpful in telling me I need to use setInterval, but because I am a beginner I am not sure how to implement it with the code I have. I tried updating the miliseconds set in the counter variable but that didn't change anything.
Here is the hover code so far. It advances the image on hover but not continuously.
$(document).ready(function(){
var thumbs = $('ul.thumbHolder li');
var bigImgs = $('ul.imgHolder li');
var mask = $('.imgHolder');
var imgW = $('ul.imgHolder li').width();
var speed = 800;
thumbs.removeClass('selected').first().addClass('selected');
thumbs.click(function () {
var target = $(this).index();
mask.animate({
'left': '-' + imgW * target + 'px'
}, speed);
thumbs.removeClass('selected');
$(this).addClass('selected');
});
$('.Bleft').on('mouseover', function () {
var i = $('ul.thumbHolder li.selected').index();
i--;
$('ul.thumbHolder li.selected').removeClass('selected');
thumbs.eq(i).addClass('selected');
if (i === -1) {
mask.animate({
'left': '-' + imgW * $('ul.thumbHolder li').index() + 'px'
}, speed);
} else {
mask.animate({
'left': '-' + imgW * i + 'px'
}, speed);
}
clearInterval(counter);
});
$('.Bright').on('mouseover', function () {
var i = $('ul.thumbHolder li.selected').index();
i = i >= thumbs.length - 1 ? 0 : i + 1;
$('ul.thumbHolder li.selected').removeClass('selected');
thumbs.eq(i).addClass('selected');
mask.animate({
'left': '-' + imgW * i + 'px'
}, speed);
clearInterval(counter);
});
var count = 0;
var counter = window.setInterval(timer, 5000);
function timer() {
count = count + 0;
if (count >= 0) {
count = 0;
return;
}
mask.animate({
'left': '-' + imgW * count + 'px'
}, speed);
thumbs.removeClass('selected');
thumbs.eq(count).addClass('selected');
}
});
This is an example of what I am trying to achieve (I know it is flash but I think it can be done with jQuery too).
This is a fiddle that has all my work so far.
Thank you for any help.
I think I am close to the solution. This is my idea.
Every ul.imgHolder li is divided in many blocks of 20px ( you can change the size of course ), so if a div has a size of 980px you will have 49 blocks for image.
When mouseover event is fired I will slide for a block every speed milliseconds until the mouseout is fired.
I've implemented only the slide right button, I've deleted partially some logic, sorry!
var $ = jQuery.noConflict(true);
$(document).ready(function(){
var thumbs = $('ul.thumbHolder li');
var bigImgs = $('ul.imgHolder li');
var mask = $('.imgHolder');
var imgW = $('ul.imgHolder li').width(); //Assuming imgW % 20 = 0
var blockSize = 20; //20px
var blocksPerThumb = imgW/blockSize;
var numBlocks = (blocksPerThumb)*thumbs.length;
var speed = 400;
var blockPos = 0;
var currentAnim = null;
thumbs.removeClass('selected').first().addClass('selected');
thumbs.click(function () {
var target = $(this).index();
mask.animate({
'left': '-' + imgW * target + 'px'
}, speed,'linear');
thumbs.removeClass('selected');
$(this).addClass('selected');
});
$('.Bleft').on('mouseover', function () {
});
$('.Bright').on('mouseover', function(){
currentAnim = setInterval(goRight,speed);
}).mouseout(function(){
clearInterval(currentAnim);
});
var goRight = function () {
blockPos = (blockPos+1)%numBlocks;
mask.animate({
'left': '-' + blockSize * blockPos + 'px'
}, speed,'linear');
};
});
Good Work!

jQuery entire page flickering on certain element

this is the fiddle:
http://jsfiddle.net/Ywq8G/
I wonder if someone is able to tell me: Why menu1 is flickering after clicking a submenu(the green one) the other two work just fine, but debugging is getting me nowhere and I was like: SO has given me so much answers allready(with just reading) may I contribute and ask my specific question.
I hope the solution will make me a better developer and help others avoid the problems I have encountered.
var MENU_HEIGHT = 110;
$(document).ready(function () {
var menuCollection = {}
var i = 1;
$(".menu").children().each(function () {
menuCollection[i] = [];
$(".subMenu" + i).children().each(function () {
menuCollection[i].push(this);
});
i++;
});
function scroll(menu, item, status) {
if (item < menu.length) {
var currentChild = menu[item];
if (status == "scrollOut") {
$(currentChild).stop().animate({
top: MENU_HEIGHT + 80 * item
}, {
queue: false,
duration: 600
}) {
scroll(menu, item + 1, status);
};
} else {
$(currentChild).stop().animate({
top: 0
}, {
queue: false,
duration: 600
}) {
scroll(menu, item + 1, status);
};
}
}
}
var ii = 1;
$(".menu").children().each(function () {
var target = $(this).attr('class');
var menu = menuCollection[ii];
$("." + target + ", .subMenu" + ii + " > a").bind("mouseover", function () {
doScroll(menu, 0, "scrollOut");
});
$("." + target + ", .subMenu" + ii + " > a").bind("mouseout", function () {
doScroll(menu, 0, "scrollIn");
});
ii++;
});
function doScroll(menu, item, status) {
scroll(menu, item, status);
}
$("a").click(function (event) {
var href = $(this).attr('href');
href = href.substring(1);
$(".current").appendTo(".hidden");
$(".current").removeClass("current");
$("." + href).addClass("current");
$("." + href).appendTo(".main");
$('html, body').animate({
scrollTop: $(".main").offset().top
}, 600);
});
});
There is flickering because you are using href parameter of tag with '#' and when you click on it browsers move window to element with id like #-value. And if you have a lot of content to change browsers first jump to this id and next use your $('html, body').animate({...}) function (so again jump to top and animate to down).
You can change 'href' for example to 'myHref' (in html and js) it's should resolve the problem.
(sorry for my english, i hope is understandable)

execute Jquery when the mouse stops moving

I have a quick script that has a trail follow the cursor:
jQuery(document).ready(function(){
$(document).mousemove(function(e){
$('.fall').each(function(){
if ($(this).css("opacity") == 0){
$(this).remove();
};
});
t = (e.pageY - 10).toString() + 'px';
l = (e.pageX - 10).toString() + 'px';
$('.fall').css("margin_left",l);
$('.fall').css("margin_top",t);
var doit = '<div class="fall" style="position:fixed;margin-left:' + l + ';margin-top:' + t + ';">+</div>'
$('body').prepend(doit);
$('#status2').html(e.pageX +', '+ e.pageY);
$('.fall').animate({
marginTop: '+=50px',
opacity: 0
},1000);
});
});
Now I would like to remove the animate part and have something like the following when the mouse is not moving:
$('.fall').each(function(){
$(this).fadeOut('slow');
$(this).remove()
});
I just can't figure out how to execute this when the mouse is not moving for more than like a second. Any ideas?
Thanks, and here is a jsfiddle
You add a timeout that fires after one second of inactivity, and clear the timeout if the mouse moves within 1 second etc :
var timer;
$(document).on('mousemove', function(e){
clearTimeout(timer);
timer = setTimeout(function() {
$('.fall').fadeOut('slow', function() {
$(this).remove();
});
}, 1000);
});
FIDDLE
EDIT:
Here's how I'd do it
FIDDLE
is this what you require? jsFiddle
lastTimeMouseMoved = new Date().getTime();
var t = setTimeout(function() {
var currentTime = new Date().getTime();
if (currentTime - lastTimeMouseMoved > 1000) {
$('.fall').fadeOut('slow');
// $('.fall').remove();
}
}, 1000)

javascript 'over-clicking' bug

I have a bug in Javascript where I am animating the margin left property of a parent container to show its child divs in a sort of next/previous fashion. Problem is if clicking 'next' at a high frequency the if statement seems to be ignored (i.e. only works if click, wait for animation, then click again) :
if (marLeft === (-combinedWidth + (regWidth) + "px")) {
//roll margin back to 0
}
An example can be seen on jsFiddle - http://jsfiddle.net/ZQg5V/
Any help would be appreciated.
Try the below code which will basically check if the container is being animated just return from the function.
Working demo
$next.click(function (e) {
e.preventDefault();
if($contain.is(":animated")){
return;
}
var marLeft = $contain.css('margin-left'),
$this = $(this);
if (marLeft === (-combinedWidth + (regWidth) + "px")) {
$contain.animate({
marginLeft: 0
}, function () {
$back.fadeOut('fast');
});
} else {
$back.fadeIn(function () {
$contain.animate({
marginLeft: "-=" + regWidth + "px"
});
});
}
if (marLeft > -combinedWidth) {
$contain.animate({
marginLeft: 0
});
}
});
Sometimes is better if you create a function to take care of the animation, instead of writting animation code on every event handler (next, back). Also, users won't have to wait for the animation to finish in order to go the nth page/box.
Maybe this will help you:
if (jQuery) {
var $next = $(".next"),
$back = $(".back"),
$box = $(".box"),
regWidth = $box.width(),
$contain = $(".wrap")
len = $box.length;
var combinedWidth = regWidth*len;
$contain.width(combinedWidth);
var currentBox = 0; // Keeps track of current box
var goTo = function(n) {
$contain.animate({
marginLeft: -n*regWidth
}, {
queue: false, // We don't want animations to queue
duration: 600
});
if (n == 0) $back.fadeOut('fast');
else $back.fadeIn('fast');
currentBox = n;
};
$next.click(function(e) {
e.preventDefault();
var go = currentBox + 1;
if (go >= len) go = 0; // Index based, instead of margin based...
goTo(go);
});
$back.click(function(e) {
e.preventDefault();
var go = currentBox - 1;
if (go <= 0) go = 0; //In case back is pressed while fading...
goTo(go);
});
}
Here's an updated version of your jsFiddle: http://jsfiddle.net/victmo/ZQg5V/5/
Cheers!
Use a variable to track if the animation is taking place. Pseudocode:
var animating = false;
function myAnimation() {
if (animating) return;
animating = true;
$(this).animate({what:'ever'}, function() {
animating = false;
});
}
Crude, but it should give you the idea.
Edit: Your current code works fine for me as well, even if I jam out on the button. On firefox.

Categories

Resources