← Back to context

Comment by doix

1 day ago

Unfortunately, nowadays writing userscripts is much harder than it used to be. Most websites are using some sort of reactive FE framework so you need to make extensive use of mutationObservers (or whatever the equivalent is in jQuery I guess).

I'm not a frontend dev but I came up with this and use it a lot in my userscripts. It's not the most efficient (it can certainly be refactored to create a MutationObserver singleton and then have each call hook into that) but it works well enough for my needs and lets me basically use an old-school to dealing with reactive sites (so long as you are fine with using async):

    function awaitElement(selector) {
        return awaitPredicate(selector, _ => true);
    }

    function awaitPredicate(selector, predicate) {
        return new Promise((resolve, _reject) => {
            for (const el of document.querySelectorAll(selector)) {
                if (predicate(el)) {
                    resolve(el);
                    return;
                }
            }

            // Create a MutationObserver to listen for changes
            const observer = new MutationObserver((_mutations, obs) => {
                // You could search just inside _mutations instead of the entire DOM.
                // Efficiency will depend primarily on how precise your selector is.
                for (const el of document.querySelectorAll(selector)) {
                    if (predicate(el)) {
                        resolve(el);
                        obs.disconnect(); // Don't forget to disconnect the observer!
                        break;
                    }
                }
            });

            // Start observing the document
            observer.observe(document.documentElement, {
                childList: true,
                subtree: true,
                attributes: false,
                characterData: false,
            });
        });
    }

I often go for `setInterval` over `MutationObserver` because it works and I don't need instant reactivity and I don't have to think too much about it.

Very true. I guess that depends on what websites you find issues with? I just checked mine and all of those are quality of life improvements for fully server rendered sites like HN or phpBB forums.

  • Yeah, I mostly use it for QoL improvements but for work related things. So Jira, Bitbucket, GitHub, Linear etc. basically whatever my employer uses. Back in the early 2010s most of that software was fully server rendered. Nowadays it's pretty rare for that to be the case.

    I just try and get LLMs to do it for me because I'm lazy, and they like to use setInterval instead of mutationObservers and if it works, I just live with the inefficiency.

    • The Atlassian stack is particularly bad to extend IMHO given that there are sooooo many API endpoints that their UI calls and most of them are dog slow.