Search code examples
javascripthtmlcssgreasemonkeyuserscripts

Using Greasemonkey to hide a multilevel parent of select nodes?


What I'm looking to do COULD be accomplished easily if CSS4 standards were in-place. But, I am looking to do something similar with Greasemonkey in the meantime and learn more about parent selectors.

My early attempt looks a little like this:

$(document).find("minds-remind").parentElement.style.display = 'none';

The element I'm looking to access is:

minds-activity < div < div < minds-remind

So if it contains minds-remind, then hide parent minds-activity only in that instance. There are hundreds of minds-activity elements, I only want those containing div div minds-remind to become hidden.

Any help would be much appreciated and I am anxious to better understand how to go about pursuing this in the future. :)


Solution

  • You seem to be trying to use jQuery, so you can use the jQuery :has selector. Like so:

    $(".minds-activity:has('.minds-remind')").hide ();
    


    Or more precise (but also more brittle):

    $(".minds-activity > div > div > .minds-remind").parents (".minds-activity").hide ();
    


    The plain javascript equivalent:

    document.querySelectorAll (".minds-activity > div > div > .minds-remind").forEach ( function (node) {
        node.parentNode.parentNode.parentNode.style.display = "none";
    } );
    

    For AJAX driven pages, use waitForKeyElements(), like so:

    // ==UserScript==
    // @name     _Hiding ancestors of select content
    // @match    http://YOUR_SERVER.COM/YOUR_PATH/*
    // @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
    // @grant    GM_addStyle
    // ==/UserScript==
    //- The @grant directive is needed to restore the proper sandbox.
    
    waitForKeyElements (
        ".minds-activity > div > div > .minds-remind", hideAncestor
    );
    
    function hideAncestor (jNode) {
        jNode.parents (".minds-activity").hide ();
    }
    


    Comparing the "¿good enough?" selector to the more precise/brittle one (Run the code snippet button, below):

    $("button").click ( function (zEvent) {
        $("body > div").removeAttr ("style");
        switch (zEvent.target.id) {
            case "okay":
                $(".minds-activity:has('.minds-remind')").css ("background", "pink");
                break;
            case "precise":
                $(".minds-activity > div > div > .minds-remind").parents (".minds-activity").css ("background", "pink");
                break;
            default:
                console.error ("Missing case in button click handler: ", zEvent.target.id);
                break;
        }
    } );
    body > div {
        margin: 1ex;
        border: 1px solid gray;
        border-radius: 1ex;
        display: inline-block;
    }
    body > div > div {
        display: table;
        height: 3em;
    }
    body > div > div > div {
        display: table-cell;
        vertical-align: middle;
        min-width: 20vw;
        text-align: center;
    }
    button { margin: 1ex; }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    <div class="minds-activity">
        <div><div><div class="">Good</div></div></div>
    </div>
    <div class="minds-activity">
        <div><div><div class="minds-remind">Bad</div></div></div>
    </div>
    <div class="minds-activity">
        <div><div><div><div class="minds-remind">Ugly</div></div></div></div>
    </div>
    <div class="hive-minds">
        <div><div><div class="minds-remind">Martian</div></div></div>
    </div>
    <button id="okay">Test good enough jQuery</button>
    <button id="precise">Test precise jQuery</button>