4

How to run doSomething() once when scrolling up or scrolling down?

window.onscroll = function(e) {
   // scrolling up
   if(this.oldScroll > this.scrollY){
      doSomething();
   // scrolling down
   } else {
      doSomething();
   }
   this.oldScroll = this.scrollY;
};

The doSomething() bind some elements and I don't want to do repeat binds. I Just want when on scrolling up, bind once and when on scrolling down bind once.

NAG
  • 341
  • 6
  • 29
  • Your code is good but could be better, you can use `animateframerequest` to be more accurate. – Colin Cline Dec 09 '17 at 01:09
  • I want run just once the doSomething() when scrolling up is fired or scrolling down is fired. – NAG Dec 09 '17 at 01:13
  • Add some state variable that act like thread in c++. like `var triggred = false` and put it in out of scope and also add it to you condition but inside your condition make it `true` so your function never run`doSomething()` twice – Colin Cline Dec 09 '17 at 01:17
  • This is _not_ c++ and usage of a global variable is a) a horrible practice; b) absolutely unnecessary. – Igor Soloydenko Dec 09 '17 at 01:19
  • related question https://stackoverflow.com/questions/4326845/how-can-i-determine-the-direction-of-a-jquery-scroll-event – Dev. Joel Dec 09 '17 at 01:22
  • @IgorSoloydenko who said this is c++? Are you missed "Like threads in c++". P.S: i dont know what kind ppl are in here but every programmer with academic background should know what is "Thread" and how they act. – Colin Cline Dec 09 '17 at 01:22
  • @ColinCline I'm saying you're suggesting a complicated, non-JS-idiomatic approach. Not sure how threads are related to what I said – Igor Soloydenko Dec 09 '17 at 01:24
  • @IgorSoloydenko i didnt said global scope. I said out of this "current" scope. A) a horrible practice?!!? (ok my friend) B) **READ MORE ABOUT DELETE** and after that recommend to other people – Colin Cline Dec 09 '17 at 01:24
  • @ColinCline a) yes, it is. do read about global state. (In fact _any_ unnecessary state is usually bad). b) what's wrong with the delete? ;) – Igor Soloydenko Dec 09 '17 at 01:26
  • @IgorSoloydenko in Javascript we don't have Thread like c++ so we use variables. `delete` should be use in right time and with care there is some nice articles out there (david walsh, sitepont and so on). If using variables as Boolean state is bad practice so thanks for sharing it with us – Colin Cline Dec 09 '17 at 01:30
  • @ColinCline threads have nothing to do with this question. Do read about what `delete` does in JS. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete (Hint: it's not about memory release) And yes, you should not use a variable when you can live without it. – Igor Soloydenko Dec 09 '17 at 01:32
  • just posted an answer for you @NAG see if that helps you out. – Muhammad Omer Aslam Dec 09 '17 at 02:15

2 Answers2

0

If you mean, your function should be executed once per each scroll event, then your code should do the job already.

However, if you mean you want your function to only be executed first time when the user scrolls, the code can look like this:

window.onscroll = function(e) {
  if (this.oldScroll > this.scrollY) {
     doSomething();
  } else {
     doSomethingElse();
  }
  this.oldScroll = this.scrollY;

  delete window.onscroll;
};

Do NOT rely on any kind of "flag variables" as it is proposed above. It is a very bad practice in this scenario!

Igor Soloydenko
  • 11,067
  • 11
  • 47
  • 90
  • The doSomething() bind some elements and I don't want to do repeat binds. I just want when you scrolling up, bind once and if you scroll down bind once. – NAG Dec 09 '17 at 01:24
0

You can have an option of defining the closure function and using it in a way like described in this post

Apart from the above post I came across this situation and i used the following method to check if the event is already registered or not see below function where I needed to bind the click once only I used typeof $._data ( elementClose.get ( 0 ), 'events' ) === 'undefined' to get the events registered with the element, $._data is used to retrieve event handlers registered to an element/

this.closeButtonPreview = () => {
  let elementClose = $("a.close-preview");
  if (typeof $._data(elementClose.get(0), 'events') === 'undefined') {
    elementClose.on('click', function(e) {
      e.preventDefault();
      let container = $(this).parent();
      container.find('video').remove();
      $("#overlay,.window").effect("explode", {}, 500);
    });
  }
  return;
};

EDIT

Just to get the concept clear for you about the logic I used with $._data(). i created an example below.

What i am doing is binding event click to anchor with id=unique inside the condition if (typeof $._data(uniqueBind.get(0), 'events') == 'undefined') { which determines if an event is assigned to the element and binding the event click to the anchor id=multi outside the condition without checking binded events on the element.

What you have to do.

Initially the button unique and multi won't log anything to console, click on EVENT BINDER once and then click on both unique and mutli they both will log text once in console, but as you keep clicking on the EVENT BINDER notice that clicking the multi button will start logging the text as many times as you have clicked the EVENT BINDER button but the unique button will only log once no matter how many times you click on the EVENT BINDER button.

$(document).ready(function() {
  $('#binder').on('click', bindEvents);
  $('#clear').on('click', function() {
    console.clear();

  })
});

function bindEvents() {
  var uniqueBind = $('#unique-bind');
  var multiBind = $('#multi-bind');

  //will bind only once as many times you click on the EVENT BINDER BUTTON
  //check if any event is assigned to the element
  if (typeof $._data(uniqueBind.get(0), 'events') == 'undefined') {
    uniqueBind.on('click', function() {
      console.log('clicked unique bind');
    });
  }

  //will log the text EVENT BINDER * TIMES_EVENT_BINDER_CLICKED button 
  multiBind.on('click', function() {
    console.log('clicked multi bind');
  });

}
body {
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<a href="#." class="btn btn-success" id="binder">EVENT BINDER</a>
<a href="#." class="btn btn-success" id="clear">CLEAR CONSOLE</a>
<br /><br /><br /><br />
<a href="#." class="btn btn-info" id="unique-bind">UNIQUE</a>
<a href="#." class="btn btn-danger" id="multi-bind">MULTI</a>
Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68