Scroll event listener javascript

Javascript

Javascript Problem Overview


Is there a js listener for when a user scrolls in a certain textbox that can be used? Kinda like onclick except for scrolling. I saw https://stackoverflow.com/questions/5669207/html5-event-listener-for-number-input-scroll-chrome-only but that seems to be for chrome only. I'm looking for something cross-browser.

Javascript Solutions


Solution 1 - Javascript

For those who found this question hoping to find an answer that doesn't involve jQuery, you hook into the window "scroll" event using normal event listening. Say we want to add scroll listening to a number of CSS-selector-able elements:

// what should we do when scrolling occurs
function runOnScroll(element) {
  // not the most exciting thing, but a thing nonetheless
  console.log(element);
};

// grab elements as array, rather than as NodeList
const elements = document.querySelectorAll(`...`);

// and then make each element do something on scroll
elements.forEach(element => {
  window.addEventListener(
    "scroll",
    () => runOnScroll(element),
    { passive: true }
  );
});

Or alternatively, bind a single scroll listener, with evt => runOnScroll(evt) as handler and then figure out what to do with everything in elements inside the runOnScroll function instead.

Note that we're using the passive attribute to tell the browser that this event won't interfere with scrolling itself. This is important if we want smooth scrolling behaviour (and also means we shouldn't do perform reflow-triggering DOM updates during scroll).

For bonus points, you can give the scroll handler a lock mechanism so that it doesn't run if we're already scrolling:

// global lock, so put this code in a closure of some sort so you're not polluting.
let locked = false;
let lastCall = false;

function runOnScroll(element) {
  if(locked) return;

  if (lastCall) clearTimeout(lastCall);
  lastCall = setTimeout(() => {
    runOnScroll(element);
    // you do this because you want to handle the last
    // scroll event, even if it occurred while another
    // event was being processed.
  }, 200);

  // ...your code goes here...

  locked = false;
};

Solution 2 - Javascript

I was looking a lot to find a solution for sticy menue with old school JS (without JQuery). So I build small test to play with it. I think it can be helpfull to those looking for solution in js. It needs improvments of unsticking the menue back, and making it more smooth. Also I find a nice solution with JQuery that clones the original div instead of position fixed, its better since the rest of page element dont need to be replaced after fixing. Anyone know how to that with JS ? Please remark, correct and improve.

<!DOCTYPE html>
<html>

<head>
<script>

// addEvent function by John Resig:
// http://ejohn.org/projects/flexible-javascript-events/

function addEvent( obj, type, fn ) {

    if ( obj.attachEvent ) {

        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );};
        obj.attachEvent( 'on'+type, obj[type+fn] );
    } else {
        obj.addEventListener( type, fn, false );
    }
}
function getScrollY() {
    var  scrOfY = 0;
    if( typeof( window.pageYOffset ) == 'number' ) {
        //Netscape compliant
        scrOfY = window.pageYOffset;
    
    } else if( document.body && document.body.scrollTop )  {
        //DOM compliant
        scrOfY = document.body.scrollTop;
    } 
    return scrOfY;
}
</script>
<style>
#mydiv {
    height:100px;
    width:100%;
}
#fdiv {
    height:100px;
    width:100%;
}
</style>
</head>

<body>

<!-- HTML for example event goes here -->

<div id="fdiv" style="background-color:red;position:fix">
</div>
<div id="mydiv" style="background-color:yellow">
</div>
<div id="fdiv" style="background-color:green">
</div>

<script>

// Script for example event goes here

addEvent(window, 'scroll', function(event) {

	var x = document.getElementById("mydiv");

    var y = getScrollY();      
    if (y >= 100) {
        x.style.position = "fixed"; 
        x.style.top= "0";
    } 
});

</script>
</body>
</html>

Solution 3 - Javascript

Wont the below basic approach doesn't suffice your requirements?

HTML Code having a div

<div id="mydiv" onscroll='myMethod();'>


JS will have below code

function myMethod(){ alert(1); }

Solution 4 - Javascript

> Is there a js listener for when a user scrolls in a certain textbox that can be used?

DOM L3 UI Events spec gave the initial definition but is considered obsolete.

To add a single handler you can do:

  let isTicking;
  const debounce = (callback, evt) => {
    if (isTicking) return;
    requestAnimationFrame(() => {
      callback(evt);
      isTicking = false;
    });
    isTicking = true;
  };
  const handleScroll = evt => console.log(evt, window.scrollX, window.scrollY);
  document.defaultView.onscroll = evt => debounce(handleScroll, evt);

For multiple handlers or, if preferable for style reasons, you may use addEventListener as opposed to assigning your handler to onscroll as shown above.

If using something like _.debounce from lodash you could probably get away with:

const handleScroll = evt => console.log(evt, window.scrollX, window.scrollY);
document.defaultView.onscroll = evt => _.debounce(() => handleScroll(evt));

Review browser compatibility and be sure to test on some actual devices before calling it done.

Solution 5 - Javascript

let lastKnownScrollPosition = 0;
let ticking = false;

function doSomething(scrollPos) {
  // Do something with the scroll position
}

document.addEventListener('scroll', function(e) {
  lastKnownScrollPosition = window.scrollY;

  if (!ticking) {
    window.requestAnimationFrame(function() {
      doSomething(lastKnownScrollPosition);
      ticking = false;
    });

    ticking = true;
  }
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKpowerView Question on Stackoverflow
Solution 1 - JavascriptMike 'Pomax' KamermansView Answer on Stackoverflow
Solution 2 - JavascriptNaomi FridmanView Answer on Stackoverflow
Solution 3 - JavascriptSatyaView Answer on Stackoverflow
Solution 4 - JavascriptvhsView Answer on Stackoverflow
Solution 5 - JavascriptTithosView Answer on Stackoverflow