setTimeout function is not working - javascript

The problem is that it keeps scrolling endlessly with no end i tried to terminate it using exit but it's not working, any solution ?
Learn More
<script>
var marginY = 0;
var destination= 0;
var speed = 10;
var scroller = null;
function initScroll(elementId)
{
destination= document.getElementById(elementId).offsettop;
scroller = setTimeout(function(){initScroll(elementId);},1);
marginY = marginY + speed;
if(marginY >= destination)
{
clearTimeout(scroller);
}
window.scroll(0,marginY);
}
</script>

JavaScript is CaSe SeNsItIvE! It is offsetTop and not offsettop:
destination = document.getElementById(elementId).offsetTop;
On a different note, I am not sure how that does work. If you are trying a smooth scroll, you can also use jQuery by:
$(document).ready(function(){
$('a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash;
var $target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 900, 'swing', function () {
window.location.hash = target;
});
});
});

Related

Uncaught TypeError: Cannot read property ‘top’ of undefined

Hi got this error with my new website, i couldn't use mobile menu navigation, any help would be greatly appreciated... cheers..
var OnePageNavigation = function() {
var navToggler = $('.site-menu-toggle');
$("body").on("click", ".main-menu li a[href^='#'], .smoothscroll[href^='#'], .site-mobile-menu .site-nav-wrap li a", function(e) {
e.preventDefault();
var hash = this.hash;
$('html, body').animate({
'scrollTop': $(hash).offset().top
}, 600, 'easeInOutCirc', function(){
window.location.hash = hash;
});
});
};
OnePageNavigation();
Solved it....
top is null and will return NaN, top needs to be 0
var OnePageNavigation = function() {
var navToggler = $('.site-menu-toggle');
$("body").on("click", ".main-menu li a[href^='#'], .smoothscroll[href^='#'], .site-mobile-menu .site-nav-wrap li a", function(e) {
if (this.hash !== "" && this.pathname == window.location.pathname) {
e.preventDefault();
var target = this.hash;
var topOffset = 0; //#top should default to 0 so no need to calculate the difference between top and top :)
if (target != "#top") { //If the target is not "#top", then calculate topOffset
var topOffset = $(target).offset().top;
}
$('html, body').animate({
'scrollTop': $(target).offset().top
}, 600, 'easeInOutCirc', function(){
window.location.hash = target;
});
}
});
};
OnePageNavigation();

How to listen to only the first scroll event on javascript/jquery?

