简体   繁体   中英

Hide div if it only contains <script> tags

Similar to this 6-year old question, but I'm not looking at parent elements and wondering if there is a better solution? hide div (it contains only script tag)

Question: My website has some blocks for google adsense advertisements. These blocks are just styled divs (background color, padding, margin, border-radius etc.) There is nothing in them except for the adsense script tags (and of course white space/text nodes, etc.). When a user has an ad block extension/plug-in, these divs still display, but they appear totally empty on the screen, which is not desirable. Therefore, I'm looking for a way to hide these divs if no ad is rendered. Using :empty or does not work since it still picks up the <script> tags.

Div element:

<div class="contentBlock"><script>//adsense code</script></div>

Perhaps there is a better way of tackling or conceptualizing this problem? If so, I'm open to alternative solutions. Thanks!

You can remove the script tags, and then check to see if the blocks are empty. In code that runs after the ad code would run if it were allowed to:

var blocks = $(".contentBlock");
blocks.find("script").remove();
blocks.each(function() {
    var div = $(this);
    if (!div.html().trim()) {
        div.remove();
    }
});

Or if you like chaining a lot:

$(".contentBlock")
    .find("script")
    .remove()
    .end()
    .each(function() {
        var div = $(this);
        if (!div.html().trim()) {
            div.remove();
        }
    });

If you have to support obsolete browsers, use $.trim() instead of the native String.prototype.trim (or polyfill it).

It seems that you need a feature which is on CSS4 proposed list: https://www.w3.org/TR/selectors-4/#has-pseudo

The relational pseudo-class, :has(), is a functional pseudo-class taking a relative selector list as an argument. It represents an element if any of the relative selectors, when absolutized and evaluated with the element as the :scope elements, would match at least one element. ...

The following selector matches elements that don't contain any heading elements:

section:not(:has(h1, h2, h3, h4, h5, h6))

Another workaround is to use jquery to mark divs with content and then remove/hide the others. See fiddle: http://jsfiddle.net/mczv6gys/

$('div.contentBlock').has('p, span, img, div').addClass('markerClass'); // P or any other typical tag
$('div.contentBlock').not('.markerClass').addClass('hideClass'); // eg display:none

You have the ability to either hide the div, or replace it with new content if AdSense hides the content.

If this example isn't working, your going to want to deal with the content dynamically created from Adsense. Such as a check for $("#google_ads_frame1").css('display')=="none") . Instead of checking your container div. Which would work, it was tested.

  • You wrap your content into a container / div for strictly advertisements. Then set a timeout function to determined said issues. If adblock enabled, then show alternative content such as a video, poster, iframe, etc.
  • Since adblock hides stuff with css too, you can then edit the css to ultimately hide everything if enabled instead of replacing. Two options.

Change snippet timeout to whatever time you want to wait to check after page loaded, to handle async ads.

 // Page has loaded window.onload = function(){ // Set a timeout function for async google ads setTimeout(function() { // We are targeting the first banner ad of AdSense var ad = document.querySelector(".ads"); // If the ad contains no innerHTML, adblock is enabled // Or check adsense's generated content // $("#google_ads_frame1").css('display')=="none") if (ad && ad.innerHTML.replace(/\\s/g, "").length == 0) { // Adblock hides with css also, or just hide everything. ad.style.cssText = 'display:block !important; background-color: LightCoral;'; // Replace, if adblock enabled ad.innerHTML = 'We detected adblock'; } }, 1); // Change this to 2000 to run after two seconds, to handle async ads }; 
 .ads { background-color: lightgreen; } 
 <p><b>Example 1:</b> Let us simulate an adblock situation, the <code>script</code> tag did not load, hence adblock</p> <div class="ads"></div> <p><b>Example 2:</b> Let us simulate no adblock, <code>script</code> tag loaded</p> <div class="ads"><script></script>Adblock ran</div> 

If you support ES6 features, you can filter .contentBlock which every nodes satisfy condition is "empty" textNode, is Script or is comment:

 let emptyBlocks = [...document.querySelectorAll('.contentBlock')].filter(block => [...block.childNodes].every(node => (node.nodeName === '#text') ? !node.textContent.trim(): ['SCRIPT','#comment'].includes(node.nodeName) ) ); emptyBlocks.forEach(function(block){ block.classList.add('empty'); }); 
 .contentBlock{ min-height:50px; width:200px; outline: solid 2px red; margin:2px; } .contentBlock.empty{ display: none; } 
 <div class="contentBlock"> <script>//nothing's happened</script><!--comment--> </div> <div class="contentBlock"> <script>document.write('something\\'s happened');</script> </div> <div class="contentBlock"> <!--comment--> <script></script> <!-- empty text nodes with spaces and tabulations --> </div> <div class="contentBlock"> <!--//--> text node </div> 

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