Skip to content Skip to sidebar Skip to footer

Javascript Event Listener Wait for Function Before Firing Event Again

Introduction

Working with coil events is quite mainstream in JavaScript applications since they are directly tied with many features that include layout changes, lazy loading images, infinite scrolling and then on.

Even the simplest of webpages will have some sort of scroll listeners working behind the scenes to power these very types of features.

In this chapter we will explore all the details to the scroll result in JavaScript and forth with it all the functionalities that can be used along with information technology.

These include sure properties that can give us the scroll position of the webpage as well as a given chemical element; and certain methods that can aid usa in changing the curl commencement of anything programmatically!

After getting yourself familiar with all the concepts taught here, head over to claiming yourself at JavaScript Ringlet Upshot Quiz.

In short, there's a lot to encompass - and so let's begin!

What is scrollable?

Before we tin can heed to scroll events on unlike elements, it's vital to understand when exactly can we do and then.

Allow's sympathize what does it mean to say that an chemical element is scrollable :

A scrollable element is ane that is capable of being scrolled. It has a scroll bar in information technology.

The most common scrollable element on a webpage is the whole certificate itself.

On most all websites out there, we accept a scroll bar on the right hand side of the document implying that the certificate is scrollable.

You can encounter the roll bar on this website every bit well, if you're on a desktop device. On mobile and tablet devices the scroll bar is usually hidden by default, unless we tweak the CSS to show it.

Other elements tin also be made scrollable by using CSS.

When the overflow CSS way property of any HTML chemical element is set to scroll or auto and the content within that chemical element overflows its dimensions, the browser automatically adds a scroll bar to enable viewing that overflowing content.

You can read more most the CSS overflow fashion holding at CSS Overflows.

The ringlet event in JavaScript is just meaningful every bit long as there is a scroll bar in the respective element. If the element is non scrollable, then there is no point of listening to the scroll outcome.

Handling the whorl consequence

Now that we know when is the scroll event meaningful to be handled on any given element, information technology's fourth dimension to swoop into its details.

Each fourth dimension an element is scrolled, a whorl result is fired on it.

How to scroll an element?

Well, at that place are quite a few means to do so. They are listed every bit follows:

  1. By clicking the arrow buttons on the scroll bar.
  2. By dragging the curl bar manually using the mouse pointer.
  3. Using the mouse wheel.
  4. Using the keyboard, by pressing the arrow , keys, or the Page Downward, Page Up keys etc.
  5. Using touch gestures, past swiping through the screen.
  6. Using JavaScript
  7. By visiting an ID link

I interesting case where scrolling gets performed, listed as the last option to a higher place, is when we visit a link referring to an ID, in the HTML document.

Such anchor links have an href attribute that starts with a hash # symbol, for example #article1. Visiting them takes us to the element with the given id. In this example, it will have us to the chemical element with id="article1".

Scrolling increments

In some browsers, when the scrollbar is used to perform the scrolling, it often makes 2px or 3px increments; which means that fifty-fifty if we drag the scrollbar to the shortest of lengths, a 2px alter would incur in the roll position.

The same goes for scrolling washed using keys.

Information technology's usually the impact event that enables a user to curl a webpage at precise 1px increments - all other methods tend to make larger increments.

The JavaScript functionalities used to change the whorl offset, of a webpage or an element, are the properties scrollTop and scrollLeft, as well as the methods scrollTo() and roll().

Oft, when visiting an ID link, the corresponding element'due south top edge is aligned with the pinnacle edge of the viewport.

