setMutationHandler

MutationObserver wrapper to wait for the specified CSS selector

< Feedback on setMutationHandler

Review: Good - script works

FFW
§
Posted: 12 Oktober 2015

For pages that have many elements to be loaded dynamically..

and quickly, I noticed sometimes it would miss an element or two. Is that normal?

woxxomPembuat
§
Posted: 12 Oktober 2015

Add the code you've used and the page url to test.

FFW
§
Posted: 12 Oktober 2015

Never mind, it turned out that that page had all its elements inside it already. Just had to wait for it to get loaded. Solid script by the way, and I'm really glad I asked about such function back then!

woxxomPembuat
§
Posted: 12 Oktober 2015
Edited: 12 Oktober 2015

BTW sorry for the API change but I've just noticed the observer parameter was used only in 10% of my scripts so I removed it and now it is passed implicitly as this:

setMutationHandler(document, '.container p.some-child', function(nodes) {
    nodes.forEach(function(node) {
        node.style.display = 'none';
    });
    this.disconnect();
    return true; // continue enumerating current batch of mutations
}, {subtree: true, attributes: true, attributeFilter: ['style']});

Also notice the nodes parameter is now passed as an array so you can call all the usual array methods on it directly.

And finally you can pass the fourth parameter options to override the default {subtree:true, childList:true}.

FFW
§
Posted: 12 Oktober 2015
Edited: 12 Oktober 2015

While we at it, selecting a container for baseNode other than document never worked for me

Here is a quick example.. https://www.reddit.com/r/firefox

// ==UserScript==
// @name        Test!
// @namespace   1081920433
// @include     https://www.reddit.com/*
// @version     0.1
// @grant       none
// @run-at      document-start
// ==/UserScript==

setMutationHandler(document.querySelector('#siteTable'), '.may-blank.title', function(nodes) {
    [].forEach.call(nodes, function(n) {
        n.href = 'breakit';
    });
    return true;
});

function setMutationHandler(baseNode, selector, cb, options) {
    var ob = new MutationObserver(function(mutations) {
        for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++)
            for (var j=0, nodes=m.addedNodes, nl=nodes.length, n; (j<nl) && (n=nodes[j]); j++)
                if (n.nodeType == 1) 
                    if ((n = n.matches(selector) ? [n] : n.querySelectorAll(selector)) && n.length)
                        if (!cb.call(ob, Array.prototype.slice.call(n)))
                            return;
    });
    ob.observe(baseNode, options || {subtree:true, childList:true}); 
    return ob;
}
woxxomPembuat
§
Posted: 12 Oktober 2015
Edited: 12 Oktober 2015

That's because at document-start the document is usually empty, occasionally even <head> may not be present entirely, often no <body> element.

FFW
§
Posted: 12 Oktober 2015

I kind of guessed that. Great, and thank you for the update!

§
Posted: 17 Februari 2019
Edited: 17 Februari 2019

Just recently, I start having an issue with the script missing elements as well, while I have a separate script that expands the urls of the posts alongside timestamps (That script included below in the function ExpandPostIDs works fine, it never missed a node, I noticed that sometimes timestamps are being skipped and missed out.

I'm not sure what the issue is.. any help?

https://greasyfork.org/en/scripts/371113-fb-full-timestamps-2019/code

EDIT: So the problem was that the elements that were being missed weren't abbr elements and didn't have a data-utime attribute either.

Adding

setMutationHandler(document, 'abbr[data-utime]', expandDates);
+setMutationHandler(document, '.h_1zif-zjsf.q_1zif-zjsq', expandDatesT);

Did yield a result, but I'm still trying to figure out how to get it to work the original data-utime because just doing that only assigns it an invalid data since the lack of a data-utime attribute

woxxomPembuat
§
Posted: 17 Februari 2019

@JZersche, sounds like a different issue. Try to find what's different about those elements in devtools.

§
Posted: 17 Februari 2019
Edited: 17 Februari 2019

Well, the tittle attribute, doesn't show up until you actually hover on the element, so this one is tricky..

Any ideas?

§
Posted: 17 Februari 2019
Edited: 17 Februari 2019

They removed the abbr attribute which contained the actual time a post was made from recent posts and instead put the time in there dynamically through XHR, so when you hover over something like '10 mins' the time pops up and the title attribute is added. Since it's added after hovering, I don't believe there's a way or at least that I know of to process it because it's not present until it's requested form the server. So, what I did was used moment.js to get the current time, and add that to the class for recently posted statuses, now I made it work only if the innerText of the class contains 'mins' using RegEX, From there I was able to extract the amount of minutes or hours that have passed since the status was made. So my next step is to take that number, and subtract it form the current time. :)

(Sorry for all the comments)

§
Posted: 17 Februari 2019
Edited: 17 Februari 2019

I got it working, I'll also be able to use

abbr.getElementsByClassName("_5pb8 o_1zif-v9x6 _8o _8s lfloat _ohe").getAttribute("href") 

to get the post url's. Might need some tweaking. I'll see.

Post reply

Sign in to post a reply.