one page scrolling website using jquery - javascript

Hi Stackoverflow fellows,
I want to create a website with one page scrolling but i don't want to use any external library. So i came-up with this technique, It works perfectly fine for a local test but i want to know if this piece of code is logical or this may have potential issues in a full website. I am asking because in my search i did not find this approach for a one page site, i want to know the reason why not this. So please point me in right direction. Any suggestions or comments are welcome. Thanks for your support. https://jsfiddle.net/emalik/xpvt214o/539446/
var current
$(function() {
var timerId;
$('.one-page').bind('DOMMouseScroll mousewheel', function(e){
e.preventDefault();
var $current = $('section.current');
if(e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
//console.log(e.originalEvent.wheelDelta);
//console.log("UP");
$prev = $current.prev();
if ($prev.length) {
clearTimeout(timerId);
timerId = setTimeout(function(){
$current.removeClass('current');
$prev.addClass('current');
$('body,html').animate({
scrollTop: $('.current').offset().top
}, 200);
}, 200)
}
}
else{
// console.log("DOWN");
$next = $current.next();
if ($next.length) {
clearTimeout(timerId);
timerId = setTimeout(function(){
$current.removeClass('current');
$next.addClass('current');
$('body,html').animate({
scrollTop: $('.current').offset().top
}, 200);
, 200)
}
}
});
});

Related

Too many scroll events for smooth scrolling

Hello there I've been trying to find a fix for the many scroll events firing on one scroll. This is the only thing close to working for me so far. I want to smoothscroll between two divs (#boxes and #header) I want to use the scroll bar to trigger this smooth scroll and not a button. Any suggestions on how to only take one scroll event? I also used solutions based from prev stackoverflow questions. I used my own locator instead of offsets because thats also unreliable
$(window).scroll(function () {
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function () {
if (locator == 0) {
id = $("#boxes");
locator = 1;
} else if (locator = 1) {
id = $("#header");
locator = 0;
}
// target element
var $id = $(id);
if ($id.length === 0) {
return;
}
// top position relative to the document
var pos = $id.offset().top;
// animated top scrolling
$('html, body').animate({scrollTop: pos}, 1500, function () {
$('html, body').clearQueue();
$('html, body').stop();
});
}, 2);
});
So, to be clear, you want any minor scroll event to scroll between one item and the other? Note that when a user scrolls, there is a "momentum" that the browser implements, and you'll be battling with that.
Regardless: You don't need to wrap this in a setTimeout. Right now, your javascript is creating a new setTimeout function that is being fired every 2ms. Scroll events occur with every pixel of movement in the scroll, so if you scroll 100px, you're going to be firing 100 times every 2ms. (That's 50,000 times).
Instead, have a a variable (isScrolling) track the state, so, if you're in the middle of scrolling, the function won't fire.
var isScrolling = false;
var locator = 0;
$(window).scroll(function () {
if (isScrolling) return false;
if (locator == 0) {
id = $("#boxes");
locator = 1;
} else if (locator = 1) {
id = $("#header");
locator = 0;
}
// target element
var $id = $(id);
if ($id.length === 0) {
return;
}
// top position relative to the document
var pos = $id.offset().top;
// animated top scrolling
isScrolling = true;
$('html, body').animate({scrollTop: pos}, 1500, function () {
$('html, body').clearQueue();
$('html, body').stop();
isScrolling = false;
});
});
Here's a JSbin: http://jsbin.com/jugefup/edit?html,css,js,output

Scroll To error and success message after submitting a form using ScrollTo jQuery Plugin

So far I have this working properly for the error message only. However, I would like this to work for success message as well. This should happen when the submit button is pressed in the contact form. Click contact at the top right of the page to scroll to it.
You can test it here.
Here is the jQuery I'm using for the error message:
$(document).ready(function() {
$(".error:first").attr("id","errors");
$("#errors").each(function (){
$("html,body").animate({scrollTop:$('#errors').offset().top-175}, 1000);
});
});
Any way to modify it to work with scrolling to #success and #errors with the same offset().top-175 ?
Thanks in advance!
You could do :
$(document).ready(function() {
var pos = null;
if($("#contact-form #errors.visible").length > 0)
pos = $('#errors').offset().top;
if($("#contact-form #success.visible").length > 0)
pos = $('#success').offset().top;
if(pos != null)
$("html,body").animate({scrollTop:pos-175}, 1000);
});
And fix the fact that your script "js/contact_script.js" must be declared after JQuery lib
this solution make the same job for Contact Form 7 (popular form plugin for WordPress). I found this page during the search by Google of my problem, so I added the solution below to help others who ended also at this page.
jQuery(function ($) {
$(document).ready(function ()
{
var wpcf7Elm = document.querySelector( '.wpcf7' );
wpcf7Elm.addEventListener( 'wpcf7submit', function( event ) {
setTimeout(function() {
$([document.documentElement, document.body]).animate({
scrollTop: $(".wpcf7-response-output").offset().top - 100
}, 500);
}, 500);
//console.log("Submited");
}, false );
});
});
$(document).ready(function () {
var $elementToScrollTo;
var $firstError = $(".error:first");
if ($firstError.length > 0) {
$firstError.attr("id", "errors");
$elementToScrollTo = $firstError;
}
else {
$elementToScrollTo = $("#success");
}
$("html,body").animate({
scrollTop: $elementToScrollTo.offset().top - 175
}, 1000);
});

Dynamic divs and scrollTop

I have a single page site:
http://chiaroscuro.telegraphbranding.com/
Each section is dynamically sized based on the user's window. I'm trying to figure out how to have a jQuery smooth scroll function scroll to the top of each section when the link is clicked. It is working great for the first section, funding areas, where I just used a simple offset().top, but the others are not working because they don't know how far to scroll because the window size is always different.
I've been trying to get offset() or position() to work, but no dice. I appreciate any advice.
Here's my jQuery:
`
$(document).ready(function () {
var slowScrollFunding = $('#funding-areas').offset().top;
var slowScrollAbout = $('#about-us').offset().top;
var slowScrollProjects = $('#our-projects').offset().top + 600;
panelOpen = true;
$('#anchor-funding-areas').click(function(event) {
event.preventDefault();
if(panelOpen == true) {
$('#slide-panel-content').stop(true, true).animate({height: '0px'}, 600, function() {
$('#panel-content-container').hide();
$('.scrollableArea').css('z-index', '11');
// Scroll down to 'slowScrollTop'
$('html, body, #home-wrap').animate({scrollTop:slowScrollFunding}, 1000);
panelOpen = false;
});
}else{
$('html, body, #home-wrap').animate({scrollTop:slowScrollFunding}, 1000);
};
});
$('#anchor-aboutus').click(function(event) {
event.preventDefault();
if(panelOpen == true) {
$('#slide-panel-content').stop(true, true).animate({height: '0px'}, 600, function() {
$('#panel-content-container').hide();
$('.scrollableArea').css('z-index', '11');
// Scroll down to 'slowScrollTop'
$('html, body, #aboutus-wrap').animate({scrollTop:slowScrollAbout}, 1000);
panelOpen = false;
});
}else{
$('html, body, #home-wrap').animate({scrollTop:slowScrollAbout}, 1000);
};
});
$('#anchor-ourprojects').click(function(event) {
event.preventDefault();
if(panelOpen == true) {
$('#slide-panel-content').stop(true, true).animate({height: '0px'}, 600, function() {
$('#panel-content-container').hide();
$('.scrollableArea').css('z-index', '11');
// Scroll down to 'slowScrollTop'
$('html, body, #home-wrap').animate({scrollTop:slowScrollProjects}, 1000);
panelOpen = false;
});
}else{
$('html, body, #home-wrap').animate({scrollTop:slowScrollProjects}, 1000);
};
});
$('#header-logo').add('.homelink').click(function() {
if(panelOpen == false) {
$('.scrollableArea').css('z-index', '0');
$('#panel-content-container').show();
$('#slide-panel-content').stop(true, true).animate({height: '389px'}, 600, function() {
// Scroll down to 'slowScrollTop'
panelOpen = true;
});
};
});
});
`
$.offset and $.position can be a little unreliable, especially if you have lots of complicated layouts going on - as your page does. What I've used in the past is the following trick:
var de = document.documentElement ? document.documentElement : document.body;
var elm = $('get_your_anchor_element').get(0);
var destScroll, curScroll = de.scrollTop;
/// check for the function scrollIntoView
if ( elm.scrollIntoView ) {
/// get the browser to scrollIntoView (this wont show up yet)
elm.scrollIntoView();
/// however the new scrollTop is calculated
destScroll = de.scrollTop;
/// then set the scrollTop back to where we were
de.scrollTop = curScroll;
/// you now have your correct scrollTop value
$(de).animate({scrollTop:destScroll});
}
else {
/// most browsers support scrollIntoView so I didn't bother
/// with a fallback, but you could just use window.location
/// and jump to the anchor.
}
The above can occur on the click event. The only thing that needs to be improved is that different browsers scroll on different base elements (body or html). When I used this I had my own element that was scrollable so I didn't need to work out which one the agent was using... When I get a second I'll see if I can find a good bit of code for detecting the difference.
The above has worked in all the modern browsers I've tested (Firefox, Safari, Chrome) however I didn't need to support Internet Explorer so I'm not sure with regard to that.
update:
I'm not quite sure what is going on with your implementation - it is possible that the page is so heavy with content that you actually can see the .scrollIntoView() happening - this has never been my experience, but then I didn't have so much going on on-screen. With that in mind, I've implemented a bare bones system that I would advise you use and build each extra part you need into it:
http://pebbl.co.uk/stackoverflow/13035183.html
That way you know you have a working system to start with, and will easily detect what it is that stops it from working. With regards to chiaro.js your implementation seems to be ok - if a little exploded over many different areas of the file - however this part is slightly erroneous:
$('#anchor-aboutus').click(function() {
event.preventDefault();
if(panelOpen == true) {
$('#slide-panel-content')
.stop(true, true)
.animate({height: '0px'}, 600, function() {
$('#panel-content-container').hide();
$('.scrollableArea').css('z-index', '11');
elm.scrollIntoView(true)
.animate({scrollTop:destScroll}, 1000);
panelOpen = false;
});
}else{
elm.scrollIntoView(true).animate({scrollTop:destScroll});
};
});
In the code above you will only get the correct value of destScroll if panelOpen === true. Ahh, actually I've also spotted another problem - which will explain why it's not working:
elm.scrollIntoView(true)
.animate({scrollTop:destScroll}, 1000);
The above code is mixing pure JavaScript and jQuery, the elm var is a normal DOM element (this supports the scrollIntoView method). But you are then attempting to chain the animate method of jQuery into the mix - you should also be triggering the animate method on the element responsible for the scrollbar. What you should use is as follows:
$('#anchor-aboutus').click(function(e) {
var currentScroll, destScroll;
e.preventDefault();
if(panelOpen == true) {
$('#slide-panel-content')
.stop(true, true)
.animate({height: '0px'}, 600, function() {
$('#panel-content-container').hide();
$('.scrollableArea').css('z-index', '11');
currentScroll = de.scrollTop;
elm.scrollIntoView(true);
destScroll = de.scrollTop;
de.scrollTop = currentScroll;
$(de).animate({scrollTop:destScroll}, 1000);
panelOpen = false;
});
}else{
currentScroll = de.scrollTop;
elm.scrollIntoView(true);
destScroll = de.scrollTop;
de.scrollTop = currentScroll;
$(de).animate({scrollTop:destScroll}, 1000);
};
});
However, what you will also need to do is make sure your de element points to the right element - either html or body depending on the browser - for this you can use this:
var de;
/// calculate which element is the scroller element
$('body, html').each(function(){
if ( this.scrollHeight > this.offsetHeight ) {
de = this;
return false;
}
});
alert( $(de).is('body') ) /// will be true for Chrome, false for Firefox.
You will need to use this code in place of the following code:
var de = document.documentElement ? document.documentElement : document.body;
The reason for changing the code you were using is as follows:
/// store the current scroll position from the de element
currentScroll = de.scrollTop;
/// get the browser to do the scrollTo calculation
elm.scrollIntoView(true);
/// store where the browser scrolled to behind the scenes
destScroll = de.scrollTop;
/// reset our scroll position to where we were before scrollIntoView()
/// if you don't reset then the animation will happen instantaneously
/// because that is what scrollIntoView does.
de.scrollTop = currentScroll;
/// wrap the normal dom element de with jquery and then animate
$(de).animate({scrollTop:destScroll}, 1000);

Cancel scrolling after user interaction

My webpage animates scrolling when users click on links to the same page. I want to cancel this animation as soon as the user tries to scroll (otherwise the user and the browser are fighting for control) – no matter whether with the mouse wheel, the keyboard or the scrollbar (or any other way – are there other ways of scrolling?). I managed to cancel the animation after the mouse wheel or keyboard are used, how do I get this working with the scrollbar?
Here is how my code looks for the keyboard:
$(document.documentElement).keydown( function (event) {
if(event.keyCode == 38 || 40) stopScroll();
});
function stopScroll() {
$("html, body").stop(true, false);
}
I also tried a more elegant way of doing this by using scroll(), the problem is that scroll() catches everything including the animated and automated scrolling. I could not think of any way to let it catch all scrolling except the animated scrolling.
you need animation marker, something like this
$("html, body").stop(true, false).prop('animatedMark',0.0).animate({scrollTop : top, animatedMark: '+=1.0'})
Here is the code, the code was mix of GWT and javascript so moved it to js, not fully tested, please try it
var lastAnimatedMark=0.0;
function scrollToThis(top){
// Select/ stop any previous animation / reset the mark to 0
// and finally animate the scroll and the mark
$("html, body").stop(true, false).prop('animatedMark',0.0).
animate({scrollTop : top, animatedMark: '+=1.0'}
,10000,function(){
//We finished , nothing just clear the data
lastAnimatedMark=0.0;
$("html, body").prop('animatedMark',0.0);
});
}
//Gets the animatedMark value
function animatedMark() {
var x=$("html, body").prop('animatedMark');
if (x==undefined){
$("html, body").prop('animatedMark', 0.0);
}
x=$("html, body").prop('animatedMark');
return x;
};
//Kills the animation
function stopBodyAnimation() {
lastAnimatedMark=0;
$("html, body").stop(true, false);
}
//This should be hooked to window scroll event
function scrolled(){
//get current mark
var currentAnimatedMark=animatedMark();
//mark must be more than zero (jQuery animation is on) & but
//because last=current , this is user interaction.
if (currentAnimatedMark>0 && (lastAnimatedMark==currentAnimatedMark)) {
//During Animation but the marks are the same !
stopBodyAnimation();
return;
}
lastAnimatedMark=currentAnimatedMark;
}
Here is the blog about it
http://alaamurad.com/blog/#!canceling-jquery-animation-after-user-interaction
Enjoy!
Here's a jquery function that should do the trick:
function polite_scroll_to(val, duration, callback) {
/* scrolls body to a value, without fighting the user if they
try to scroll in the middle of the animation. */
var auto_scroll = false;
function stop_scroll() {
if (!auto_scroll) {
$("html, body").stop(true, false);
}
};
$(window).on('scroll', stop_scroll);
$("html, body").animate({
scrollTop: val
}, {
duration: duration,
step: function() {
auto_scroll = true;
$(window).one('scroll', function() {
auto_scroll = false;
});
},
complete: function() {
callback && callback();
},
always: function() {
$(window).off('scroll', stop_scroll);
}
});
};
It's not very elegant, but you could use a flag of some kind to detect what type of scrolling you're dealing with (animated or 'manual') and always kill it when it's animated. Here's an untested example:
var animatedScroll = false;
// you probably have a method looking something like this:
function animatedScrollTo(top) {
// set flag to true
animatedScroll = true;
$('html').animate({
scrollTop : top
}, 'slow', function() {
// reset flag after animation is completed
animatedScroll = false;
});
}
function stopScroll() {
if (animatedScroll) {
$("html, body").stop(true, false);
}
}

javascript - how to scroll page smothly until user relese mouse button

Shor question - page opened on pc with not-so-good touch-screen display. I created 2 big arrows and dont know how to program it using JS/jQuery.
First try: onClick->scroll - it works but user must tap many times to scroll article.
Second:
var scrolling = false;
$("#scUp").mouseup(function(){
$(this).css("opacity", 0.3);
scrolling = false;
}).mousedown(function(){
$(this).css("opacity", 1);
scrolling = true;
while(scrolling) {
$('html, body').stop().animate({ scrollTop: 50 }, 500);
}
event.preventDefault();
});
Doesnt work ;)
I`m trying to simulate real browser scroll arrows - until you keep preesed mouse button page scrolls down (or up).
I answered this question some time back... basically it sets a flag when the mouse is down and clears when the mouse is up. Then a setTimeout loops until the flag clears. Also, it has mousewheel and drag-and-drop functionality.
Check out the demo
Your code above doesn't work because JavaScript is not multi-threaded. That is, your while loop is eating CPU and probably preventing other code from running (i.e. the mouseup event).
I did something like this not too long back. Please feel free to check out my blog post.
Also, not sure if you're doing this or not, but make sure that you place all of your JavaScript code in jQuery's ready() function; otherwise, jQuery may not find the #scUp element.
Here's the relevant code from my old blog post:
var scrollTimer;
function scrollContent(amt)
{
$("#content").scrollTop($("#content").scrollTop()+amt);
scrollTimer = window.setTimeout("scrollContent(" + amt + ")", 25);
}
$(document).ready(function ()
{
$("#content").css("overflow", "hidden");
$("#scrollUp").mousedown(function() {
window.clearTimeout(scrollTimer); //Not necessary, but just to be sure...
$("#scrollUp").animate({"opacity": 100}, 'fast');
scrollContent(-10);
});
$("#scrollUp").mouseup(function() {
window.clearTimeout(scrollTimer);
$("#scrollUp").animate({"opacity": 0}, 'fast');
});
$("#scrollDown").mousedown(function() {
window.clearTimeout(scrollTimer); //Not necessary, but just to be sure...
$("#scrollDown").animate({"opacity": 100}, 'fast');
scrollContent(10);
});
$("#scrollDown").mouseup(function() {
window.clearTimeout(scrollTimer);
$("#scrollDown").animate({"opacity": 0}, 'fast');
});
//$("#scrollUp").css("opacity", 0); //Alternative
$("#scrollUp").animate({"opacity": 0}, 'slow');
$("#scrollDown").animate({"opacity": 0}, 'slow');
});
...and the link:
http://blake-miner.blogspot.com/2010/08/javascript-sticky-footer-and-scroll.html
Hope this helps!
In meantime I wrote this code:
var scrollId = 0;
$("#scUp").mouseup(function(){
$(this).css("opacity", 0.3);
clearInterval(scrollId);
}).mousedown(function(){
$(this).css("opacity", 1);
var scroll = function() { $("html, body").stop().animate({ scrollTop: "-=10px" }, 15); }
scroll();
scrollId = setInterval(scroll, 15);
});
$("#scDw").mouseup(function(){
$(this).css("opacity", 0.3);
clearInterval(scrollId);
}).mousedown(function(){
$(this).css("opacity", 1);
var scroll = function() { $("html, body").stop().animate({ scrollTop: "+=10px" }, 15); }
scroll();
scrollId = setInterval(scroll, 15);
});
It works BUT not on Opera ... funny thing - kiosk is based on Opera browser, so, any solution?
btw. Is there any materials about building kiosk (not outdated for 1.x version of FF) on Linux with FF (linux is no problem for me but I searching for security-plugin for FF).
<div style="position:fixed">
Up
Down
</div>
<script>
var scrollValue = 2;
function scrollAs(value) {
if(value) scrollValue = value;
document.body.scrollTop += (scrollValue - 2)*10;
if(scrollValue != 2) setTimeout(scrollAs, 100);
}
<script>

Categories

Resources