1

Hi guys I am using the scroll function on this script but it fires each time a user scrolls. I want it to only fire once when the user scrolls down to #ror. I tried using the fired variable to check if it has already been fired but that didn't seem to work. I know some people have answered this before but this is where i got the fired solution from and cant get it to work only once. Anyone think they can help please?

$( window  ).scroll(function() {
var fired = 0;
    console.log(fired);
    if(fired == 0){
    $('#ror').html('');
    $('#ror').goalProgress({
     goalAmount: 100,
     currentAmount: 75,
     textBefore: 'progress bar',
     textAfter: '',
     offset: 10,
     });
     fired=1;   
   }
});
Pevara
  • 14,242
  • 1
  • 34
  • 47
Mohammed
  • 555
  • 1
  • 6
  • 19

3 Answers3

3

You need to move the fired variable outside the scroll function. As you are doing it now you are reinitializing the fired variable and setting it to 0 each time the scroll event gets fired.

var fired = 0;
$(window).scroll(function() {
    console.log(fired);
    if(fired == 0){
    $('#ror').html('');
    $('#ror').goalProgress({
     goalAmount: 100,
     currentAmount: 75,
     textBefore: 'progress bar',
     textAfter: '',
     offset: 10,
     });
     fired=1;   
   }
});
Aaron Ullal
  • 4,855
  • 8
  • 35
  • 63
  • I did that and it did not work, I checked on console, the 0 turns into a one as soon as I hit scroll. Im trying to allow it to fire once only when the scrollbar reaches it as it is right at the bottom of the page, do you follow me? – Mohammed May 15 '16 at 18:41
3

To detect when a given #target scrolls into view, you can look at it's top position, and check if that position is already inside the viewport.

$('#target').offset().top - $(window).outerHeight() > $(window).scrollTop();

That left part of the equation is constant (as long as you don't move anything around, or change the size of the viewport). Therefore it may be wise to move that outside your event handler function. You need to keep in mind that the scroll event is rather expensive, since it fires constantly when you are scrolling, and the browser is already quite busy with the rendering of the viewport.

When the work is done, you can remove the event handler.

$(window).off(event);

So your final code would look something like this:

var triggerAtY = $('#target').offset().top - $(window).outerHeight();

$(window).scroll(function(event) {
  // #target not yet in view
  if (triggerAtY > $(window).scrollTop()) {
    return;
  }

  // run your task

  // remove this event handler
  $(this).off(event);
}); 

Have a look at the demo: https://jsfiddle.net/6whnfa02/1/

Docs:

Pevara
  • 14,242
  • 1
  • 34
  • 47
  • it doesn't work either way, as i mentioned in the above comment when I check the console log, i see 0 but as soon as I start scrolling I se 1 being fired. I want it to load when I get down to the id only once. – Mohammed May 15 '16 at 19:30
  • sry @Mohammed, I seem to have misread your question (I took the liberty to rephrase it, as I was apparently not the only one). I've updated my answer! – Pevara May 15 '16 at 20:36
1
$(window).scroll(function(event) {
    var eT = $('#ror').offset().top,
    wH = $(this).height(),
    wSt = $(this).scrollTop();
    if(wSt > (eT-wH)) {
      alert('you have scrolled to the ror!');
      //detach scroll event handler, as we dont want it to fire again
      $(this).off(event);
    }
}

The above code checks if user has scrolled down to an element. If yes, alert something and detach the scroll event handler for window. You can refer jquery documentation to see the meaning of offset, height and scrollTop.

Now, as @Pevera pointer out, it is costly to attach event handler to window scroll, you should be aware of that. If you have some heavy code execution inside scroll callback, it will hamper in scrolling the page. So, if you have to attach handler to window scroll, run the scroll callback code within a timeout callback. It ensures to run the scroll callback code after certain delay which helps to scroll the page better. Rewriting the above code with timeout will look like this:

var timeout = null;
$(window).scroll(function (event) {
    if (!timeout) {
        // set a timeout to run after 250ms
        timeout = setTimeout(function () {
            clearTimeout(timeout);
            timeout = null;
            var eT = $('#ror').offset().top,
            wH = $(this).height(),
            wSt = $(this).scrollTop();
            if (wSt > (eT-wH)){
              alert('you have scrolled to the ror!');
              //detach scroll event handler, as we dont want it to fire again
              $(this).off(event);
            }
        }, 250);
    }
});

Everytime user scrolls the page, a timeout is set to run after(atleast) 250ms. In the timeout callback, we remove this timeout handler and check if user has scrolled to the element. If yes, we alert something and detach the scroll handler for window so that it doesn't run again.

Please refer to this FIDDLE for better understanding.

More info on this stackoverflow post and John Resig's blog post.

Community
  • 1
  • 1
Saad
  • 942
  • 6
  • 15