-
webfresh
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
-
George
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 ondocument, notwindow: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
gbOverlayOpeneddoes 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-hiddenattribute instead. When any overlay opens, GenerateBlocks Pro setsaria-hidden="false"on the.gb-overlaywrapper, and"true"when it closes. Keep this in your Hook Element onwp_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
loadwrapper 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. -
webfresh
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
-
George
Hi,
Each overlay already has a unique, stable identifier you can target: the
idon the.gb-overlaywrapper — yours isgb-overlay-7214. You can key off that directly, no class needed.In the script, check
panel.idbefore 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-overlaydiv — you’re not missing anything. The Overlay Panel settings don’t expose a class field for that outer wrapper; thegb-overlayelement 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 theidis 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 */ } -
webfresh
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.
-
George
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. -
webfresh
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.
-
George
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 -
webfresh
thanks for the extra suggestion!
-
George
No problem!
- You must be logged in to reply to this topic.