Animate scroll between sections - without a plugin - javascript

Im trying to create a script that animates the scrolling between section on my page without using a plugin - just pure jquery. But seems that I'm experiencing some issues when I try and scroll my page. Can anyone help me?
Here is my jsFiddle
And my code:
$(document).ready(function() {
$('.main').bind('mousewheel', function(e){
var mHeight=$(document).height()/8;
console.log(mHeight);
if(e.originalEvent.wheelDelta /120 > 0) {
// alert('up');
$('html, body').animate({
scrollTop: mHeight
}, 1000);
}
else{
// alert('down');
$('html body').animate({
scrollTop: -mHeight
}, 1000);
}
});
});

check this
$('body').bind('mousewheel', function (e) {
e.stopPropagation();
e.preventDefault();
var mHeight = $(document).height() / 8;
console.log(mHeight);
if (e.originalEvent.wheelDelta / 120 > 0) {
// alert('up');
$('html, body').stop().animate({
scrollTop: -mHeight
}, 1000);
}
else {
// alert('down');
$('html body').stop().animate({
scrollTop: mHeight
}, 1000);
}
});
Demo
Edit
var index = 1;
$('body').bind('mousewheel', function (e) {
e.stopPropagation();
e.preventDefault();
var mHeight = $(document).height() / 8;
console.log(mHeight);
if (e.originalEvent.wheelDelta / 120 > 0) {
// alert('up');
index--;
mHeight = mHeight * index;
$('html, body').stop().animate({
scrollTop: mHeight
}, 1000);
}
else {
// alert('down');
index++;
mHeight = mHeight * index;
$('html body').stop().animate({
scrollTop: mHeight
}, 1000);
}
});
Updated Fiddle

Related

target.attr is not a function, length undefined jquery onclick

I have these two on click events for two different classes, they have one part of the code that is the same for both of them, so I tried making a function that would contain the part of the code which is the same, and then cal, that function inside onclick, but I keep getting one error.
This is the code that works properly:
$(list).on('click', function() {
$(arrow).removeClass("mobile-select__arrow--active")
$(listItem).removeClass(listItem_expanded);
$(list).addClass("mobile-select--sticky");
var windowHeight = $(window).height();
var documentHeight = $(document).height();
var target = $(this.getAttribute('href'));
if (target.length) {
//prevent default bhebahvior
event.preventDefault();
var topDistance = target.offset().top;
var bottomDistance = documentHeight - topDistance;
if (windowHeight > bottomDistance) {
$(container).css('padding-bottom', topDistance + 'px');
};
var stickyTopHeight = $(list).outerHeight();
$('html, body').stop().animate({
scrollTop: target.offset().top - stickyTopHeight - 150
}, 1000);
if($(window).width() <= 769) {
$('html, body').stop().animate({
scrollTop: target.offset().top - stickyTopHeight - 100
}, 1000);
}
}
if($(window).width() <= 769) {
if (!$(this).hasClass(list_expanded)) {
$(this).addClass(list_expanded);
$(arrow).addClass("mobile-select__arrow--active")
$(listItem).addClass(listItem_expanded);
} else {
$(this).removeClass(list_expanded);
// $(this).slideUp();
$(arrow).removeClass("mobile-select__arrow--active")
$(listItem).removeClass(listItem_expanded);
}
}
if ($(window).width() > 769) {
$(this).addClass(list_expanded);
$(arrow).addClass("mobile-select__arrow--active")
$(listItem).addClass(listItem_expanded);
}
});
$(link).on('click', function() {
$(arrow).removeClass("mobile-select__arrow--active")
$(listItem).removeClass(listItem_expanded);
$(list).addClass("mobile-select--sticky");
var windowHeight = $(window).height();
var documentHeight = $(document).height();
var target = $(this.getAttribute('href'));
if (target.length) {
//prevent default bhebahvior
event.preventDefault();
var topDistance = target.offset().top;
var bottomDistance = documentHeight - topDistance;
if (windowHeight > bottomDistance) {
$(container).css('padding-bottom', topDistance + 'px');
}
var stickyTopHeight = $(list).outerHeight();
$('html, body').stop().animate({
scrollTop: target.offset().top - stickyTopHeight - 150
}, 1000);
if($(window).width() <= 769) {
$('html, body').stop().animate({
scrollTop: target.offset().top - stickyTopHeight - 100
}, 1000);
}
}
});
And this is what I tried doing but with zero luck, since I've been getting these errors: Uncaught TypeError: target.attr is not a function
Uncaught TypeError: Cannot read property 'length' of undefined
function doSomething(target) {
target = target || $(this);
$(arrow).removeClass("mobile-select__arrow--active")
$(listItem).removeClass(listItem_expanded);
$(list).addClass("mobile-select--sticky");
var windowHeight = $(window).height();
var documentHeight = $(document).height();
if (target.attr('href').length) {
//prevent default bhebahvior
event.preventDefault();
var topDistance = target.offset().top;
var bottomDistance = documentHeight - topDistance;
if (windowHeight > bottomDistance) {
$(container).css('padding-bottom', topDistance + 'px');
};
var stickyTopHeight = $(list).outerHeight();
$('html, body').stop().animate({
scrollTop: target.offset().top - stickyTopHeight - 150
}, 1000);
if($(window).width() <= 769) {
$('html, body').stop().animate({
scrollTop: target.offset().top - stickyTopHeight - 100
}, 1000);
}
}
}
$(list).on('click', function() {
doSomething($(this));
if($(window).width() <= 769) {
if (!$(this).hasClass(list_expanded)) {
$(this).addClass(list_expanded);
$(arrow).addClass("mobile-select__arrow--active")
$(listItem).addClass(listItem_expanded);
} else {
$(this).removeClass(list_expanded);
// $(this).slideUp();
$(arrow).removeClass("mobile-select__arrow--active")
$(listItem).removeClass(listItem_expanded);
}
}
if ($(window).width() > 769) {
$(this).addClass(list_expanded);
$(arrow).addClass("mobile-select__arrow--active")
$(listItem).addClass(listItem_expanded);
}
});
$(link).on('click', doSomething);
I just wanted to try and write these events in a shorter way. Is that possible?
This is probably the one that's failing:
$(link).on('click', doSomething);
The doSomething function expects its one argument to be a jQuery object for a DOM element, but the click event passes the event object, not the element which invoked the event. You can pass the element as a jQuery object the same way you do in your other click handler:
$(link).on('click', function () { doSomething($(this)); });

