JavaScript / JQuery - How to temporarily disable function after use? - javascript

I have a simple JS that would smoothly autoscroll to another div whenever mousewheel is moved up or down.
Here's the script:
$(document).bind('mousewheel', function(evt) {
var delta = evt.originalEvent.wheelDelta
if(delta < 0){
$('html, body').animate({
scrollTop: $("#content-wrapper").offset().top
}, 3000);
}
else {
$('html, body').animate({
scrollTop: $("#bgheader").offset().top
}, 3000);
}
});
My problem is that if i play for a few seconds with the mousewheel it would start scrolling here and there forever, since every move recorded is queued as additional script launch.
Is there any way to put some sort of 'cooldown' to the script? So that after using once it would become avaiable to use again in, let's say' 3 seconds? Or once the animation is finished?

You can unbind the wheel event listener, and then use jQuery's .animate() callback function to re attach the event listener after it is done, like so:
function scrollHandler (event) {
$(document).off("mousewheel.custom");
var delta = event.originalEvent.wheelDelta
if(delta < 0){
$('html, body').animate({
scrollTop: $("#content-wrapper").offset().top
}, 3000, function () {
// animation callback function
$(document).on("mousewheel.custom", scrollHandler);
}));
}
else {
$('html, body').animate({
scrollTop: $("#bgheader").offset().top
}, 3000, function () {
// animation callback function
$(document).on("mousewheel.custom", scrollHandler);
});
}
}
// namespace the event so we can easily .off() it
$(document).on('mousewheel.custom', scrollHandler);

I've used timeouts.
var maxPoll = 3000,
eventActive = false;
$(document).bind('mousewheel', function(evt) {
if(eventActive) {
return
} else {
setTimeout(maxPoll, function() { eventActive = True })
}
var delta = evt.originalEvent.wheelDelta
if(delta < 0){
$('html, body').animate({
scrollTop: $("#content-wrapper").offset().top
}, maxPoll);
}
else {
$('html, body').animate({
scrollTop: $("#bgheader").offset().top
}, maxPoll);
}
});
It's rough and it uses globals, but it basically turns off your event while the animation is running.

Related

JQuery .resize function running code x times resized

