I have code like this:
Element.el
(List.concat
[ if tutorial.enabled then
[ Element.Events.onClick (TutorialMsg (Tutorial.Current (Just Tutorial.Search1)))
, Html.Attributes.id (Tutorial.idToString Tutorial.Search1) |> Element.htmlAttribute
]
else
[]
, case tutorial.current of
Just current ->
[ Html.Attributes.classList [ ( Tutorial.observeClass, current == Tutorial.Search1 ) ] |> Element.htmlAttribute ]
Nothing ->
[]
]
)
(search isTutorialSearch1 window locale map state.search)
And such code for observer:
module.exports = {
setup :
function(app) {
var containsObserver = app.ports.containsObserver_701aae30_0dc8_4bbf_9943_c5d1e28e6b07;
var onContains = app.ports.onContains_3feaf185_0702_4f48_a011_ff932defa8df;
var whatToObserve = document.body;
if (containsObserver && onContains) {
var portCallback = function(args) {
var [ canaryId, className ] = args;
var observer = new MutationObserver(function(mutations) {
console.log(mutations);
var elems = document.getElementsByClassName(className);
for(var i = 0; i < elems.length; i++) {
console.log(elems[i].id);
// onContains.send(elems[i].id);
}
mutations.forEach((mutation) => {
if (mutation.type == "childList" && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach(processNode);
} else if (mutation.type == "attributes") {
console.log(mutation);
processNode(mutation.target);
if (mutation.target.id == canaryId) {
clearInterval(intervalID);
mutation.target.remove();
}
}
function processNode(node) {
if (node.classList && node.classList.contains(className)) {
onContains.send(node.id);
}
}
});
});
observer.observe(whatToObserve, {attributes: true, attributeFilter: ['class'], childList: true, characterData: false, subtree:true});
var newDiv = document.createElement("div");
newDiv.id = canaryId
whatToObserve.appendChild(newDiv);
var intervalID = window.setInterval(() => newDiv.classList.toggle(className), 500);
};
containsObserver.subscribe(portCallback);
}
}
};
If I run two times this in devconsole:
document.getElementById("Search1").classList.toggle(observeClass)
I will get notification from observer.
Tested both in Firefox and Chrome.
Here Race Condition? Fetching an element by ID of a view which is yet to be rendered it is adviced to use MutationObserver. Now I am not so sure about it.
Also there are answers on so to better use getElementById
setTimeout
bc observing document.body
may be to slow.
So my question is: does anybody experienced this? How to overcome it?
- https://stackoverflow.com/questions/31659567/performance-of-mutationobserver-to-detect-nodes-in-entire-dom/39332340#39332340
- https://stackoverflow.com/questions/38881301/observe-mutations-on-a-target-node-that-doesnt-exist-yet/38882022#38882022
- https://stackoverflow.com/questions/58036689/using-mutationobserver-to-detect-when-a-node-is-added-to-document
- https://stackoverflow.com/questions/55284360/mutationobserver-detecting-element-appereance-and-changing-of-elements-value/55286019#55286019
- https://stackoverflow.com/questions/10411824/webkit-mutation-observer-callback-not-triggered-when-select-box-attributes-chan
- https://www.smashingmagazine.com/2019/04/mutationobserver-api-guide/
- https://stackoverflow.com/questions/57885450/why-nested-postmessage-will-cause-raf-fired-before-settimeout/57933928#57933928
- https://stackoverflow.com/questions/40614654/does-a-mutationoberserver-callback-fire-within-the-same-animation-frame-in-which
- https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
- https://stackoverflow.com/questions/40647311/are-microtasks-guaranteed-to-fire-within-the-same-animation-frame-where-they-wer
- https://stackoverflow.com/questions/19906947/is-there-anything-faster-than-settimeout-and-requestanimationframe