I knew you'd respond about the innerHTML... Not that I wanted to leave it out there, but because it worked, and I wanted to see where this goes... some observations of mutations, if you will.
Yesterday Bruce and I spent about 45 minutes flushing out the following mutation observer, by looking through each mutation, expanding and breaking it down looking for anyway to access the right mutation, the add people modal. The sample we worked out uses the mutations classList to find the modal with the people class, but then fails to trigger any time the add people button is clicked.
var mcb = function(mutationsList) {
for(var mutation of mutationsList) {
if(Object.values(mutation.target.classList).indexOf('people') > 1 ) {
if(mutation.addedNodes[0].children[0].firstChild.id == 'add_people_modal')
console.log('doo eet')
}
}
};
var watch = document.body;
var observer = new MutationObserver(mcb);
observer.observe(watch, { childList: true, subtree: true });
Bruce continued...
From what I can tell Googling for mutations, it is just not a thing. Most any developer I see who's dealing with mutations is either making them or writing observers to debug them in their own environment.
What I'm getting at is, each mutation we write against Canvas is basically an investigation worthy of a Badge/r.
For instance, you showed me the following with Custom JavaScript for Admin/Courses Page #comment-112302
Mine:
var callback = function (mList) {
for (var mutation of mList) {
if (mutation.target.dataset.automation == 'courses list' && mutation.target.childNodes.length == init.length) {
try {
var doit = addLinks($('tbody[data-automation="courses list"] tr td:nth-child(2)'))
if (doit == true) break
} catch (e) {
console.log(e)
}
}
}
};
Yours, doesn't even need the mutations:
var callback = function () {
var allItems = document.querySelectorAll('tbody[data-automation="courses list"] tr td:nth-child(2) > a');
var markedItems = document.querySelectorAll('tbody[data-automation="courses list"] tr td:nth-child(2) > a + span');
if (allItems.length > markedItems.length) {
console.log('courses list')
}
};
Bruce's listener is the magic I like, it's why I ignored innerHtml.
(function() {
'use strict';
var pplModal = {};
pplModal.startObserver = function() {
var detectedModal = false;
var mcb = function(mutationsList) {
var mutationHTML = '';
for(var mutation of mutationsList) {
mutationHTML = mutation.target.innerHTML;
if((mutationHTML).indexOf('add_people_modal') > 1 ) {
detectedModal = true;
console.log('doo eet');
break;
}
}
if (detectedModal === true) { observer.disconnect(); }
};
var observer = new MutationObserver(mcb);
observer.observe(document.body, { attributes: true, childList: true, subtree: true });
};
document.getElementById('addUsers').onclick = pplModal.startObserver;
})();
...and last night while watching the Manchurian Candidate, I tinkered with what we tried yesterday and everything else I've tried. I've been trying to solve observer issues with Admin Tray - Sub Account Menu since the day I wrote it. While the rest of the code works really well and continues to improve, the the tray seems to take exponentially longer and longer to open the tray on repeated clicks. This is because the observer never disconnects, and disconnecting would prevent it from work on the next click. My current undocumented solution is don't open the links in a new tab. If I loop through every mutation I can fish out a very specific one, and reduce these issues. I'm still trying to disconnect the observer, but lately I'm mostly playing with properties within mutations.
varv mcb = function(mutationsList) {
for(var mutation of mutationsList) {
if(mutation.addedNodes.length >= 1 && mutation.target.id == 'nav-tray-portal') {
console.log('open tray')
}
if(mutation.removedNodes.length >= 1 && mutation.target.id == 'nav-tray-portal') {
console.log('close tray')
}
}
};
var watch = document.getElementById('nav-tray-portal');
var observer = new MutationObserver(mcb);
observer.observe(watch, { childList: true, subtree: true });
What do we do if we can't find a DOM element?
Combining his and yours, I start seeing reusable patterns for mutation observers.
(function() {
'use strict';
var pplModal = {};
pplModal.startObserver = function() {
var detectedModal = false;
var mcb = function() {
var detectedModal = false;
var findModal = document.getElementById('add_people_modal');
if(findModal) {
detectedModal = true;
console.log('add_people_modal');
}
if (detectedModal === true) { observer.disconnect(); }
};
var observer = new MutationObserver(mcb);
observer.observe(document.body, { attributes: true, childList: true, subtree: true });
};
document.getElementById('addUsers').onclick = pplModal.startObserver;
})();
I know, looking through your Canvancements, that you're pretty good at the observer.disconnect()
I'm trying to figure out best practices... maybe we can write a tutorial, with examples...
We should disconnect, use DOM when possible (because it's easier), and how to fish out mutation properties...
...or just a series of warnings.
I'm going to spend some time this weekend trying to solve my crux on the sub account tray observer. :smileygrin: