get javascript to run if overlay is open

  • I have an overlay popup with a trigger of time delay. It opens correctly.

    I would like to run some javascript when it is open.

    I created a hook element to display on entire site hooked to wp-footer with this javascript

    
    <script type="text/javascript">
    	
    window.addEventListener('load', function() {
    		 console.log('in script');
        document.addEventListener('gb-overlay-open', function(event) {
    		 console.log('overlay open');
        });
    });
    
    </script>

    It does log the ‘in script’ message but not the ‘overlay open’ message.
    Is this the correct javascript to use?

    I have put site name and needed password to view in private area.

    Also when I view the page in firefox browser I get ‘Empty string passed to getElementById()’ message showing in the console multiple times. It is OK in other browsers.

    Thanks

  • Hi,

    You were on the right track, the event name was just slightly off. The overlay does dispatch events, but they’re named gbOverlayOpened / gbOverlayClosed (camelCase), and they fire on document, not window:

    document.addEventListener('gbOverlayOpened', function (event) {
        console.log('overlay opened', event.detail.overlayId);
    });

    However, there’s an important limitation for your case: these events only fire when the overlay is opened by a trigger element (a click or hover on a button/link). When a panel opens automatically via a time delay (as well as scroll, exit-intent, or custom-event triggers), no trigger element is involved, so gbOverlayOpened does not fire. Since your popup uses the time-delay trigger, listening for that event won’t catch the open.

    For a method that works regardless of how the panel opens, watch the panel’s aria-hidden attribute instead. When any overlay opens, GenerateBlocks Pro sets aria-hidden="false" on the .gb-overlay wrapper, and "true" when it closes. Keep this in your Hook Element on wp_footer:

    <script type="text/javascript">
    window.addEventListener('load', function () {
        document.querySelectorAll('[data-gb-overlay]').forEach(function (panel) {
            new MutationObserver(function (mutations) {
                mutations.forEach(function (m) {
                    if (m.attributeName === 'aria-hidden' && panel.getAttribute('aria-hidden') === 'false') {
                        console.log('overlay open');
                        // your code here — runs each time a panel opens
                    }
                });
            }).observe(panel, { attributes: true, attributeFilter: ['aria-hidden'] });
        });
    });
    </script>

    This watches every overlay on the page and runs your code each time one opens, including time-delay opens. The load wrapper ensures the observer is attached before your time-delay trigger fires.

    Regarding the Firefox “Empty string passed to getElementById()” message: this is coming from a LiteSpeed combined JavaScript file (/wp-content/litespeed/js/...), not from GeneratePress or GenerateBlocks. It’s a non-fatal warning produced by LiteSpeed’s JS optimization and won’t affect functionality. If you’d like to clear it, you can try excluding the relevant script from LiteSpeed’s JS Combine/Optimize settings, or raise it with LiteSpeed support — but it’s safe to ignore.

  • perfect, thank you!!

    I’ve implemented and it works.

    Since it captures the opening of every overlay on the page how would I check that it is the correct overlay – I only want the javascript on a specific overlay.

    At the moment my pages don’t have any other GB overlays, as I’m using a popup plugin , but I will be converting to GB overlays, so I do need to be able to distinguish between them.

    I need some css to target my specific overlay, and in the edit overlay screen there doesn’t seem to be any way to add a class name to the ‘parent’ div of the overlay i.e. the one with the class ‘gb-overlay’. Am I missing something?

    re the ‘Empty string passed to getElementById()’ issue, I’ll open a new topic for that

  • Hi,

    Each overlay already has a unique, stable identifier you can target: the id on the .gb-overlay wrapper — yours is gb-overlay-7214. You can key off that directly, no class needed.

    In the script, check panel.id before running your code:

    <script type="text/javascript">
    window.addEventListener('load', function () {
        var panel = document.getElementById('gb-overlay-7214');
        if (!panel) return;
    
        new MutationObserver(function (mutations) {
            mutations.forEach(function (m) {
                if (m.attributeName === 'aria-hidden' && panel.getAttribute('aria-hidden') === 'false') {
                    // your code here — runs only for this overlay
                }
            });
        }).observe(panel, { attributes: true, attributeFilter: ['aria-hidden'] });
    });
    </script>

    Because it targets one element by ID, there’s no loop and no chance of other overlays triggering it — so when you add more GB overlays later, this stays scoped to just this one.

    On the question of adding your own class to the parent gb-overlay div — you’re not missing anything. The Overlay Panel settings don’t expose a class field for that outer wrapper; the gb-overlay element and its classes are generated by GB Pro, and the editor’s “Additional CSS Class(es)” fields apply to the blocks inside the panel, not the wrapper itself. So the id is the intended hook for targeting a specific overlay, both in JS and in CSS.

    For CSS, you’d use the same ID:

    #gb-overlay-7214 {
        /* styles for just this overlay */
    }
    
    #gb-overlay-7214 .gb-overlay__content {
        /* target the inner content of just this overlay */
    }
  • Thanks

    It’s just that if I create the overlay on dev then copy the content to a new overlay on live, then it doesn’t get the same ID, so I can’t just copy the css from Dev to live

    Also if you want to target multiple different overlays with the same CSS then you have to repeat all the different IDs, rather than having one class that you could add to multiple overlays and then target that.

    Use case: I have multiple overlay banners set up with different wording. They are all set as ‘draft’. I publish one when it is needed. I would like the css to work with any of them.

  • Hi,

    Try adding your own class to a block inside the panel, which you do control. On the top-level Container block inside each overlay, add an Additional CSS Class — for example wf-banner (Block → Advanced → Additional CSS Class(es)). Give that same class to the top container in every banner panel. Because the class lives on your content, it travels with the panel when you copy dev→live, and it’s identical across all your draft banners.

    For the JavaScript, target the panel that contains your class rather than a specific ID:

    <script type="text/javascript">
    window.addEventListener('load', function () {
        document.querySelectorAll('[data-gb-overlay]').forEach(function (panel) {
            if (!panel.querySelector('.wf-banner')) return; // only your banners
            new MutationObserver(function (mutations) {
                mutations.forEach(function (m) {
                    if (m.attributeName === 'aria-hidden' && panel.getAttribute('aria-hidden') === 'false') {
                        // your code here — runs only for panels containing .wf-banner
                    }
                });
            }).observe(panel, { attributes: true, attributeFilter: ['aria-hidden'] });
        });
    });
    </script>

    For the CSS, you can style the inner content directly:

    .wf-banner {
        /* applies to every banner carrying this class */
    }

    Or, if you need to style the overlay wrapper itself (backdrop, width, positioning), use :has() to reach the wrapper based on the class inside it:

    .gb-overlay:has(.wf-banner) .gb-overlay__content {
        /* styles the content of any overlay containing .wf-banner */
    }

    :has() is well supported in current browsers and effectively gives you the “one class on the parent” behaviour you were after, applied from the inside out. Since the class is on a block you control, it copies cleanly between dev and live and works across all your draft banners without repeating IDs — publish whichever banner you need and the same JavaScript and CSS apply automatically.

  • Thanks

    I already had a class on my content but it was the overlay itself that I needed to target.

    Your suggestion of:

    .gb-overlay:has(.wf-banner) .gb-overlay__content {
        /* styles the content of any overlay containing .wf-banner */
    }

    will work well.

    My feedback is that it would be good to be able to put a class on the overlay though.

  • Right, there is no hook to add classes there. You could use the type class.

    eg. all standard overlays get give the class of:

    gb-overlay--standard

  • thanks for the extra suggestion!

  • No problem!

Viewing 10 posts - 1 through 10 (of 10 total)
  • You must be logged in to reply to this topic.