On scroll the active menu does not chaning

I've created a right side menu but when i scrolling down it is not changing the active class to next menu,I've used this code lots of time but this time i'm not getting the result,
$(window).scroll(function() {
var scrollbarLocation = $(this).scrollTop();
scrollLink.each(function() {
var sectionOffset = $(this.hash).offset().top - 70;
if ( sectionOffset <= scrollbarLocation ) {
$('.icons').removeClass('iconactive');
$(this).children('.icons').addClass('iconactive');
}
});
});
DEMO
you need to define scrollLink and you can give some animation effect when you click an anchor link by adding a function like this
$(document).on('click', 'a[href^="#"]', function (event) {
event.preventDefault();
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top
}, 1000);
});
Demo : http://jsfiddle.net/3xmop98u/
I think you are missing var scrollLink = $('.myanimate'); in your code. Adding this line in your DEMO make the code work.
$(window).scroll(function() {
var scrollbarLocation = $(this).scrollTop();
var scrollLink = $('.myanimate');
scrollLink.each(function() {
var sectionOffset = $(this.hash).offset().top - 70;
if ( sectionOffset <= scrollbarLocation ) {
$('.icons').removeClass('iconactive');
$(this).children('.icons').addClass('iconactive');
}
});
});
$(".myanimate").click(function (){
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
});

Remove class when scrolled to the href atribute

Currently I remove class from the element in 2000
setTimeout(function(){
$('.nav-item a').removeClass('active');
}, 2000);
How can I amend my code to remove class when the 'autoscroll' is finished?
$('.nav-item a, .nav-brand a, .button, .footer2 a').click(function() {
event.preventDefault(); // default action of the event will not be triggered, eg will not change links name
var windowSize = $(window).width();
if (windowSize >= 769) {
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top - 51
}, 1500);
}
else if (windowSize <= 768) {
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top - 102
}, 1500);
}
return false; });
I guess I should somehow use attribute href, but I am not sure how.
You can do it by defining a complete callback into animate method.
$('.nav-item a, .nav-brand a, .button, .footer2 a').click(function() {
event.preventDefault(); // default action of the event will not be triggered, eg will not change links name
var windowSize = $(window).width();
var scrollY;
if (windowSize >= 769) {
scrollY = $($(this).attr('href')).offset().top - 51;
} else {
scrollY = $($(this).attr('href')).offset().top - 102;
}
$('html, body').animate({
scrollTop: scrollY
}, 1500, function() {
$('.nav-item a').removeClass('active');
});
return false;
});
JQuery Animate takes a final argument complete function, so you should be able to write something like:
$('.nav-item a, .nav-brand a, .button, .footer2 a').click(function() {
event.preventDefault();
var windowSize = $(window).width();
if (windowSize >= 769) {
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top - 51
}, 1500, function() {
$('.nav-item a').removeClass('active');
});
} else if (windowSize <= 768) {
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top - 102
}, 1500, function() {
$('.nav-item a').removeClass('active');
});
}
return false;
});

jQuery animate callback with promise still fires too early

