I'm trying to add a side navigation bar to my website, which animates in from the right hand side when the user has scrolled so that the normal navigation bar isnt visible. Ive managed to get it so its animating how I want but not when i want. It just alternates between being shown, and not being shown whenever the user scrolls, not whenever the user scrolls past the header.
I am using jquery and here is a jsfiddle:
http://jsfiddle.net/2twmcmzh/1/ and my current js:
$(document).ready(function() {
var $header = $('header');
var $sideButtons = $('.roundSideButton');
var scrollstate = 'hidden';
var animating = false;
var duration = 500;
$( window ).scroll(function() {
var scrollToTop = $(window).scrollTop();
if(animating === false){
if(scrollToTop > $('header').height() && scrollstate == 'hidden'){
showSideButtons(true);
}else if (scrollstate == 'shown' ){
showSideButtons(false);
}
}
});
function showSideButtons(hide){
animating = true;
if(hide){
$.each($sideButtons,function(i) {
$(this).stop().delay(i * (duration / 2)).animate({right:"20px"}, duration,function(){animating = false;});
});
setTimeout(function() {
animating = false;
scrollstate = 'shown';
console.log(" " + scrollstate + " " + animating);
}, duration * $sideButtons.length);
}else{
$.each($sideButtons,function(i) {
$(this).stop().delay(i * (duration / 2)).animate({right:"-20px"}, duration);
});
setTimeout(function() {
animating = false;
scrollstate = 'hidden';
console.log(" " + scrollstate + " " + animating);
}, duration * $sideButtons.length);
}
}
});
If I understand you correct, everything OK when the user scroll down. Whenever that the header is hidden the points are shown. (From I see in the fiddle). The problem start when the user scroll to the top, than the point are hidden before the header is shown. Right?
If so, you just need to copy the check like you did when the state is hidden.
if(animating === false){
if(scrollToTop > $('header').height() && scrollstate == 'hidden'){
showSideButtons(true);
// I was added this check `scrollToTop < $('header').height()`
} else if (scrollstate == 'shown' && scrollToTop < $('header').height()){
showSideButtons(false);
}
}
Related
I have a script which has a button to scroll the site but I need it to scroll automatically on page load. I need the script to scroll exactly like shown below, except the button. Could anyone change it for me? I'm new to javascript, thanks..
function scroll(element, speed) {
var distance = element.height();
var duration = distance / speed;
element.animate({scrollTop: distance}, duration, 'linear');
}
$(document).ready(function() {
$("button").click(function() {
scroll($("html, body"), 0.015); // Set as required
});
});
Call the scroll function in on window load, this will scroll the page on load finished.
$(window).on('load', function(){
scroll($("html, body"), 0.015); // Set as required
})
You can try the below JavaScript code
var div = $('.autoscroller');
$('.autoscroller').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(evt) {
if (evt.type === 'DOMMouseScroll' || evt.type === 'keyup' || evt.type === 'mousewheel') {
}
if (evt.originalEvent.detail < 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta > 0)) {
clearInterval(autoscroller);
}
if (evt.originalEvent.detail > 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta < 0)) {
clearInterval(autoscroller);
}
});
var autoscroller = setInterval(function(){
var pos = div.scrollTop();
if ((div.scrollTop() + div.innerHeight()) >= div[0].scrollHeight) {
clearInterval(autoscroller);
}
div.scrollTop(pos + 1);
}, 50);
here on the load of the page. The text are auto-scrolled upto the end of the page.
Currently my code snippet hides the navbar as the user scrolls down and brings it back into view as the user scrolls up.
How would I also bring it back into view once the user stops scrolling down (or pauses momentarily)?
Code:
var mywindow = $(window);
var mypos = mywindow.scrollTop();
var up = false;
var newscroll;
mywindow.scroll(function () {
newscroll = mywindow.scrollTop();
if (newscroll > mypos && !up) {
$('.header').stop().slideToggle();
up = !up;
console.log(up);
} else if(newscroll < mypos && up) {
$('.header').stop().slideToggle();
up = !up;
}
mypos = newscroll;
});
Jsfiddle:
http://jsfiddle.net/GM46N/2/
Perhaps you'd want to use a setTimeout at the end of your scroll event and clear it as soon as the event is fired again, as in:
var mywindow = $(window);
var mypos = mywindow.scrollTop();
var up = false;
var newscroll;
mywindow.scroll(function () {
newscroll = mywindow.scrollTop();
clearTimeout(a);
if (newscroll > mypos && !up) {
$('.header').stop().slideToggle();
up = !up;
console.log(up);
} else if(newscroll < mypos && up) {
$('.header').stop().slideToggle();
up = !up;
}
var a = setTimeout(function(){
if (up) {
$('.header').stop().slideToggle();
up = !up;
}
},1400);
mypos = newscroll;
});
I hope this helped you!
You need a timeout.
Since it looks like your using jQuery here is a resource with a bunch of examples for timeout solutions regarding scrolling event: jquery-event-when-user-stops-scrolling
I was working on a project that, when you click the page, it scrolls the entire length of the page. But it does this at 20px intervals; this is to allow javascript to be executed while scrolling in iOS.
However, when uploading the final version, my ftp client has deleted some of the code and it's now not working. I can't see why.
Any suggestions?
var t;
var scrolling = false;
// doScroll sets the position in which to auto pause.
function doScroll() {
$('body').scrollTop($('body').scrollTop() + 20);
if($("#pause").offset().top >=300 && $("#pause").offset().top < 304){
ScrollIt();
} else
if($("#pause").offset().top >=4000 && $("#pause").offset().top < 4004){
ScrollIt() ;
} else
if($("#pause").offset().top >=7500 && $("#pause").offset().top < 7504){
ScrollIt() ;
}
}
// ScrollIt removes the interval for scrolling, pausing the scroll.
function ScrollIt() {
clearInterval(t);
scrolling = false;
return;
// playPause()
}
//Stop/start on click
$('#pause').on('click',function(){
ScrollIt();
scrolling = !scrolling;
if(!scrolling){
clearInterval(t);
return;
}
t = setInterval(doScroll, 5);
});
I create jsfiddle page for you.
http://jsfiddle.net/u32Nw/2/
I can see that it is working, but scrolling is not stopping.
var t;
var scrolling = false;
// doScroll sets the position in which to auto pause.
function doScroll() {
var $body = $("body"),
$pause = $("#pause");
$body.scrollTop($body.scrollTop() + 20);
var pauseTop = $pause.offset().top;
if (pauseTop >= 300 && pauseTop < 304 || pauseTop >= 4000 && pauseTop < 4004 || pauseTop >= 7500 && pauseTop < 7504) {
clearScrollInterval();
}
}
// scrollIt removes the interval for scrolling, pausing the scroll.
function clearScrollInterval() {
clearInterval(t);
scrolling = false;
return;
// playPause()
}
//Stop/start on click
$("#pause").on("click", function () {
clearScrollInterval();
scrolling = !scrolling;
t = setInterval(doScroll, 5);
});
This is exact same code, just refactored.
Try working from here. You need to refactor your code for debugging.
I'm facing some problem to scroll the HTML sections with the help of viewport jQuery plugin. I have 4 sections on a page, I want to scroll one by one while mouse scrolling (up or down). My HTML and JavaScript code are given below:
<section id="chapter1-block" class="chapter">
<span id="chapter1" class="pointer"></span><span class="pointer-b"></span>
</section>
<section id="chapter2-block" class="chapter">
<span id="chapter2" class="pointer"></span><span class="pointer-b"></span>
</section>
<section id="chapter3-block" class="chapter">
<span id="chapter3" class="pointer"></span><span class="pointer-b"></span>
</section>
<section id="chapter4-block" class="chapter">
<span id="chapter4" class="pointer"></span><span class="pointer-b"></span>
</section>
JS:
$(function () {
var _top = $(window).scrollTop();
var _direction;
var curChapterPos = 'chapter1';
$(window).scroll(function(){
var _cur_top = $(window).scrollTop();
console.log(curChapterPos);
if(_top < _cur_top)
{
if(curChapterPos == "chapter1")
{
$('body').scrollTo( '#chapter2');
curChapterPos = 'chapter2';
console.log(_cur_top);
return false;
}
else
if(curChapterPos == "chapter2")
{
$('body').scrollTo( '#chapter2');
curChapterPos = 'chapter3';
console.log('3--'+curChapterPos);
return false;
}else
if(curChapterPos == "chapter3")
{
$('body').scrollTo( '#chapter3');
curChapterPos = 'chapter4';
console.log('3--'+curChapterPos);
return false;
}
_direction = 'down';
}
else
{
_direction = 'up';
}
_top = _cur_top;
});
});
The problem here, is when the page scrolls, the functions is invoked 7 times if you use the scroll bar from the browser. 9 times with the key down. And If you use the mouse wheel the function is invoked between 12 and 25 times. So, the problem could be solved if you avoid the use of the mouse, because the sensibility of the mouse could be different in any client/browser. But this not resolve the original question. Maybe if combine the page scroll with the mouse hover and the visibility of the tag, will result in the answer you need.
Here is my partial solution. It makes a loop if the mouse scroll goes down.
http://jsfiddle.net/manueru_mx/Wm6Pn/
$(function () {
var _top = $(window).scrollTop();
$("#xtop").val(0);
var _direction;
var curChapterPos = '';
var _last = false;
$(window).scroll(function(){
var _cur_top = $(window).scrollTop();
var _top = $("#xtop").val();
curChapterPos = $("#chapterhidden").val();
if(_top < _cur_top){
if(curChapterPos == "chapter1"){
$('body').scrollTo( '#chapter2');
curChapterPos = 'chapter2';
$("#chapterhidden").val(curChapterPos);
}else if(curChapterPos == "chapter2"){
$('body').scrollTo( '#chapter2');
curChapterPos = 'chapter3';
$("#chapterhidden").val(curChapterPos);
}else if(curChapterPos == "chapter3"){
$('body').scrollTo( '#chapter3');
curChapterPos = 'chapter4';
$("#chapterhidden").val(curChapterPos);
} else if(curChapterPos == "chapter4" && elementInViewport(document.getElementById('chapter3')) == false){
console.log("aquisss");
$('body').scrollTo( '#chapter4');
curChapterPos = 'chapter4';
$("#chapterhidden").val(curChapterPos);
$("#xtop").val(_cur_top+1000);
}else{
return false;
}
_direction = 'down';
$("#xtop").val(_cur_top);
}else {
if(curChapterPos == "chapter4" && elementInViewport(document.getElementById('chapter4-block')) == false){
$('body').scrollTo( '#chapter3');
curChapterPos = 'chapter3';
$("#chapterhidden").val(curChapterPos);
} else if (curChapterPos== "chapter3"){
$('body').scrollTo( '#chapter2');
curChapterPos = 'chapter2';
$("#chapterhidden").val(curChapterPos);
} else if (curChapterPos== "chapter2"){
$('body').scrollTo( '#chapter1');
curChapterPos = 'chapter1';
$("#chapterhidden").val(curChapterPos);
}
_direction = 'up';
$("#xtop").val(_cur_top);
}
});
});
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth)
);
}
When you enter the last position, although the direction of travel is up, never enters the condition. So I add 1000 to the end position. This creates the cycle and lets start from the beginning. It is wrong, but i can not find logic in behavior. Interestingly only happens in the last position.
Tested on FF 16 and IE 8 with compatibility view. and works with mouse scroll, key down and browser scroll bar.
Using this plugin would be easier.
http://www.appelsiini.net/projects/viewport
But I would not change much your initial approach. I used the library scrollTo because I see you use that function and is not native to jQuery
http://demos.flesler.com/jquery/scrollTo/js/jquery.scrollTo-min.js
Hope this help
References:
ElementInViewPort function
I have a page that I'm building and I would like to make it that when I scroll (up or down) the page scrolls to the next div (each div is 100% the height of the window). And gets "fixed" there until you scroll again. An example of what I'm trying to accomplish can be seen here:
http://testdays.hondamoto.ch/
You will notice that when you scroll down, it automatically moves you to the next "div".
What I've tried:
Using the jQuery .scroll event combined with:
function updatePosition() {
if(canScroll) {
var pageName;
canScroll = false;
var st = $(window).scrollTop();
if (st > lastScrollTop){
// downscroll code
if(pageNumber < 7) {
pageNumber++;
}
pageName = '#' + getPageToScrollTo().id;
$('body').animate({ scrollTop: $(pageName).offset().top }, 2000, function() {
canScroll = true;
});
} else {
// upscroll code
if(pageNumber > 0) {
pageNumber--;
}
pageName = '#' + getPageToScrollTo().id;
$('body').animate({ scrollTop: $(pageName).offset().top }, 2000, function() {
canScroll = true;
});
}
lastScrollTop = st;
}
}
But the scroll event was getting called when the page was scrolling (animating), AND when the user scrolled. I only need it to be called when the user scrolls.
Then I added:
var throttled = _.throttle(updatePosition, 3000);
$(document).scroll(throttled);
From the Underscore.js library - but it still did the same.
Finally, I browsed here a bit and found:
Call Scroll only when user scrolls, not when animate()
But I was unable to implement that solution. Is there anyone that knows of any libraries or methods to get this working?
EDIT:
Solution based on Basic's answer:
function nextPage() {
canScroll = false;
if(pageNumber < 7) {
pageNumber++;
}
pageName = getPageToScrollTo();
$('html, body').stop().animate({ scrollTop: $(pageName).offset().top }, 1000, function() {
canScroll = true;
});
}
function prevPage() {
canScroll = false;
if(pageNumber > 0) {
pageNumber--;
}
pageName = getPageToScrollTo();
$('html, body').stop().animate({ scrollTop: $(pageName).offset().top }, 1000, function() {
canScroll = true;
});
}
//--Bind mouseWheel
$(window).on(mousewheelevt, function(event) {
event.preventDefault();
if(canScroll){
if(mousewheelevt == "mousewheel") {
if (event.originalEvent.wheelDelta >= 0) {
prevPage();
} else {
nextPage();
}
} else if(mousewheelevt == "DOMMouseScroll") {
if (event.originalEvent.detail >= 0) {
nextPage();
} else {
prevPage();
}
}
}
});
Ok...
The relevant code for the Honda site can be found in http://testdays.hondamoto.ch/js/script_2.js. It seems to be doing some calculations to locate the top of the div then scroll to it. There are handlers for different types of scrolling.
Specifically, the movement is handled by function navigation(target)
the key bits is here...
$('html,body').stop().animate({
scrollTop: $(target).offset().top + newMargin
}, 1000,'easeInOutExpo',function(){
//Lots of "page"-specific stuff
}
});
There are handlers for the scroll types...
$('body').bind('touchstart', function(event) {
//if(currentNav!=3){
// jQuery clones events, but only with a limited number of properties for perf reasons. Need the original event to get 'touches'
var e = event.originalEvent;
scrollStartPos = e.touches[0].pageY;
//}
});
//--Bind mouseWheel
$('*').bind('mousewheel', function(event, delta) {
event.preventDefault();
//trace('class : '+$(this).attr('class') + ' id : '+$(this).attr('id'));
if(!busy && !lockScrollModel && !lockScrollMap){
if(delta<0){
nextPage();
}else{
prevPage();
}
}
});
You'll note that the navigate() function sets a busy flag which is unset when scrolling completes - which is how it suppresses all new scroll events during a scroll. Try changing the direction of scroll while the page is already scrolling and you'll notice user input is being ignored too.