简体   繁体   中英

Javascript detect when style.display is used regardless of style change

Take the following html:

<div id="somediv" style="display:none;"></div>
<script>
    document.getElementById("somediv").style.display = 'none';
</script>

somediv is already hidden, some javascript runs, effectively doing nothing. I need code that detects when style.display has been used in javascript, regardless of if style was changed or not.

I've tried MutationObserver :

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutationRecord) {
        alert(mutationRecord.target.id);
    });
});
observer.observe(document.getElementById("somediv"), { attributes : true, attributeFilter : ['style'] });

The above only triggers if there was a style change. I need it to trigger regardless if there was a style change or not.

So I did come up with an answer. The way it works, is you grab every script tag, replace .style.display with your own function, and finally replace the DOM (which is the real trick):

//loop through <script> tags
$('script').each(function(){
        var scripthtml = $(this).html();
        if (scripthtml.indexOf('style.display') != -1){
            scripthtml = scripthtml.replace(/.style.display = 'none'/g, ".customdisplay('none')");
            scripthtml = scripthtml.replace(/.style.display = "none"/g, '.customdisplay("none")');
            scripthtml = scripthtml.replace(/.style.display ='none'/g, ".customdisplay('none')");
            scripthtml = scripthtml.replace(/.style.display ="none"/g, '.customdisplay("none")');
            scripthtml = scripthtml.replace(/.style.display='none'/g, ".customdisplay('none')");
            scripthtml = scripthtml.replace(/.style.display="none"/g, '.customdisplay("none")');
            $(this).replaceWith('<script>' + scripthtml + '</script>');
        }

});

Now here is my .style.display replacement function:

HTMLElement.prototype.customdisplay = function(showhide){
    //insert whatever code you want to execute
    this.style.display = showhide;
    alert('Success!  .style.display has been detected!');
};

.replaceWith is what actually changes the DOM. The only thing this script doesn't do, is it isn't able to look through included javascript files . Thank you all for your comments <3.

UPDATE:

When using replaceWith to add the script tag, ipad/iphone/ipod will execute the script tag a second time. to prevent this double execution, you need to do this:

$(this).replaceWith('<script>if (1==0){' + scripthtml + '}</script>');

Your functions will be valid, but anything outside of the function will not be executed.

I don't think you fully realise what you are asking for, but here is a short description of closest options I am aware of:

https://blog.sessionstack.com/how-javascript-works-tracking-changes-in-the-dom-using-mutationobserver-86adc7446401

Basically, MutationObserver is the major improvement over past here that is closest to what you want and supported in modern browsers. But the whole point of all this is it listens to changes.

You are basically asking to detect even non-changes. I don't see you getting out of this problem other than:

Writing a wrapper for the ways you use to change this in code and then instead of calling the change call the wrapper. Simple, easy, requires refactoring all the calls in code.

Overwriting the actual functions that make a change. This saves you the refactor but you are playing with fire here. Rewriting a well-known function on a global level means a PERMANENT source of problems to you and all developers who work on the project.

Polling - in short calling over and over on some element to check properties. Not only it detects changes with a lag of 0 to the polling interval it also uses resources and if you want to monitor everything you will have to write a recursion that descends through the current DOM from the top to each node and check it. You are gonna kill the performance with this. How hard I can't tell but I suspect either polling interval will be long thus increasing the detection lag or your performance will dive down like a gray falcon.

I have 1 big question for you:

What led you to the state where you need this? You basically want the ability for a program to detect when it is using a specific part of itself (be that as it is, a core part, one implemented by the browser). This sounds similar to request: hey whenever I change or not change a value in any variable in my code I should be able to react to it.

I am not trying to sound like Naggin Nancy here but instead encourage you to question train of thought that led to this being something you need and figure out whether you want to sink further time into this, because I don't think you are getting that what you desire easily and I suspect it came to be due to poor design decisions in the past.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM