10

I would like to know if it's possible and how to transfer a mousewheel/scroll event (scroll attempt by a user) from the header to the container.

I have the following example situations:

+------------+     +------------+|
|   header   |     |   header   ||
+------------+     +------------+|
|           ||     |            ||
|           ||     |            ||
| container ||     | container  ||
|           ||     |            ||
|           ||     |            ||
+------------+     +------------+|
 situation 1        situation 2

Situations


Situation 2 is the 'traditional' setup in which the complete page can be scrolled. When your cursor hovers the header (even though it might be fixed) the scroll attempt is passed along to the body/html. Since the container overflows the body/html the container will move/scroll if a user rotates his/her mousewheel. Because the header is fixed it will stay at the same position.

Situation 1 is my test setup. The container's content overflows the container which will cause the container to show a scrollbar. Now i'd like for the container to also scroll when a user's cursor is hovering the header and the user rotates his/her scrollwheel.

Update 1

a jsfiddle of situation 1

a jsfiddle of situation 2

Update 2

I've created another fiddle to show my progress in which may lie the solution, only I can't get it to work. This might inspire someone else to get the actual solution :) I get the error: (index):69 Uncaught InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched. (For now it's only the scroll event in chrome)

Update 3

This comes closest to my expected solution which is based on 'Other Solution 2'. Thanks to Maksym Stepanenko's research it does not seem to be possible yet. I leave the question unanswered for now in case someone does find a method :)


Other solutions


These questions talk about this issue but don't provide a solution for this setup the way I'd expect it to work:

    1. This won't help because the header issn't placed over the container but above. HTML & JavaScript - Passing the scroll action from one element to another
    1. The accepted answer doesn't transfer the event but just sets the scrollTop. This is not the behaviour the browser provides when scrolling. You can clearly see a difference in the jsFidle in the way the scroll happens when hovering the element or when the scroll is performed normally. The browser makes the scroll smooth, the scrollTop just sets the value making it 'shock'. However, except for the 'shock' part this is very close to the behaviour I'd like to have! Pass mousewheel event through fixed content
Community
  • 1
  • 1
Dex
  • 704
  • 2
  • 9
  • 22
  • 1
    Could you add your HTML to the question. It's vital to the answer as we need to see how the structure fits together to determine event bubbling. – Rory McCrossan Jun 28 '16 at 14:57
  • Yes sure! Give me some minutes :) – Dex Jun 28 '16 at 15:01
  • Couldn't you just create a javascript/jQuery function that scrolls the container, which is called by both the scroll event for the container and the scroll event for the header? – Sgt AJ Jun 28 '16 at 15:05
  • Yes then the solution looks like (if i understand you correctly) 'other solutions 2' in which the scrollTop is set. This is however not as 'fluent' as the browser tends to scroll by itself. You can see the difference in this fiddle (provided with that awnser: http://jsfiddle.net/Toukakoukan/5bwWe/20/), also this example doesn't work in firefox but that could be fixed – Dex Jun 28 '16 at 15:10
  • Why down vote without any reason whatsoever? I mean just provide pointers for me to improve my question... – Dex Jun 28 '16 at 15:24
  • 3
    Some people are on SO just to downvote and then they go on to an other question to do the same. They see a grammar error and downvote. People a weird. – Alexandre Jun 28 '16 at 16:04

3 Answers3

5

I ended up needing this functionality as well.

If you're listening to the "wheel" event, you can get "delta" info about the scrolling. Then you can simply apply the delta to your target div.

document.addEventListener('DOMContentLoaded', function() {
  const target = document.querySelector('#container');

  // listen on the whole document; you could restrict this to an element though
  document.addEventListener('wheel', function(event) {
    target.scrollTop += event.deltaY;
  });
});

I haven't tested this on mobile, though, and I suspect it wouldn't work there.

zjm
  • 51
  • 1
  • 2
  • Thank you for your awnser. Setting the scrollTop method works, but is not an actual scroll event transfer. The reason i'd like the event to be transfered is because of the way the browser responds to a scroll event. It scrolls 'smoothly' when no scrollTop is used. If you use scrollTop the scroll becomes a 'shock' into the new position. Check the difference in scrolling from this fiddle: https://jsfiddle.net/9hydg8sx/8/ – Dex Feb 07 '19 at 14:42
3

After hours of researching this is what I could find.

  1. You can't actually call the browsers default reaction to the event( e.g. scroll) as it happens before the event is dispatched. Something similar is explained here.

  2. What dispatchEvent does - is actually triggering the event for handlers implemented in javascript. e.g. Fiddle

  3. Your only cross-browser way of doing this is the scrollTop with or without different easings (like jquery animate). As even dispatching scroll events works differently for FF and other browsers.

Hope it helps.

Update 1

I found this post which states you can actually simulate the scroll event in Firefox but i could not make it work.

Community
  • 1
  • 1
Max Novich
  • 1,169
  • 9
  • 20
  • Thank you for your research! I tried the other post as well but window.QueryInterface is undefined in both chrome and FireFox so I also don't know how he got it working.. – Dex Jul 04 '16 at 10:02
0

If you are trying to trap the mousewheel event in an iframe and send it to the parent, this is how I got it to work.

In the page that is loaded in the iframe I placed a DIV with the id="everything" that encased the whole BODY of the page

Then, in the bottom of the page that is loaded in the iframe insert this SCRIPT.

 document.getElementById("everything").addEventListener("mousewheel", function (e) {
    parent.scrollme(e.deltaY);
});

then in the parent, I had to insert this SCRIPT near the top

function scrollme( i ){
 window.scrollTo(window.scrollX, window.scrollY + i);

}

This traps the wheelscroll in the iframe and pushes the event to the parent instead.

  • Thank you for your awnser. This users the same principle as @zjm's awnser though the source of the scroll event is different. – Dex Feb 07 '19 at 14:44