I now use CSS Media queries for my carousels and the buttons. But for the scroll animation to work properly I need Jquery. The problem I'm having is that if I resize to a device resolution and back to desktop, doing that 3 times means the code will run 3 times. so doing that 6 times, it will run the code 6 times.
Jquery:
function setupButtons() {
if ($(window).width() > 1198) {
if ($('#carousel-a').is(':visible')) { // desktop
$("#OnzeDiensten").click(function(a) {
a.preventDefault();
$('html, body').animate({
scrollTop: $("#OnzeDienstenHeading").offset().top - 80
}, 2000);
alert(" MAIN!");
});
}
}
if ($(window).width() < 992) { // device
if ($('#carousel-d').is(':visible')) {
$("#OnzeDienstenDevices").click(function(b) {
b.preventDefault();
$('html, body').animate({
scrollTop: $("#OnzeDienstenHeadingDevice").offset().top - 80
}, 2000);
alert("DEVICE!");
});
}
}
if ($(window).width() < 1198 && $(window).width() > 992) { // tablet
if ($('#carousel-e').is(':visible')) {
$("#OnzeDienstenResponsive").click(function(c) {
c.preventDefault();
$('html, body').animate({
scrollTop: $("#OnzeDienstenHeadingResponsive").offset().top - 80
}, 2000);
alert("RESPONSIVE!");
});
}
}
}
function resizeAnimatedScreenButton() {
var resizeTimeout;
$(window).resize(function() {
clearTimeout(resizeTimeout);
if ($(window).width() > 1198) {
resizeTimeout = setTimeout(function() {
if ($('#carousel-a').is(':visible')) { // desktop
$("#OnzeDiensten").click(function(a) {
a.preventDefault();
$('html, body').animate({
scrollTop: $("#OnzeDienstenHeading").offset().top - 80
}, 2000);
alert(" MAIN!");
$('#carousel-a').unbind();
});
}
}, 500);
}
if ($(window).width() < 992) { // device
resizeTimeout = setTimeout(function() {
if ($('#carousel-d').is(':visible')) {
$("#OnzeDienstenDevices").click(function(b) {
b.preventDefault();
$('html, body').animate({
scrollTop: $("#OnzeDienstenHeadingDevice").offset().top - 80
}, 2000);
alert("DEVICE!");
$('#carousel-d').unbind();
});
}
}, 500);
}
if ($(window).width() < 1198 && $(window).width() > 992) { // tablet
resizeTimeout = setTimeout(function() {
if ($('#carousel-e').is(':visible')) {
$("#OnzeDienstenResponsive").click(function(c) {
c.preventDefault();
$('html, body').animate({
scrollTop: $("#OnzeDienstenHeadingResponsive").offset().top - 80
}, 2000);
alert("RESPONSIVE!");
$('#carousel-e').unbind();
});
}
}, 500);
}
});
} // end resizeanimation
$(document).ready(function() {
setupButtons();
resizeAnimatedScreenButton();
});
CSS Media Queries:
#media (min-width:1198px)
.carousele, .carouseld, .DienstResponsive, .DienstDevice {
display:none!important;
}
#media (max-width:1197px) and (min-width: 993px)
.carousela, .carouseld, .DienstDesktop, .DienstDevice {
display:none;
}
#media (max-width:992px)
.carousele, .carousela, .DienstDesktop, .DienstDevice {
display:none;
}
The problem is that you attach a .click listener inside the scroll callback :
$(window).resize(function() {
$("#OnzeDiensten").click(function(a) { ... }
})
This means that you are attaching one click listener every time the window is resized by 1 pixel. So if you resize the window by 100 pixels, you attach 100 listeners (!) And when the button is clicked, the code runs 100 times.
Even worse, as I already said in the comments, you are not caching your jQuery objects. So jQuery must traverse the whole DOM and look for each of $('#carousel-a'), $('html, body'), $("#OnzeDienstenDevices"), $("#OnzeDienstenHeadingDevice") and $('#carousel-d') a HUNDRED times, and build this many jQuery objects a HUNDRED times, every time! This is just horrendous, performance-wise.
So 1. CACHE your objects
var $OnzeDiensten = $("#OnzeDiensten");
// and then RE-USE them at will
$OnzeDiensten.click(...)
$OnzeDiensten.animate(...)
$OnzeDiensten.css(...)
and 2. cancel previous click listeners before re-attaching them :
$OnzeDiensten
.off("click") // Remove any previous click listeners
.on("click", function(){ // attaches ONE click listener
// do stuff once
})

JQuery scroll to anchor acting odd

So i've got a script to scroll to an anchor on click. It doesnt seem to work on the "first" click going down. it will jump, rather than scroll. but after the first click, it jumps to the anchor and my menu appears, and then all the links (including the first one that jumped) work fine. im not sure what would cause this, and was wondering if anyone else would have an idea?
I have a JSFiddle, but it works fine there. only when i implement the same code into my site is when it happens.
Thanks
http://spo.comxa.com/
uploaded the files above for testing, same thing is happening.
http://jsfiddle.net/reeceheslop/b59fn43e/
$(document).ready(function () {
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 900, 'swing', function () {
window.location.hash = target;
});
});
Your click function seems to be nested inside of a scroll event listener, so I assume its not being called until something is scrolled. Try moving it to the outside along with the document ready function like this:
document.addEventListener('scroll', function (e) {
var newPos = (window.scrollY * -1) / 5
document.getElementById("header").style.backgroundPosition = "center " + newPos + "px";
var startY = 300;
$(window).scroll(function(){
checkY();
});
function checkY(){
if( $(window).scrollTop() > startY ){
$('.fixednav').slideDown();
}else{
$('.fixednav').slideUp();
}
}
checkY();
});
$(document).ready(function(){
$('a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 900, 'swing', function () {
window.location.hash = target;
});
});
});

All the functions defined for onClick of button are getting called

