I have an accordion feature that does not adjust the viewport to the top of the open element when it is clicked. View on mobile or small screen size to see what i am talking about: http://startyourlife.com/biz-training/
Here is an example of one that works: http://tympanus.net/Tutorials/FlexibleSlideToTopAccordion/
You will see that if you click it scrolls to the top of that element. Here is the javascript I currently have:
if (section_title.length) {
section_title.click(function () {
if ((!section.hasClass('active')) && (!running)) {
running = true;
var currentHeight, newHeight;
items.each(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
}
});
if (item.length) {
item.addClass('active');
}
sections.each(function () {
if ($(this).hasClass('active')) {
currentHeight = $(this).find('.w-timeline-section-content').height();
$(this).find('.w-timeline-section-content').slideUp();
}
});
newHeight = section_content.height();
if (activeIndex < index) {
$('html').animate({
scrollTop: $('html').scrollTop() - currentHeight
});
}
section_content.slideDown(null, function () {
sections.each(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
}
});
section.addClass('active');
activeIndex = index;
running = false;
});
}
});
}
Fixed it, add this right after the last line "running = false"
var target = $(section);
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
Related
I have a div with a 2 logos in it and on scroll the first logo hides and the second appears using classes. On reverse scroll the second logo should hide and the first reappear. The first is reappearing but the second is hiding then reappearing when I reach the top of the page.
I've been going around in circles and I can't understand why on reverse scroll the 'show-logo' class is reappearing. Can anyone explain why?
JS:
if ($(window).width() > 640){
var scrollTop = $(window).scrollTop();
var header = $(".site-header");
if (scrollTop > 50) {
header.addClass("scrolling");
setTimeout(function() {
header.addClass("show-logo");
}, 500);
}
else {
header.removeClass("show-logo scrolling");
};
} else {
header.removeClass("show-logo scrolling");
}
Thanks in advance.
The setTimeout has no clue that it should not run so it runs. So if you do not want it to execute it, you need to cancel it. Two different ways depending on what you want to happen.
var myTimer = null;
var header = $(".site-header");
var win = $(window);
win.on("scroll", function() {
if (myTimer) {
window.clearTimeout(myTimer)
}
if ($(win.width() > 640) {
var scrollTop = win.scrollTop();
if (scrollTop > 50) {
header.addClass("scrolling");
myTimer = setTimeout(function() {
header.addClass("show-logo");
}, 500);
} else {
header.removeClass("show-logo scrolling");
}
} else {
header.removeClass("show-logo scrolling");
}
});
or
var myTimer = null;
var header = $(".site-header");
var win = $(window);
win.on("scroll", function() {
if ($(win.width() > 640) {
var scrollTop = win.scrollTop();
if (scrollTop > 50) {
header.addClass("scrolling");
if (!myTimer) {
myTimer = setTimeout(function() {
header.addClass("show-logo");
}, 500);
}
} else {
header.removeClass("show-logo scrolling");
if (myTimer) {
window.clearTimeout(myTimer)
myTimer = null
}
}
} else {
header.removeClass("show-logo scrolling");
}
});
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.
and let me tell you in advance that the no-conflict script didnt work either, my issue is this:
I have a site that i made, i made some animations for it, using the animate library and some other animations
$(document).ready(function ($) {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('active');
})
$(this).addClass('active');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 1000, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('.nav-ul-home a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('.navbar-home ul li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll > 100) {
$(".navbar-home").addClass("navbar-section");
$(".nav-ul-home").addClass("nav-ul-section");
}
else{
$(".navbar-home").removeClass("navbar-section");
$(".nav-ul-home").removeClass("nav-ul-section");
}
});
$(function() {
var Accordion = function(el, multiple) {
this.el = el || {};
// more then one submenu open?
this.multiple = multiple || false;
var dropdownlink = this.el.find('.dropdownlink');
dropdownlink.on('click',
{ el: this.el, multiple: this.multiple },
this.dropdown);
};
Accordion.prototype.dropdown = function(e) {
var $el = e.data.el,
$this = $(this),
//this is the ul.submenuItems
$next = $this.next();
$next.slideToggle();
$this.parent().toggleClass('open');
if(!e.data.multiple) {
//show only one menu at the same time
$el.find('.submenuItems').not($next).slideUp().parent().removeClass('open');
}
}
var accordion = new Accordion($('.accordion-menu'), false);
})
and this is my animations script
$(window).on('scroll', function (e) {
var top = $(window).scrollTop() + $(window).height(),
isVisible = top > $('#texto p').offset().top;
$('#texto p').toggleClass('animated fadeInUp', isVisible);
});
$(window).on('scroll', function ($) {
var top = $(window).scrollTop() + $(window).height(),
isVisible = top > $('in img').offset().top;
$('in img').toggleClass('magictime tinRightIn', isVisible);
});
$(window).on('scroll', function ($) {
var top = $(window).scrollTop() + $(window).height(),
isVisible = top > $('in p').offset().top;
$('in p').toggleClass('magictime puffIn', isVisible);
});
I only put some of it cause it basically repeats its self for every case....
now... I have links to both jquery and jquery-min i need the jquery for this code and the jquery-min for the contact form, the problem is that when i have both links the animations dont work...
if i remove the jquery-min link everything is fine but the contact form doesnt work...
maybe if someone has a contact form template that has JS but doesnt need jquery-min the problem is solve..
sorry for my aqward way to post im prety new here.
thanks!
I've got a script that will allow for snap scrolling when you move down but I can't get it to allow the user to scroll back upwards.
var items = $(".item");
var animating = false;
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));
if (!animating) {
$.data(this, 'scrollTimer', setTimeout(function() {
items.each(function(key, value) {
if ($(value).offset().top > $(window).scrollTop()) {
animating = true;
$('body').animate( { scrollTop: $(value).offset().top + 'px' }, 1000);
setTimeout(function() { animating = false; }, 500);
return false;
}
});
}, 50));
}
});
http://jsfiddle.net/kZY9R/77/
You have to do
var body = $("html, body");
and
$(body).stop().animate( { scrollTop: $(value).offset().top)}, 1000,'swing');
Chrome reading body and srolling, Firefox need html to do it
Check Working Fiddle
So I'm having scrolling issues on my site when viewing on mobile browsers. For some reason, scrolling is sometimes stopped or frozen and there is a weird vertical scrolling bar line that appears randomly in the middle of the browser. I have no idea what this could be, I figure it's a js issue between the menu and the project container but not sure if it may be css overflow issue. The link is johnavent.net/projects if you want to view yourself.
Here's my JS for the menu:
var isLateralNavAnimating = false;
//open/close lateral navigation
$('.cd-nav-trigger').on('click', function(event){
event.preventDefault();
//stop if nav animation is running
if( !isLateralNavAnimating ) {
if($(this).parents('.csstransitions').length > 0 ) isLateralNavAnimating = true;
$('body').toggleClass('navigation-is-open');
$('.cd-navigation-wrapper').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
//animation is over
isLateralNavAnimating = false;
});
}
});
And here it is for my project contianers:
$('.cd-single-project').bgLoaded({
afterLoaded : function(){
showCaption($('.projects-container li').eq(0));
}
});
$('.cd-single-project').on('click', function(){
var selectedProject = $(this),
toggle = !selectedProject.hasClass('is-full-width');
if(toggle) toggleProject($(this), $('.projects-container'), toggle);
});
$('.projects-container .cd-close').on('click', function(){
toggleProject($('.is-full-width'), $('.projects-container'), false);
});
$('.projects-container .cd-scroll').on('click', function(){
$('.projects-container').animate({'scrollTop':$(window).height()}, 500);
});
$('.projects-container').on('scroll', function(){
window.requestAnimationFrame(changeOpacity);
});
function toggleProject(project, container, bool) {
if(bool) {
container.addClass('project-is-open');
project.addClass('is-full-width').siblings('li').removeClass('is-loaded');
} else {
var mq = window.getComputedStyle(document.querySelector('.projects-container'), '::before').getPropertyValue('content').replace(/"/g, "").replace(/'/g, ""),
delay = ( mq == 'mobile' ) ? 100 : 0;
container.removeClass('project-is-open');
project.animate({opacity: 0}, 800, function(){
project.removeClass('is-loaded');
$('.projects-container').find('.cd-scroll').attr('style', '');
setTimeout(function(){
project.attr('style', '').removeClass('is-full-width').find('.cd-title').attr('style', '');
}, delay);
setTimeout(function(){
showCaption($('.projects-container li').eq(0));
}, 300);
});
}
}
function changeOpacity(){
var newOpacity = 1- ($('.projects-container').scrollTop())/300;
$('.projects-container .cd-scroll').css('opacity', newOpacity);
$('.is-full-width .cd-title').css('opacity', newOpacity);
$('.is-full-width').hide().show(0);
}
function showCaption(project) {
if(project.length > 0 ) {
setTimeout(function(){
project.addClass('is-loaded');
showCaption(project.next());
}, 150);
}
}
});
(function($){
$.fn.bgLoaded = function(custom) {
var self = this;
var defaults = {
afterLoaded : function(){
this.addClass('bg-loaded');
}
};
var settings = $.extend({}, defaults, custom);
self.each(function(){
var $this = $(this),
bgImgs = window.getComputedStyle($this.get(0), '::before').getPropertyValue('content').replace(/'/g, "").replace(/"/g, "").split(', ');
$this.data('loaded-count',0);
$.each( bgImgs, function(key, value){
var img = value.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
$('<img/>').attr('src', img).load(function() {
$(this).remove();
$this.data('loaded-count',$this.data('loaded-count')+1);
if ($this.data('loaded-count') >= bgImgs.length) {
settings.afterLoaded.call($this);
}
});
});
});
};
Will post CSS if the issue does not lie within the JS but everything is what you would think and how it behaves on desktop.