Search code examples
javascriptjquerycssgreasemonkeytampermonkey

Select containing row based on CSS and content


I know how to deal with CSS, so I could create custom filter to block some post's name from some websites with a chrome extension called "stylish".

However, as CSS3 selector not allow to search inverted way, I want to enhance my custom filter using Tampermonkey in Chrome with jQuery or javascript.

What I want is an effect like below with javascript (which doesn't work with CSS3 yet.)

.wordbreak[content="USER_NAME"] < a < tr {display:none!important}

What I meant to do is; find classes named wordbreak also which contains the text 'USER_NAME' for the first, and then set their styles to "display:none" if the "tr" sibling tree is formed as; tr > a > .wordbreak + the inner text is "USER_NAME"

I've look through greasemonkey.org to find something like this one, but I couldn't any clue to how to make it work though. help would be grateful !


Link of the page I want to modify

List of the posts and I want to hide the line of authored by "LibereQ: HTML structure


The first shot :

// ==UserScript==
// @name         Black list
// @match        https://cafe.naver.com/MyCafeIntro*
// @match        https://cafe.naver.com/jssct*
// @match        https://cafe.naver.com/jssct
// ==/UserScript==

document.querySelectorAll('tr > td > div > table > tbody > tr > td > a > .wordbreak').forEach(wordbreak => {
  if (wordbreak.textContent.includes('LiberaQ')) wordbreak.style.display = 'none';
}, 1000);

Solution

  • That script has 3 main problems:

    1. The target pages are AJAX (javascript) driven so you must use AJAX-aware techniques such as MutationObserver or waitForKeyElements.
    2. The selector is overly complicated -- which means:
        (a) you must get it EXACTLY right and missing tds (for example) are deal-breakers
        (b) The script becomes much more brittle (likely to fail on some pages, or in the future).
    3. The @match list is wrong. The actual content you appear to be targeting is in an iframe with an address like: cafe.naver.com/ArticleList.nhn?search....

    The content you want is conveniently marked with a wordbreak class. That is the ideal selector by itself (based on what you've shown). Keep it simple.

    Also keeping the @match simple, but you might be okay with the alternate.

    Here's a complete script that illustrates the process:

    // ==UserScript==
    // @name        Black list
    // @match       https://cafe.naver.com/*
    // @require     https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @require     https://gist.github.com/raw/2625891/waitForKeyElements.js
    // @grant       GM_addStyle
    // @grant       GM.getValue
    // ==/UserScript==
    //- The @grant directives are needed to restore the proper sandbox.
    
    //Possible alternate match:
    // @match       https://cafe.naver.com/ArticleList*
    
    waitForKeyElements (".wordbreak", hideBlackListedNode);
    
    function hideBlackListedNode (jNode) {
        if (jNode.text ().includes ('LiberaQ') ) {
            //jNode.hide ();                             // Hide just the node
            //jNode.closest ("tr").hide ();              // Hide the containing row
            /* Hide the containing row of the containing table
               The .parent() is needed due to a quirk of .closest().
            */
            jNode.closest ("tr").parent ().closest ("tr").hide ();
        }
    }