I have below code in jsp and js. What's happening is irrespective of what button I am clicking both the javascript functions are getting called. I am not sure what am i missing here?
HTML:
<a type="button" id="scrollOffsetDiv" href="dashboard?offloglag=off&duration=${duration}#offset">Offset</a>
<a type="button" id="scrollMsgDiv" href="dashboard?offloglag=off&duration=${duration}#offset">Msg</a>
JS:
$(document).on("click","#scrollOffsetDiv", setTimeout(scrollOffsetDiv,3000));
function scrollOffsetDiv() {
var scrollTop = $(window).scrollTop(),
elementOffset = $('#offset').offset().top,
scrollDistance = (scrollTop-elementOffset);
alert("2222222222");
$('html, body').animate({
scrollTop: scrollDistance
}, 200);
}
$(document).on("click","#scrollMsgDiv", setTimeout(scrollMsgDiv,3000));
function scrollMsgDiv() {
var scrollTop = $(window).scrollTop(),
elementOffset = $('#msgsbytesinpersec').offset().top,
scrollDistance = (scrollTop-elementOffset);
alert("33333333");
$('html, body').animate({
scrollTop: scrollDistance
}, 200);
}
Adding jsfiddle link.
I was able to get it working with this jQuery code:
$("#scrollOffsetDiv").click(function(){ setTimeout(scrollOffsetDiv,3000); });
function scrollOffsetDiv() {
alert("2222222222");
}
$("#scrollMsgDiv").click(function() { setTimeout(scrollMsgDiv,3000) });
function scrollMsgDiv() {
alert("33333333");
}
Though I believe the main issue was simply needing to wrap your setTimeout function in a function(){}. Doing without that wrapper seems to only work with not parameterized calls to a function... if your calling a function with variables, wrap it in function(){}.
Anyone want to improve my vocabulary on the issue, please feel free. I've only learned this through observation.
An even more elegant way to write it might be:
$("#scrollOffsetDiv").click(function(){ setTimeout(function(){
var scrollTop = $(window).scrollTop(),
elementOffset = $('#offset').offset().top,
scrollDistance = (scrollTop-elementOffset);
alert("2222222222");
$('html, body').animate({
scrollTop: scrollDistance
}, 200);
},3000); });
$("#scrollMsgDiv").click(function() { setTimeout(function(){
var scrollTop = $(window).scrollTop(),
elementOffset = $('#msgsbytesinpersec').offset().top,
scrollDistance = (scrollTop-elementOffset);
alert("33333333");
$('html, body').animate({
scrollTop: scrollDistance
}, 200);
},3000) });

Getting some internal link animation to work

I have this script that opens a new page and scroll down to a id
var jump = function (e) {
if (e) {
e.preventDefault();
var target = $(this).attr("href");
} else {
var target = location.hash;
}
$('html,body').animate(
{
scrollTop: $(target).offset().top
}, 2000, function () {
location.hash = target;
});
}
$('html, body').hide();
$(document).ready(function () {
$('a[href^=#]').bind("click", jump);
if (location.hash) {
setTimeout(function () {
$('html, body').scrollTop(0).show();
jump();
}, 0);
} else {
$('html, body').show();
}
});
What I wanna do is, make it animate the scroll on the current page with internal links. How do I integrate that?
The easiest way would to just use links, like this.
It doesn't require jQuery or javascript, just some elements added to your HTML using IDs as href values
<a id='exampleTop' href='#exampleMiddle'>I'm an example! Click to go down</a>

section scrolling using mousewheel

I'm using the mousewheel plugin to scroll sections of my page.
What I should look into for disabling the function I wrote until the animation has fully completed?
I am running stop() but that only cancels out the animation.
$('section').mousewheel(function(event, delta, deltaX, deltaY) {
$('section' ).waypoint(function(direction){
thisID = $(this);
},{ offset: '25%' });
if (delta > 0) {
console.log('up');
if ($(this).not(":first-child")) {
//$(this).animate(function(){
$('html, body').stop().animate({
scrollTop: thisID.prev().offset().top
}, 1000);
//});
}else {
$('html, body').stop().animate({
scrollTop: thisID.offset().top
}, 1000);
}
}
else if (delta < 0) {
if ($(this).not(":first-child")) {
$('html, body').stop().animate({
scrollTop: thisID.next().offset().top
}, 1000);
}
else {
$('html, body').stop().animate({
scrollTop: thisID.offset().top
}, 1000);
}
console.log('down');
}
return false; // prevent default
});
One way to do this would be to create a "stoplight" variable. Set it to False at the beginning of your function, and then re-set it to True at the end of the animation using the complete argument of the animate() function. Then make the main function only run if this variable is True.
Instead of reinventing the wheel you might want to take a look at things such as fullPage.js.
It will save you from many headaches when you start dealing with touch devices, touch screens, old browsers, kinetic scrolling present in trackpads or Apple laptops...

Categories

Resources