I'm currently working on implementing my own version of snap-scrolling using vanilla JavaScript, and while I've got it mostly working as of now, I'm having trouble handling the scroll events.
My HTML looks something like this:
<div class="container">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
<div id="item4"></div>
</div>
And my JS looks something like this:
var pos = 0;
var isScrolling = false;
var id = 1;
$(window).scroll(function() {
if (!isScrolling) {
isScrolling = true;
var curPos = $(this).scrollTop();
if (curPos > pos) {
// scrolling down
if (id < 4) {
id++;
$('html, body').animate({
scrollTop: $('#item' + id).offset().top
}, 500);
}
} else {
// scrolling up
if (id > 1) {
id--;
$('html, body').animate({
scrollTop: $('#item' + id).offset().top
}, 500);
}
}
isScrolling = false;
pos = curPos;
}
});
What currently happens is when I scroll down my mouse wheel, it will do the animation but will keep proceeding to the next divs because of the multiple scroll events being fired. How do I make it so that it only listens to the first event (whether it scrolls up or down)?
A hacky way is to use timer:
var pos = 0;
var isScrolling = false;
var id = 1;
var lastScrollTime = $.now();
$(window).scroll(function() {
if ((!isScrolling)&&((($.now()-lastScrollTime)>3000)) {
isScrolling = true;
var curPos = $(this).scrollTop();
if (curPos > pos) {
// scrolling down
if (id < 4) {
id++;
$('html, body').animate({
scrollTop: $('#item' + id).offset().top
}, 500);
}
} else {
// scrolling up
if (id > 1) {
id--;
$('html, body').animate({
scrollTop: $('#item' + id).offset().top
}, 500);
}
}
isScrolling = false;
pos = curPos;
lastScrollTime = $.now();
}
});
You can register one time listeners in jQuery using jQuery.one.
EDIT:
You can use the complete callback of jQuery.animate to stop/start responding to scroll events.
var isScrolling = false;
$(window).on('scroll', function () {
if (!isScrolling) {
isScrolling = true;
var curPos = $(this).scrollTop();
if (curPos > pos) {
// scrolling down
if (id < 4) {
id++;
$('html, body').animate({
scrollTop: $('#item' + id).offset().top
}, 500,function(){
isScrolling = false;
});
}
} else {
// scrolling up
if (id > 1) {
id--;
$('html, body').animate({
scrollTop: $('#item' + id).offset().top
}, 500,function(){
isScrolling = false;
});
}
}
pos = curPos;
}
});
There's no easy way to deal with what it is known as kinetic scrolling.
Browsers do not provide developers a proper way to distinguish the meaningful scrolling from the inertial ones.
However, there are some attempts out there that aims to solve this issue, such as Lethargy.
Not 100% ideal, but very close to it.
Other than that, you can take a look at libraries like fullPage.js where another attempt to solve the issue was made.

Pass arrays in function

I created a function but then realised I had to call it three times with two different parameters so I decided to create two different arrays and modify the function so it is called once. After modifiying the function it doesn't work so I am not sure what is happening. Here it is:
function scrll(selector,speed){
for (var i = 0; i < selector.length; i++){
var findIt = '.find("a")';
var selected = selector[i];
selected += findIt;
selected.click(function(e) {
e.preventDefault();
var section = $(this).attr("href");
$("html, body").animate({
scrollTop: $(section).offset().top - 54
},speed[i]);
});
};
};
var selector = ['$(".navbar")','$(".click")','$("#foot")'];
var speed = [2000,1000,2000];
scrll(selector,speed);
Here is a jsfiddle example: http://jsfiddle.net/theMugician/31fws6kd/16/
You seem to be under the impression that you can combine some strings together and the result will be what you would have gotten by executing the contents of that string.
JavaScript doesn't work like that.
This is how you can use selectors like you were trying to do.
function scrll(selectors, speed) {
for (var i = 0; i < selectors.length; i++) {
var selected = $(selectors[i]);
var link = selected.find("a");
link.click(function(e) {
e.preventDefault();
var section = $(this).attr("href");
$("html, body").animate({
scrollTop: $(section).offset().top - 54
}, speed[i]);
});
}
}
var selectors = [".navbar", ".click", "#foot"];
var speed = [2000, 1000, 2000];
scrll(selectors, speed);
There's still a bug here, because i is a closure variable and by the time the events run, it will have the value 3 and everything will be broken. An easy way to fix this is to use forEach():
function scrll(selectors, speed) {
selectors.forEach(function (selector, i) {
var selected = $(selector);
var link = selected.find("a");
link.click(function(e) {
e.preventDefault();
var section = $(this).attr("href");
$("html, body").animate({
scrollTop: $(section).offset().top - 54
}, speed[i]);
});
});
}

CSS/JS issue in Mozilla Firefox

I am having a weird kind of issue in Firefox.
I have applied some js to the header of this site http://devignstudios.nl/ so the header is alway sticky when user scroll down the page.
The sticky header works fine in all browsers except firefox.
I tried to find the solution but couldn't find a proper answer.
Following is the js
var stickyNavTop = $('#header').offset().top;
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('#header').addClass('sticky');
} else {
$('#header').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
Any help here will be highly appreciated.
Thanks in advance!
It has something to do with the scrollTop function which doesn't work in all cases on firefox when applied to id and classes.
Try this: http://jsfiddle.net/rHmAA/7/
This is the modified version of your sticky div thing. (for future reference)
The script uses a #stickyheader as a wrapper.
$(document).ready(function () {
$('a[href^="#"]').bind('click.smoothscroll', function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
var offset;
if ($('#stickyheader').css('position') == 'relative') {
offset = $('#stickyheader').outerHeight(true) * 2;
} else {
offset = $('#stickyheader').outerHeight(true);
}
console.log("offset: " + offset);
var $parent = $target.offsetParent();
console.log("$target.offset().top " + $target.offset().top);
$('#wrapper').animate({
'scrollTop': $target.offset().top - offset
}, 1500, function(){
window.location.hash = target;
});
});
});

jQuery: Sliding via anchorlink

I loaded this jQuery-snippet for sliding a page via anchorLinks.
http://www.position-absolute.com/articles/better-html-anchor-a-jquery-script-to-slide-the-scrollbar/
In my case I have a fixed block (position:fixed) on the top of the page. Due to that I need a delta value for sliding down. If I don't use such a delta value the page is sliding to deep so that my anchorLink is hidden by the fixed block.
Has anybody an idea how to fix this issue?
Thx
The original Plugin:
jQuery.fn.anchorAnimate = function(settings) {
settings = jQuery.extend({
speed : 1100
}, settings);
return this.each(function(){
var caller = this
$(caller).click(function (event) {
event.preventDefault()
var locationHref = window.location.href
var elementClick = $(caller).attr("href")
var destination = $(elementClick).offset().top;
$("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination}, settings.speed, function() {
window.location.hash = elementClick
});
return false;
})
})
}
Modified:
jQuery.fn.anchorAnimate = function(settings) {
settings = jQuery.extend({
speed : 1100,
offset: 0
}, settings);
return this.each(function(){
var caller = this
$(caller).click(function (event) {
event.preventDefault()
var locationHref = window.location.href
var elementClick = $(caller).attr("href")
var destination = $(elementClick).offset().top;
$("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination+settings.offset}, settings.speed, function() {
window.location.hash = elementClick
});
return false;
})
})
}
Note that I've just added an offset option. So if your fixed div has a height of 60px then just call it with $('#whatever').anchorAnimate({offset: 60});
There must be a solution by editing this line:
window.location.hash = elementClick
Changing the duration value helps to slide to right position. But then the window "jumps" the offset-value at the end of the sliding.
Solution: I fixed the problem by removing line:
window.location.hash = elementClick

Categories

Resources