Greasy Fork is available in English.

Reddit Watcher

Consolidated mutation observer handler for use by other reddit userscripts. By itself doesn't do much, but other scripts and use hooks to avoid redundant observers on the same thing.

Auteur
Lawrence Sim
Nombre d'installations quotidiennes
0
Nombre d'installations
341
Évaluations
0 0 0
Version
1.3.2
Créer
2022-03-08
Mis à jour
2022-04-16
Licence
WTFPL (http://www.wtfpl.net)
S'applique à

Reddit Watcher

Consolidated MutationObserver handler for use by other Reddit userscripts. By itself doesn't do much, but other scripts can use hooks to avoid redundant observers watching the same thing. The main benefit being that overloading MutationObservers could slow down the browser. As such, if using multiple userscripts that use this functionality, a centralized handler will avoid unnecessary duplication.

Can use with:

Ensure in userscript dashboard that this is loaded before any dependent scripts by moving it above in the sorted list of installed userscripts.

https://lawrenzo.com/p/reddit-watcher

Buy Me a Coffee at ko-fi.com

Change log

v1.3.2 : Apr 16, 2022

  • Addition checking of post-change on feed could result in feed change event being triggered twice (once for container change, again for post change). Added bit to not double-count here.

v1.3.1 : Mar 10, 2022

  • A few updates to speed things up a bit.
  • Body watcher only looks at childtree. This is enough to detect page changes for the most part. Use more specific observers to check in depth.
  • Listing watcher enabled/disabled based on whether >1 posts found on body update. This keeps observer dormant when viewing a post/comment in isolation.

v1.2.0 : Mar 9, 2022

  • Additional functions added for potential development use.

v1.1.0 : Mar 9, 2022

  • Use unsafeWindow instead of no-sandboxing with @grant none

Development

redditWatcher

Lives as object named unsafeWindow.redditWatcher as simplest way of making itself available to other userscripts. As such, the @grant parameter of the userscript header will need access to unsafeWindow.

Within are three watcher objects for redditWatcher.body, redditWatcher.listing, and redditWatcher.feed. Each handles changes to the document body, the listing outer container, and the post feed respectively.

Hooks

Each watch for updates and changes on the element it is observing, for which hooks can be applied. Updates are defined as anything that would trigger the MutationObserver to detect an update. For listing this include any DOM changes in childlist or subtree. For body and feed, this only includes direct childlist, which for the feed means on any added and/or removed post.

Changes are defined as the element itself being removed and replaced, which will subsequently also fire an update event. This should never happen on the body. When a change does occur, the old MutationObserver is disconnected and a new MutationObserver is created to watch the replacement element. All the existing hooks are carried over to the new observer. Ideally this helps prevent memory leaks from old MutationObserver instances hanging on to references of detached elements and preventing garbage collection.

Note than on some of the watched elements (excluding body), React behavior may occasionally be unpredictable. E.g. swapping from the front page to r/popular may or may not replace the feed container, it may simply empty and repopulate it. As such, a special case is implemented for the feed watcher, which also triggers a change event when the first post is removed and/or changes, in addition to the feed container being replaced.

Usage

To apply a hook, identify the applicable watcher and pass a function to onUpdate() or onChange(). E.g., to add hooks to the feed watcher:

unsafeWindow.redditWatcher.feed.onUpdate((feed, mutated) => {
    mutated.addedNodes.forEach(post => {
        console.log("New post detected");
    });
    mutated.removedNodes.forEach(post => {
        console.log("Post removed");
    });
});
unsafeWindow.redditWatcher.feed.onChange(feed => {
    console.log("Feed changed");
});

The function onUpdate() is provided with the watched element and the array of changes as MutationRecords. The function onChange() is provided with only the watched element. Both append hooks (instead of replacing a singular hook).

Hooks can be removed with un(), passing the original callback/hook to be removed from both the update and change hooks.

More usage

  • update() may be called to manually fire an update event.
  • change() may be called to manually fire a change event (which will subsequently fire an update event).
  • check() may be called to start a manual check for if an element change has occurred. If a change is detected, will also fire a change event (which will subsequently fire an update event).
  • get() will return the element, if found, as searched for in the document. It should be analogous to watching, but instead of returning the stored reference, will dynamically search the document for it when it is called.
  • watching is the current element being watched.
  • watcher stores the current MutationObserver watching the element.
  • observe(elem, options) is a proxy to MutationObserver.observe() on the current MutationObserver.