I scroll my homepage back up if the logo in my menu is clicked. I also have a listener on $(window).scroll() which animates an object out of the screen with a negative margin.
My problem is that this event gets triggered with the animation (animate scrollTop).
This shouldn't occur because I have a boolean variable which has to be true to do this, I only set this on true AFTER the scroll animation using a combination of .promise() and .done().
This is my JavaScript:
var firstscroll=true;
$(function(){
var captionWidth= $(".caption").children().size() * 35;
$(".caption").width(captionWidth);
$(window).scroll(function() {
if(firstscroll){
$(".hidden-menu").removeClass("hidden-menu", {duration:500});
$('.header').animate({
marginTop: $('.header').height() * -1
}, 500);
$('html, body').animate({
scrollTop: 0
}, 500);
firstscroll = false;
}
});
$(".menu-logo, .logo-container").click(function(){
$('.header').animate({
marginTop: 0
}, 500);
$('html, body').animate({
scrollTop: 0
}, 500).promise().done(resetFirstScroll());
});
});
var resetFirstScroll = function() {
firstscroll=true;
}
A solution would be to give the function a setTimeout of 50 milliseconds, but I'd rather do it correctly after the animation is completed.
Using the standard callback gives the same output:
$(".menu-logo, .logo-container").click(function(){
$('.header').animate({
marginTop: 0
}, 500);
$('html, body').animate({
scrollTop: 0
}, 500, function() {
resetFirstScroll();
});
});
});
var resetFirstScroll = function() {
firstscroll=true;
}
For those who want the "hacky" solution:
var firstscroll=true;
$(function(){
var captionWidth= $(".caption").children().size() * 35;
$(".caption").width(captionWidth);
$(window).scroll(function() {
if(firstscroll){
$(".hidden-menu").removeClass("hidden-menu", {duration:500});
$('.header').animate({
marginTop: $('.header').height() * -1
}, 500);
$('html, body').animate({
scrollTop: 0
}, 500);
firstscroll = false;
}
});
$(".menu-logo, .logo-container").click(function(){
$('.header').animate({
marginTop: 0
}, 500);
$('html, body').animate({
scrollTop: 0
}, 500, function() {
setTimeout( resetFirstScroll, 50 );
});
});
});
var resetFirstScroll = function() {
firstscroll=true;
}

How can i combine this codes? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
As the title says, I think this code can be simplified in less lines. Could someone help me with this?
$('a[href=#over]').click(function(){
$('html, body').animate({
scrollTop: $("#over").offset().top - 100
}, 2000);
});
$('a[href=#diensten]').click(function(){
$('html, body').animate({
scrollTop: $("#diensten").offset().top - 100
}, 2000);
});
$('a[href=#portfolio]').click(function(){
$('html, body').animate({
scrollTop: $("#portfolio").offset().top - 100
}, 2000);
});
$('a[href=#contact]').click(function(){
$("html, body").animate({ scrollTop: $(document).height() }, 2000);
});
$('a[href=#top]').click(function(){
$('html, body').animate({scrollTop:0}, 2000);
return false;
});
I was thinking myself off an if/elseif statement, but im kinda stuck in there. So could you please have an look?
You can use the href attribute of anchors for selecting the element by IDs.
$('a').click(function(){
var id = this.href;
$('html, body').animate({
scrollTop: $(id).offset().top - 100
}, 2000);
});
$('a').click(function(e) {
e.preventDefault();
var id = this.href;
var scroll = '';
if (id === '#contact') {
scroll = $(document).height();
} else if (id === '#top') {
scroll = 0;
} else {
scroll = $(id).offset().top - 100;
}
$('html, body').animate({
scrollTop: scroll
}, 2000)
});
This wasn't tested. It is just your code that I minified (and optimized a little bit).
$('a[href]').click(function(){
var href = $(this).attr('href');
var htmlbody = $('html,body');
if( href == '#over' || href == '#diensten' || href == '#portfolio' )
htmlbody.animate({ scrollTop: $(href).offset().top - 100 }, 2000);
if( href == '#contact' )
htmlbody.animate({ scrollTop: $(document).height() }, 2000);
if( href == '#top' )
htmlbody.animate({ scrollTop: 0 }, 2000);
});
$('a').click(function(){
var id = $(this).attr("href");
if(id in {"#over": 1, "#diensten": 1, "#portfolio": 1}) {
$('html, body').animate({ scrollTop: $(this).offset().top - 100 }, 2000);
}
else if(id === "#contact") {
$("html, body").animate({ scrollTop: $(document).height() }, 2000);
}
else {
$('html, body').animate({scrollTop:0}, 2000);
return false;
}
});
Since you're only consolidating a process, there are countless answers. But in case you need to micromanage targets, you can do something like:
function reusable_scroll_anchor( q_ids, q_off ) {
for( var q_id in q_ids )(function(q_id) {
$("a[href=#" + q_id + "]").click(function(){
$('html, body').animate({
scrollTop: $("#" + q_id).offset().top - q_off
}, 2000);
});
})(q_ids[q_id]);
}
reusable_scroll_anchor(
['over', 'diensten', 'portfolio', 'contact', 'top' ],
100
);
Though this approach requires some manual tending, it's a reusable snippet for future sites.

Categories