I'm working on a Prestashop site project with a particularly fiddly megamenu setup.
The MutationObserver
does a pretty good job of pushing the menu back when the cart overlay is open, but the issue if the menu is dynamically pulled in by another JavaScript library that is obfusticated beyond any rescue and as such the MutationObserver
gets unlinked from the node each time, causing everything to be drawn incorrectly if anything is added to the cart after page load.
The MutationObserver
is currently linked directly to the main page container object (category
).
// CREATE A MUTATION OBSERVER OBJECT TO MONITOR ANY STATE CHANGES ON THE JS NODE
let observer = new MutationObserver(blockCartOpened);
function blockCartOpened(mutationRecords) {
// PROCESS THE LIST OF MUTATION THAT HAVE OCCURED
mutationRecords.forEach (function (mutation) {
// GET THE MUTATION TARGET AND SEE IF THE DISPLAY STYLE ATTRIBUTE IS SET OR NOT
// AND REACT ACCORDINGLY
var target = $(mutation.target);
if(target.hasClass("cart_block")) {
if(target.css("display") == "block") {
$(".ets_mm_megamenu").css("z-index", "-1");
} else {
$(".ets_mm_megamenu").css("z-index", "2");
}
}
mutation.addedNodes.forEach(function(node) {
// Nothing to be here yet...
});
});
}
// SET THE TARGETNODE AS WELL AS THE SETTINGS FOR WHAT TO TRIGGER THE OBSERVER ON, IN THIS CASE
// TRIGGER THE OBSERVER ON ANY CHANGES TO THE STYLE ATTRIBURES OF THE NODE
var targetNodes = document.getElementById("category");
var observerOptions = {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["style"]
}
// SINCE THIS IS A CLASS, A EACH LOOP IS REQUIRED EVEN IF THERE IS ONLY ONE RESULT
observer.observe(targetNodes, observerOptions);
Is there a way to monitor for the attribute changes on created child nodes inside the parent, or is this just a pipe dream?
Well in the end I didn't have to use a MutationObserver, since the issue proved to be unsuited for that sort of solution. So I took the path of least resistence, i.e the solution isn't elegant but it works PERFECTLY:
// BPK: CODE ADDITIONS
$(document).on("click", function(event) {
var target = $(".blockcart-header");
if(target.hasClass("open")) {
$(".ets_mm_megamenu").css("z-index", "-1");
} else {
$(".ets_mm_megamenu").css("z-index", "2");
}
});
$(document).on("click", ".blockcart-header a", function(event) {
var target = $(".blockcart-header");
if(target.hasClass("open")) {
$(".ets_mm_megamenu").css("z-index", "-1");
} else {
$(".ets_mm_megamenu").css("z-index", "2");
}
});
// END BPK
Using a document wide click event to monitor for "closing" clicks and a click event on the trigger button for the cart display just to be sure solved the problem for me.
Lesson: Don't try to go too complicated to solve a problem...