@jerry_nguyen ,
Yes, you can do this with Mutation Observers, but probably not in the way you are thinking.
A MutationObserver detects a change to underlying DOM. In general, the DOM doesn't necessarily change when you scroll, but it turns out that they do in the Canvas gradebook.
At least they sort of change. The addition or removal of information from the screen triggers a DOM change. That's not the same as scrolling; it's scrolling enough to bring something into the display or take it out of the display. That may be good enough for you.
What you want to look at is div.viewport_1 > div.canvas_1. The selector .canvas_1 appears to be enough to select it.
With horizontal scrolling all of the children of that element. When vertical scrolling, only some of the items change. The vertical scrolling can be detected by observing childList, but to get the horizontal scrolling, you need to add subtree as it doesn't happen directly to a child of .canvas_1.
Adding subtree makes it costly as it now fires for every change within the gradebook, not just those related to scrolling. Clicking on a cell to enter a grade will fire it. So we want to avoid subtree if we can.
We can do that by adding a mutation observer that watches the first row of the gradebook with selector .canvas_1 > div
Here is a code fragment that will do that.
(function(){
'use strict';
const hEl = document.querySelector('.canvas_1 > div');
if (hEl) {
const hObserver = new MutationObserver(() => {console.log('Horizontal Scroll');});
hObserver.observe(hEl, {'childList' : true});
}
const vEl = document.querySelector('.canvas_1');
if (vEl) {
const vObserver = new MutationObserver(() => {console.log('Vertical Scroll');});
vObserver.observe(vEl, {'childList' : true});
}
})();
Here's the problem, though. An element on the .canvas_1 class doesn't exist when the page is loaded. That means that you cannot attach a Mutation Observer to it until it is present. This gets into where I have used Mutation Observers before -- waiting for an element to be present on the page.
To do this, you need to find an element that is present on the page. Viewing the source (Ctrl+U) shows you what is delivered with the page and you can rest assured that it is in the DOM to listen to.
It looks like #gradebook_grid is as close as you're going to get.
Watching the #gradebook_grid element and waiting for .canvas_1 > div to appear under it isn't going to get it exactly, though. I had vertical scrolls show up as additional students were loaded before I ever scrolled. However, the .canvas_1>div element is removed and recreated after the observer was attached and so it's not listening to the final version. I determined this because the code above works when it is entered from the console (after the page is fully rendered) but it does not work when added to a script that runs automatically and waits for it appear. The vertical scroll detection works, but the horizontal one never fires.
A likely candidate is because the first student loaded isn't necessarily the first student displayed (depending on your sort order), but that has to be taken care of.
You would need some way of detecting once the gradebook was completely ready to watch. More likely, you would need to watch .canvas_1 to see if the whole thing is re-rendered, wiping out the >div portion that you were watching.
Now we have a mutation observer to wait for .canvas_1 to appear and then we can attach a listener to .canvas_1 to see when the div elements under it change to detect a possible vertical scroll (or perhaps just loading of additional students) and to see when the div elements under it completely change so that we can add an observer to look for horizontal scrolling.
A much easier way of determining scrolling is by adding an eventListener to the div.viewport_1 element. Element: scroll event - Web APIs | MDN
You will still need to use a mutation observer to wait for the .viewport_1 element to become present on the page. You will also want to request an animation frame as detailed in the link provided.
What looks to be the easiest way right now is to use a Mutation Observer to wait for .viewport_1 to be ready and then a scroll Event Listener once .viewport_1 is ready.