Search code examples
javascriptjquerydomjquery-eventsmutation-observers

Is there a way of capturing element state before MutationObserver mechanism fires (onVisibilityChanged)?


I am trying to get the information on change in element state using Javascript MutationObserver
to get what was the state of the element before the change then check what is current state and based on that make some decisions.

Basically I am trying implement onVisibilityChanged event.

I am capturing any change on elements that I care about, then I do check if they are visible or not. Then if visibility is different to what it was broadcast visibilityChanged.
I know workaround I could do, since I am getting changes that happened I could create clone of element (MutationEvent[0].target) and revert apply all changes then check if clone is visible, this however sounds 'hacky' and inefficient so I was wondering is there a way of capturing element right before mutation happened. I do understand it's a long-shot since MutationObserver is fired after all changes happened and it's like travelling in time, yet I am all ears for your suggestions.

var observer = new MutationObserver(function(mutations) {
var itemFromThePast = mutations[0].MagicTimeMachine().GetMeTheItemBeforeItWasChanged; // this is the line that is missing
if ($(itemFromThePast).is(":visible") != $(mutations[0].target).is(":visible"))
      {
       console.log('I win!');
      }
    
});
var targets = $('.ui-collapsible-content');

$.each(targets, function(i,target){
observer.observe(target, { attributes: true, childList: false, characterData : true,     characterDataOldValue : true });
});

Solution

  • One way to do this.
    Works only on visibility changes that are made by class change.

    var observer = new MutationObserver(function(mutations) {
        var clone = $(mutations[0].target).clone();
        clone.removeClass();
        for(var i = 0; i < mutations.length; i++){
            clone.addClass(mutations[i].oldValue);
        }
        $(document.body).append(clone);
        var cloneVisibility = $(clone).is(":visible");
        $(clone).remove();
        if (cloneVisibility != $(mutations[0].target).is(":visible")){
            var visibilityChangedEvent = document.createEvent('Event');
            visibilityChangedEvent.initEvent('visibilityChanged', true, true);
            mutations[0].target.dispatchEvent(visibilityChangedEvent);
        }
    });
    
    var targets = $('.ui-collapsible-content');
    $.each(targets, function(i,target){
        target.addEventListener('visibilityChanged', function(){ console.log('Kaboom babe');});
        observer.observe(target, { attributes: true, attributeFilter : ['class'], childList: false, attributeOldValue: true });
    });