Closed SilentCicero closed 8 years ago
This MutationObserver design picks up the changes better, although it is a different design using querySelector and ID's.
var listeners = [];
var doc = window.document,
MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
observer;
function ready(selector, fn){
// Store the selector and callback to be monitored
listeners.push({
selector: selector,
fn: fn
});
if(!observer){
observer = new MutationObserver(function(mutations){
for(var i = 0, len = listeners.length, listener, elements; i < len; i++){
listener = listeners[i];
elements = document.querySelectorAll(listener.selector);
for(var j = 0, jLen = elements.length, element; j < jLen; j++){
element = elements[j];
if(!element.ready){
element.ready = true;
listener.fn.call(element, element);
}
}
}
});
observer.observe(doc.documentElement, {
childList: true,
subtree: true
});
}
}
This is my querySelector design:
var watch = []
if (window && window.MutationObserver) {
var observer = new MutationObserver(function (mutations) {
for(var i = 0; i < watch.length; i++) {
if(document.querySelector(watch[i][0]) && !watch[i][3]) {
watch[i][3] = 1;
watch[i][1]();
}else if(!document.querySelector(watch[i][0]) && watch[i][3]) {
watch[i][2]();
watch.splice(i, 1);
}
}
})
observer.observe(document.body, {childList: true, subtree: true})
}
function onload (el, l, u) {
l = l || function () {}
u = u || function () {}
watch.push([el, l, u, 0])
}
So the idea here, when there is a mutation, check all listeners for the element. If the element exists and it is not marked as "ready" (i.e. watch[i][3]) then fire the onLoad listener. If the element is marked as "ready" and the element can be found in the querySelection, mark as unloaded.
I believe this to be the most reliable for checking if an element exists with querySelection.
Another approach would be to walk through the children like so, this way we really cover all our bases:
var watch = []
function walkChildren (node, visit) {
visit(node)
for (var i = 0; i < node.childNodes.length; i++) {
walkChildren(node.childNodes[i], visit)
}
}
if (window && window.MutationObserver) {
var observer = new MutationObserver(function (mutations) {
for (var i = 0; i < mutations.length; i++) {
var mutation = mutations[i]
var x, y
for (x = 0; x < mutation.addedNodes.length; x++) {
for (y = 0; y < watch.length; y++) {
walkChildren (mutation.addedNodes[x], function(node){
if (watch[y][0] === node) {
watch[y][1]()
}
});
}
}
for (x = 0; x < mutation.removedNodes.length; x++) {
for (y = 0; y < watch.length; y++) {
walkChildren (mutation.removedNodes[x], function(node){
if (watch[y][0] === node) {
watch[y][2]()
watch.splice(y, 1)
}
});
}
}
}
})
observer.observe(document.body, {childList: true, subtree: true})
}
function onload (el, l, u) {
l = l || function () {}
u = u || function () {}
watch.push([el, l, u])
}
With >= 2.1.0
this should now be fixed. Thanks!
try on RequireBin: http://requirebin.com/?gist=8371be058c7c0c087ebe
I'd like onLoad to fire when each component is loaded. However, it only fires when the first component is loaded. The
cb
does not fire for any other component.Thoughts?
I was able to get around this by creating my own MutationObserver, giving each component a unique ID, which then allowed me to select component ID's with my Mutation Observers listeners.
But my observer allows for me to select element by ID.
This is the code for that MutationObserver: http://ryanmorr.com/using-mutation-observers-to-watch-for-element-availability/