Search code examples
javascriptmousewheel

Not all wheel events are cancelable in Chrome (Opera)


I have found out that not all wheel events can be canceled in Chrome 68 (Opera 55). E.g. there is the following code:

#block {
    width: 10em;
    height: 10em;
    border: 1px solid black;
    overflow: auto;
}

#block div {
    margin: 0.5em;
    padding: 0.5em;
    border: 1px solid blue;
}
<div id="block" onwheel="console.log(event.cancelable)">
        <div>*****</div>
        <div>*****</div>
        <div>*****</div>
        <div>*****</div>
        <div>*****</div>
        <div>*****</div>
</div>

If you run it and try to scroll the block you will see that not all events are cancelable, to wit, there are false values in the console.

However, in case of Firefox all events are cancelable.

It seems to me that when you cancel the first event in a sequence of wheel events, all subsequent events will be canceled as well. But how can I get to know whether there is a sequence of events or there is only one cancelable event?

I need to change the content of a block when a user reaches the bottom of the block. After the content is changed, the block is scrolled up to initial position automatically, and I cancel all events within 100 ms after the content is changed. However, in case of Chrome I change the content after the second/third non cancelable wheel event occurs (because the first one is not canceled when the user hasn't reached the bottom yet), and then I just can't cancel other events, so the block scrolls after the content is changed.

Are there any solutions? And is the behaviour of Chrome correct or maybe it's just a bug?


Solution

  • I have come up with a rather blunt solution. I change the content of the block only when the scroll event is cancelable. In other words, when a series of wheel event is fired, I pay attention only to the cancelable events and if a cancelable event (which is the first in the series) is fired and the bottom of a block has been already reached, I change the content of the block. If an event is not cancelable, it is just ignored.

    Yes, if the bottom of the block has almost been reached, but still not reached yet, there is a kind of blocking effect, since even if a user scrolls a wheel vehemently the content isn't changed when the bottom is reached. However, it's not a big problem to my mind, and an optimization may be applied in this case - the deltaY property of a cancelable event may be taken into account and if it's big enough to scroll the content to the bottom, the event may be canceled, the content may be scrolled programmatically, and then the content may be changed.