0

I want a click handler that gets fired whenever the user clicks anything on the page. I don't need to know what they clicked on, just that they clicked. (See the note at the end for why I want this.)

Adding an event handler to the document.body works for most pages:

document.body.addEventListener("click", userActivityDetected);

The main thing that doesn't work is if the page has iframes inside it. These are iframes showing content from the same origin (I know that you can't detect anything in cross-origin iframes). If I add the event handlers to each iframe's contentDocument element, I can get the behavior I want. The problem is, my code needs to be generic, so I don't know in advance whether, or how many, iframes a page will have, or even if iframes will be dynamically added after the page loads.

What I really want is a way to add an event listener that applies to the current page and all (same-origin) iframes inside of it. If that's not possible, I'd like a way to detect when an iframe element is added to the page so that I can add the event handler to it.

Why I want this behavior: I want to keep the user's session from timing out if they're "active" on the page. I'm taking clicks and key presses as "active" (I would also be fine with focus changes).

Tom Panning
  • 4,613
  • 2
  • 26
  • 47
  • You could use document.getElementsByTagName('iframe'), then iterate those and add your click event listeners – Ryan Wilson May 02 '18 at 17:50
  • @RyanWilson That would work at the beginning, but wouldn't help if an iframe element is dynamically added after the page loads. – Tom Panning May 02 '18 at 17:57
  • @TomPanning You could add one more `getElementsByTagName('iframe')` that iterates whenever an element is added on the page. – AndrewL64 May 02 '18 at 18:00
  • @TomPanning Building off of AndrewL's comment, this SO post describes how to set up a DOM changed event (https://stackoverflow.com/questions/3219758/detect-changes-in-the-dom) – Ryan Wilson May 02 '18 at 18:03
  • You can also use event delegation, and probably target the window object instead of document.body – mhodges May 02 '18 at 18:11
  • @mhodges calling `window.addEventListener()` has the same behavior :( – Tom Panning May 02 '18 at 18:40

1 Answers1

1

Per @RyanWilson's comment, the fallback solution of detecting when an iframe element is added, and then adding the click handler to it would look like:

function userClicked() {
    console.log("user clicked");
}
function addClickHandler(iframe) {
    iframe.contentWindow.addEventListener("click", userClicked);
}
// Listen to all the iframes that already exist
for (let iframe of document.getElementsByTagName('iframe')) {
    addClickHandler(iframe);
}
// Watch for new iframes
var observer = new MutationObserver((mutationsList) => {
    for (let mutation of mutationsList) {
        for (let addedNode of mutation.addedNodes) {
            if (addedNode.nodeName.toLowerCase() === 'iframe') {
                addClickHandler(addedNode);
            }
        }
    }
});
observer.observe(document.body, {childList: true, subtree: true});
Tom Panning
  • 4,613
  • 2
  • 26
  • 47