Once scrolling is done, subsequent actions can exist made using the onscroll handler:

                              targetObject.onscroll = office() {     // handling code }            

..or even by listening to the curl event using addEventListener():

                              targetObject.addEventListener("roll", function() {     // handling code });            

Let'south consider a quick example of treatment the scroll upshot.

A simple example

Beneath we create a <div> element and assign information technology some CSS styles in guild to get in scrollable:

If we want to work with the whorl event, we ought to make sure that the chemical element we'll exist working on is scrollable i.e information technology has a scroll bar.

              <div><p>Some content</p></div>            
              div {     pinnacle: 200px;     overflow: machine;     background-color: #ddd } p {     height: 500px;     /* summit exceeds 200px so a scrollbar volition exist given */ }            

For more info on how to make an element scrollable, consider reading CSS Overflows.

Next, we handle the curlicue event on the <div> element using the onscroll belongings:

              var div = document.getElementsByTagname("div")[0];  div.onscroll = function(east) {     console.log("Scrolling"); }            

Within the handler, nosotros simply log the string 'Scrolling'.

With all this is place, we get the post-obit effect:

Open the console to view the logs made by scrolling this <div>.

Learn AJAX

Scrolling the document

The most common target of the scroll event is the window object i.e the whole HTML document.

It'due south mutual because usually many features of a web application are direct tied with the whole HTML certificate, such equally monitoring advertising impressions, lazy loading images, enabling space scrolling so on.

Following we illustrate scroll treatment, as done on the window object:

              window.onscroll = office(east) {     console.log("Scrolling"); }            

Live Example

Keep, open the link to a higher place and endeavour to gyre the document; you'll see logs filling upwardly the console.

Note that in place of window we can too use certificate.body, as both of them refer to the aforementioned onscroll handler:

              window.onscroll = role(e) {     panel.log("Scrolling"); }  console.log(window.onscroll === document.body.onscroll); // true  document.trunk.onscroll = null; console.log(window.onscroll); // null            

You give an onscroll handler to document.trunk, it will be applied to window; you give it to window, it will be practical to document.torso.

They both are simply interchangeable!

However, for simplicity, developers often employ window - come up on, it'southward seven characters shorter!

Detecting gyre position

In JavaScript, it's typical to figure out how far has the HTML certificate been scrolled, vertically or horizontally, in units of pixels.

The language provides us with iv properties on the window object that enable us to do so.

Ii of them are adequately recent, while the other 2 are from the old ages.

First, for the newer set, we accept the properties scrollX and scrollY . For the older set, we have pageXOffset and pageYOffset .

Equally the names suggest:

The scrollX and pageXOffset properties, both return the altitude past which the document has been scrolled horizontally.

The scrollY and pageYOffset properties, both return the distance by which the document has been scrolled vertically.

All these 4 properties are available on the window object.

Using these properties, we can figure out how far the certificate has been scrolled in a given axis, and consequently power numerous features that rely on this.

Consider the code below:

              window.onscroll = part(due east) {     // log the length scrolled vertically     console.log(window.pageYOffset); }            

Equally before, we are handling the scroll of window, but this fourth dimension, instead of making fixed "Scrolling" logs, we log the vertical scroll distance of the document.

Live Example

To get an agreement of the significance of being able to rails the curl get-go of the certificate, consider the following task.

Write some code to make an alert "Into view" the moment the <div> chemical element shown below comes into view.

                <!--some content here--> <div style="background-color: #ddd">Good to go!</div>              

Once information technology does come into view, remove the curl handler.

Y'all shall assume that the <div> element is 327 pixels abroad from the bottom of the viewport, and apply this value in your scroll handler.

Starting time with the onscroll handler:

                  window.onscroll = office() {     if (window.pageYOffset >= 327) {         window.onscroll = nada;         alert("Into view");     } }                

Now with the roll listener:

                  function scrollListener() {     if (window.pageYOffset >= 327) {         window.removeEventLisener("ringlet", scrollListener);         alarm("Into view");     } }  window.addEventListener("scroll", scrollListener);                

Construct a curlicue handler for window that fixes the #tab element shown below, once its elevation edge touches the top of the viewport.

                <div id="tab-cont">     <!--Fix the following #tab div-->     <div id="tab">Tab</div> </div>              

Post-obit are a couple of CSS styles set up:

                #tab {     background-color: #bbb;     box-sizing: border-box;     padding: 10px; } .fixed {     position: stock-still;     top: 0;     width: 100% }              

To fix #tab, give it the class fixed; and as well to unfix it, remove the grade.

Before you fix #tab, make certain that you requite a custom elevation to its parent #tab-cont considering on fixing #tab, its height will reduce downwardly to 0 and thus crusade the content below information technology to get a leap shift!

Yous shall utilize a JavaScript method to summate #tab'southward height. Try to figure out that method!

Utilize classList for the class addition/removal logic.

Post-obit is the solution:

                  var tab = certificate.getElementById("tab"); var tabRect = tab.getBoundingClientRect(); var tabOffsetTop = tabRect.peak + window.pageYOffset;  // go #tab'due south superlative and give it to #tab-cont tab.parentNode.style.height = tabRect.height + "px";  window.onscroll = function() {     if (window.pageYOffset >= tabOffsetTop) {         tab.classList.add("fixed");     } else {         tab.classList.remove("fixed");     } }                

Live Example

First we call back the #tab element so compute its kickoff from the superlative of the certificate (in line 3, saved in tabOffsetTop).

Later this, we requite its parent a acme value equal to its ain tiptop (in line 6).

Finally we handle the scroll event on window - here nosotros check whether pageYOffset is greater than or equal to tabOffsetTop and if it is then give it the form fixed.

If it'due south not, then nosotros remove this class then that #tab can return dorsum to its original position.

Scrolling an element

Similar to the window object, we tin adhere a curlicue handler to any HTML element nosotros like (plain excluding tags in <head>).

Everything remains the same except for the properties to track the scroll offset.

For window we utilize pageXOffset and pageYOffset (or interchangeably scrollX and scrollY), just for elements, the case is different.

For HTML elements, we use the properties scrollTop and scrollLeft .

Beneath we create a <div> element, give it a couple of CSS styles to make it scrollable, and then finally handle its coil event, where nosotros log both its scrollLeft and scrollTop properties:

              <div id="area">     <p>Some content inside this div.</p> </div>            
              #area {     elevation: 300px;     width: fourscore%;     overflow: auto; } p {     elevation: 600px;     width: 120%; }            

For more info on how to make an element scrollable, consider reading CSS Overflows.

              var area = document.getElementById("expanse"); area.onscroll = function() {     console.log(this.scrollLeft, this.scrollTop); }            

Live Case

In the link given higher up, instead of logging scrollLeft and scrollTop, we display them inside ii <span> elements so that you lot can visualise their values without a trip to the console.

The scrollLeft and scrollTop properties both have ane very interesting feature that can be used to change the scroll offset of an element.

That is, they allow values to exist assigned to them to point to the given whorl position.

Let's discuss on this...

Changing the scroll position

If nosotros assign a value to the scrollLeft or scrollTop belongings, the element on which we call the holding will be scrolled to the provided value.

For instance, if nosotros want to navigate same <div> chemical element above to a 50px vertical scroll offset, we tin can simply assign 50 to its scrollTop property every bit shown below:

              <div id="surface area">     <p>Some content inside this div.</p> </div>            

The CSS for this example is the same as the one shown above.

              var area = document.getElementById("area"); area.scrollTop = 50;            

Live Instance

In the link given to a higher place, we execute the statement div.scrollTop = fifty on the click of a button, so that you can hands visualise the change!

The same thought can as well exist practical to the principal HTML document, however with certain wierd things.

Offset of all, the scrollTop and scrollLeft backdrop are not bachelor on window. This is because window isn't an element, and equally we stated to a higher place, these scroll properties are but bachelor on chemical element objects.

Now it maybe tempting to think that since window.onscroll is analogous to document.torso.onscroll i.e both point to the same handler, nosotros tin can use these properties on document.trunk to curl the HTML document.

In simpler words, to move the document to a given gyre starting time nosotros can apply something like document.body.scrollTop = scrollOffset

Strangely, this doesn't work!

This is because the scrollbar that the browser renders for the document belongs to the <html> element, NOT to the <body> element.

The scrollTop holding can only navigate the caller object's ain scrollbar to the provided value - if information technology own't has any scrollbar then the consignment won't simply piece of work.

To eddy information technology downwardly, scrolling the document using scrollTop or scrollLeft can only exist achieved past using these backdrop on the documentElement object.

In the code below nosotros change the scroll first of the document by assigning a value to the scrollTop belongings of the document.documentElement object:

              // gyre the certificate to 100 pixels vertically document.documentElement.scrollTop = 100;            

Alive Example

Construct a function bringInView() that takes in an element node as statement, and operates by scrolling the document to a position such that the element'due south bottom edge touches the bottom border of the document's viewport.

An example is shown beneath:

The lesser edge of the element, denoted by the blue box, coincides with the bottom border of the document'southward viewport, denoted by the greyness bordered box.

                  function bringInView(ele) {     // summate the altitude of ele's bottom edge from     // the bottom edge of the viewport     var rect = ele.getBoundingClientRect();     var distance = window.pageYOffset + rect.top + rect.height - window.innerHeight;      // now, scroll certificate to the given altitude     document.documentElement.scrollTop = distance; }                

Live Instance

Handling scroll on documentElement has no event.

We just learnt in a higher place that the scrollbar on a webpage belongs to the <html> chemical element, and so would naturally think that scrolling the document would fire scroll events on the documentElement object. Yet this isn't the case!

When we scroll a document, the gyre consequence does Non burn on the documentElement object. This ways that a scroll handler on documentElement wouldn't execute as the document is scrolled, despite the fact that the scrollbar is actually practical on the documentElement object!

                document.documentElement.onscroll = part() {     // scroll treatment code }              

And so what's best to do in this case is to accept this as some sort of bug in the coil behaviour of browsers, and just motion on.

This is just one of the many quirks JavaScript has to show to its novice learners!

DOM methods to scroll

Scrolling the window object in JavaScript is quite foreign if done using the scrollLeft and scrollTop properties.

Likewise, we are provided with three methods to ease in changing the coil offset of window, and of whatsoever element we wish: curlicue(), scrollTo() and scrollBy() .

Following is a discussion on these methods.

curlicue() and scrollTo()

The method ringlet() is available on both Window and Element objects and serves to scroll its caller object to the given set up of co-ordinates.

Beneath shown is the general form of the method as called with two arguments:

                              WindowOrElementObject.scroll(ten,                y)            
  1. x is the altitude from the acme of the caller object.
  2. y is the altitude from the left of the caller object.

The method can as well be provided a ScrollToOptions object with three properties.

                              WindowOrElementObject.curl(options)            
  1. left: same as the x argument
  2. acme: same every bit the y argument
  3. behavior: determines how the scrolling should be done i.e whether information technology should exist performed smoothly using "smooth" or in the blink of an eye using "auto". Past default, it's set up to "auto".

Remember that the beliefs holding has no 'u' in it i.east information technology's spelled as 'behavior' and NOT as 'behavio u r'!

Consider the following code where we demonstrate the curlicue() method chosen with two arguments on the window object:

Executing this piece of code scrolls the certificate precisely to the given co-ordinates i.e 50px from the left of the document and 300px from the top of the document.

Live Example

Permit's now consider an example of calling scroll() with an object argument:

              window.ringlet({     left: 50,     summit: 300,     behavior: "smooth" });            

The co-ordinates are the same as in the code above. The behavior property, set to "smooth", causes the scroll transition to be made smoothly.

Live Example

There is some other method scrollTo() that's exactly the same every bit scroll(). Use one or the other, it'southward upto y'all!

Likewise we'll skip the caption for scrollTo() and instead motion to the tertiary and last method to explore i.e scrollBy().

scrollBy()

Ofttimes times, instead of scrolling to an absolute value as the method scroll() (and fifty-fifty scrollTo()) does, we need to scroll by a given value.

For instance, allow'south suppose that our certificate is currently scrolled 100px vertically.

From this point on, scrolling vertically to 200px would mean we terminate up at 200px. In contrast, scrolling vertically by 200px would hateful we end upward at 300px, since we are now scrolling further by 200px.

Always try to relate the name of a method with its purpose. Information technology helps in 99.9% cases!

The method scrollBy() serves this very purpose.

Syntactically, it works exactly like scroll(), but internally information technology doesn't.

                              WindowOrElementObject.scrollBy(dx,                dy)            
  1. dx is the amount past which to further scroll the caller object horizontally. Negative numbers are valid
  2. dy is the corporeality by which to further curlicue the caller object vertically. Negative numbers are valid.

Consider the lawmaking below:

Nosotros telephone call scrollBy() on window along with passing it two arguments, which will result in the document existence scrolled by these given values.

Live Instance

For the 2d case:

              window.whorl({     left: 50,     top: 300,     behavior: "smooth" });            

Live Example

Detecting roll direction

Sometimes it'south irrelevant to know how far has a document been scrolled in a given axis. Rather, what's relevant is only to know the axis of the scroll.

In other words, nosotros're concerned with figuring out the direction in which the document is currently being scrolled. Is the user going up, or is he/she going downwards?

This can very easily be accomplished using a bit of clever coding!

The cadre of this thought lies in a global variable that holds the concluding gyre according of the document (in this case, the y co-ordinate).

Each time the scroll consequence takes place, we compare the new scroll co-ordinate from this variable, and so decide what is the direction of the curl.

Let's take an example.

Suppose the global variable lastScrollY holds the last coil according of the document. Initially it'southward set up to 0.

The user scrolls the document, and consequently its scroll effect gets dispatched. Inside the issue's handler, the current scroll co-ordinate is retrieved via windown.pageYOffset.

The following expression compares both these values:

                window.pageYOffset > lastScrollY              

What tin we infer about the direction of the scroll from the return value of this expression?

If the expression returns true, this implies that window.pageYOffset is indeed greater than lastScrollY, and consequently the document has been scrolled down.

On the other hand, if the expression returns imitation this implies that window.pageYOffset is lesser than lastScrollY, and therefore the document has been scrolled upwards.

Now that we know about the expression to use to cheque the scroll's direction, let'south finally incorporate information technology into a fully functional piece of lawmaking:

              var lastScrollY = window.pageYOffset;  window.onscroll = function() {     if (window.pageYOffset > lastScrollY) {         panel.log("Scrolling downwards");     }     else {         console.log("Scrolling upwards");     }      // update to the current value     lastScrollY = window.pageYOffset; }            

In line 1, a global variable lastScrollY is created and initialised to whatever location the certificate is scrolled currently.

Side by side we define the onscroll handler on window and put a provisional argument to evaluate the value of the expression and decide based on it the direction of the scroll.

Notice line 12 here - it updates lastScrollY to the latest gyre position so that on subsequent roll events, the right scroll management is detected.

Alive Example

Performance issues

A mutual mistake done while handling the ringlet event is to tie expensive operations with the handler, which results in some serious functioning issues on even loftier-cease devices.

For example, suppose a computationally expensive function is represented as expensiveOperation(). The following code portrays the real trouble:

              window.onscroll = function(e) {     // perform the expensive operation     expensiveOperation(); }            

The reason information technology's a problem is directly related with the behaviour of the curl upshot - how often it fires.

Essentially, all events that fire at high rates, such equally touch, curlicue, mousemove, keydown, volition compromise the performance of an application when tiring processes are carried on in their handlers.

Every bit you know, the scroll event can potentially occur at each pixel you scroll (on touch on devices) on a document. Besides, if we have an expensive operation being processed on it, even a gentle scroll may stack upwardly hundreds of those expensive operations.

This is conspicuously inefficient and thus needs rectification. What'southward the rectification?

We defer the underlying performance.

Defering a scroll event is simply to tiresome downwardly the rate at which its handler's underlying performance is being performed.

At that place are 2 variants of doing this - we can either debounce or throttle the functioning.

Debouncing

In debouncing , what happens is that:

We await until the event doesn't fire for a given amount of time and so perform its underlying operation.

The name comes from electronics where it's used to represent roughly the aforementioned idea - merely one signal is made to be accepted in a given amount of time.

Debouncing means that but when something stops from happening for a certain amount of fourth dimension, like the oscillations of a central on a keyboard, practise we process it.

The way we debounce an onscroll's underlying operation for 500 millseconds is discussed as follows:

We roll the document for, let's say 1px, and consequently the curl event fires in one case. Now imagine that 500 millseconds haven't elapsed since this happened, that we scroll for another 1px. Since this next curl result occured before 500ms passed since the previous event's occurence we don't execute our operation.

Now suppose that 600ms have passed since this second coil issue, that we scroll for another 1px (to account for a total of 3px scroll). Since this time, we've has crossed the 500ms marker, we therefore execute our functioning.

In simple words, debouncing resets a timer each time a new consequence is put upwards before the timer completes.

Live Debouncing Example

This line is very of import - we'll use it to construct a debouncing onscroll handler below.

Rewrite the onscroll handler beneath such that it debounces the console.log() statement for the fourth dimension the scroll event doesn't fire for the next 500 milliseconds, since its final occurence.

You may use setTimeout() for this task.

                window.onscroll = function(e) {     console.log("Hello"); // debounce this }              

At each curl event we clear any timeout already nowadays in the task queue, past using clearTimeout() and passing it timeout which is meant to hold the ID of the last timeout created. Later on this we create a new timeout for 500ms, and salve this inside timeout.

Following is the solution:

                  var timeout = null;  window.onscroll = function(e) {     // clear any previously queued up timeout     clearTimeout(timeout);      // so create a fresh, new timeout     timeout = setTimeout(function(due east) {         console.log("Hello");     }, 500); }                

Live Debouncing Example

Throttling

In throttling what happens is that:

We commencement decide on a time interval and then get the underlying performance to exist performed at those intervals.

Again the proper name comes from computing where information technology's used to represent the idea of decision-making the rate at which a process is happening.

The way nosotros throttle an onscroll's underlying performance for 500 millseconds is discussed as follows:

A constant cheque is being run in the background at every 500ms for whether the user is scrolling or not. The check is implemented by giving a global variable some truthy value inside the onscroll handler - normally and sensibly, the value true, and then comparing the value of this variable inside the constant background check.

If information technology is true, we know that the user has scrolled just recently and consequently perform the underlying operation.

Live Throttling Example

Unlike debouncing, throttling doesn't delay the performance for until the event stops firing - rather it just slows down its rate of execution.

Call up that in both these cases, the actual scroll event isn't being delayed in whatever manner - information technology is just the underlying performance/role/procedure that is being delayed!

Rewrite the onscroll handler below such that it throttles the console.log() statement for 500ms intervals.

Yous may utilize setInterval() for this chore.

                window.onscroll = function(due east) {     console.log("Hello"); // throttle this }              

In scroll throttling, the interval logic and the scrolling logic are both separate from each other, but obviously linked together.

A 500ms interval is running constantly in the groundwork, checking for whether the user is scrolling right now. If scrolling is being performed, the interval makes the console log and finally sets scrolling to fake then that the interval doesn't keep on running!

Post-obit is the solution:

                  var scrolling = simulated; setInterval(role() {     if (scrolling) {         panel.log("Hello");         scrolling = fake;     } }, 500)  window.onscroll = function(eastward) {     scrolling = true; }                

Live Throttling Example

And this is it for scroll events...

neeleytwerfell1939.blogspot.com

Source: https://www.codeguage.com/courses/js/events-scroll-event

Enviar um comentário for "Javascript Event Listener Wait for Function Before Firing Event Again"