Spinner overlay will not display

I have 2 forms with products using the PayPal checkout addon. They submit to paypal fine and the paypal popup window allows the user to complete the transaction fine and it closes… exposing the gravity form with paypal checkout buttons the user JUST submitted. There is a processing delay before the success message replaces the form. To overcome this delay I created a spinner… a developer has been attempting for a week to get this spinner to display and it will not. I am at a lose. There is css for the spinner in style.css in the child theme, there is code in functions.php for it, added through a wp code snippet in the footer of the form pages. Nothing. It does not appear. The forms function exactly as expected otherwise. This is the php in wp code snippets >>

add_action( ‘wp_footer’, function() {
?>

#paypal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255,255,255,0.8); /* White with 80% opacity /
z-index: 999999;
display: none;
align-items: center;
justify-content: center;
flex-direction: column;
color:
#000*; /* Black text for visibility on white /
font-size: 20px;
text-align: center;
}

#paypal-overlay img.spinner-image {
width: 120px; /
Adjust spinner size */
height: auto;
margin-bottom: 15px;
}

<div id="paypal-overlay">
    <img class="spinner-image" src="https://akroagatemarbles.com/wp-content/uploads/2025/08/akroagatemarbles_spinner1.png" alt="Loading...">
    Completing Transaction...
</div>

<script>
jQuery(document).ready(function($) {

    function attachPayPalListener() {
        if (window.gform_ppcp && window.gform_ppcp.buttons) {
            // Loop through all PayPal buttons
            for (let key in window.gform_ppcp.buttons) {
                let btn = window.gform_ppcp.buttons[key];
                if (btn.originalConfigAttached) continue; // prevent double attach

                let originalConfig = btn.config || {};
                let originalOnApprove = originalConfig.onApprove;

                originalConfig.onApprove = function(data, actions) {
                    $('#paypal-overlay').fadeIn(200);
                    if (typeof originalOnApprove === 'function') {
                        return originalOnApprove.call(this, data, actions);
                    }
                };

                btn.originalConfigAttached = true;
                btn.config = originalConfig;
            }
        }
    }

    // Initial load
    attachPayPalListener();

    // Re-attach after GF renders (for AJAX forms)
    $(document).on('gform_post_render', function() {
        attachPayPalListener();
    });

    // Hide overlay when confirmation loads
    $(document).on('gform_confirmation_loaded', function() {
        $('#paypal-overlay').fadeOut(300);
    });

});
</script>
<?php

});

This is the css added to style.css
img.gform_ajax_spinner {
position: fixed !important;
z-index: 999999;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: block !important;
overflow: hidden !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(255, 255, 255, 0.8); /* White with 80% opacity /
background-image: url(‘https://akroagatemarbles.com/wp-content/uploads/2025/08/akroagatemarbles_spinner1.png’);
background-repeat: no-repeat;
background-size: 8rem; /
Larger spinner */
background-position: center center;
content: “”;
}

Does anyone see something wrong here?? The developer had the spinner showing at one point, FULL PAGE but incorrect colors and styling. With this new code, NOTHING shows at all. The code is supposedly in theglobal footer, but I have mentioned to him there are CUSTOM footers on all pages. The pages are https://akroagatemarbles.com/ and The Store-Book • Akro Agate Marbles they are virtually identical forms with one and two products, use gravity wiz inventory perk and sumbit to paypal checkout sandbox sucessfully, process successfully, show the confirmation message successfully… but there is a lag where a spinner overlay is needed between the time the paypal checkout window closing and the gravity form success message taking the place of the form. That is where the spinner comes in… but it will not display. Can anyone see anything wrong here?? Developer can not figure it out I guess and I need it to work. It has to work. So if anyone has an idea or can point mr to a paid service that can get this working in the next few days please share that information. There has got to be a service that can fix overlay spinner to work.

Thank you

ps. both these forms are in paypal sandbox mode… to test out and see what happens on purchase completion you can use this sandbox paypal password #bNv2’L?

At a quick glance, you have some issues with your CSS.

You are not properly finishing your comments. This will prevent the rest of your CSS from working.

This is a proper comment in css. /*adjust spinner size */

you have / adjust spinner size */

you also have started a comment in your #paypal-overlay but you never closed it.

in #paypal-overlay you also have an * before the ; color #000*;

let’s start by fixing your CSS before diving into any other issues.

I pointed these syntax errors out to the developer and he fixed them. added this code to a code module in divi on the page for the zippos. The Store-Lighters • Akro Agate Marbles

add_action( ‘wp_footer’, function() {
?>

/* Hide Gravity Forms’ default spinner */
img.gform_ajax_spinner {
display: none !important;
}

#paypal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.8); /* Black with 80% opacity */
    z-index: 999999;
    display: none;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    font-size: 20px;
    text-align: center;
}
#paypal-overlay .spinner-text {
    color: red; /* Red text */
    margin-top: 10px;
}
#paypal-overlay img.spinner-image {
    width: 120px; /* Adjust spinner size */
    height: auto;
    animation: spin 1.5s linear infinite; /* Rotate animation */
}
@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
</style>

<div id="paypal-overlay">
    <img class="spinner-image" src="https://akroagatemarbles.com/wp-content/uploads/2025/08/akroagatemarbles_spinner1.png" alt="Loading...">
    <div class="spinner-text">Completing Transaction...</div>
</div>

<script>
jQuery(document).ready(function($) {

    function attachPayPalListener() {
        if (window.gform_ppcp && window.gform_ppcp.buttons) {
            for (let key in window.gform_ppcp.buttons) {
                let btn = window.gform_ppcp.buttons[key];
                if (btn.originalConfigAttached) continue;

                let originalConfig = btn.config || {};
                let originalOnApprove = originalConfig.onApprove;

                originalConfig.onApprove = function(data, actions) {
                    $('#paypal-overlay').fadeIn(200);
                    if (typeof originalOnApprove === 'function') {
                        return originalOnApprove.call(this, data, actions);
                    }
                };

                btn.originalConfigAttached = true;
                btn.config = originalConfig;
            }
        }
    }

    attachPayPalListener();

    $(document).on('gform_post_render', function() {
        attachPayPalListener();
    });

    $(document).on('gform_confirmation_loaded', function() {
        $('#paypal-overlay').fadeOut(300);
    });

});
</script>
<?php

});

I do not understand why he is referencing wp_footer at all. This code is now in a module in the gf module. He is still working on it, but no spinner or overlay is showing up after the paypal window closes.

Try adding your code to your functions.php file and instead of it being asynchronous try using

add_action( ‘wp_footer’, ‘gf_custom_spinner’ );

// Define the function
function gf_custom_spinner() {
// your code here
}

Also Try echoing your style tags.

I would also remove the code that’s currently inside of your divi code module for the page you’re testing this so there aren’t any conflicts.

Hi Drew. The reasoning behind having it in the form module is to only have the overlay on the form, not the entire page. Like the attached image. Only 3 things need to happen. This is so confusing now, I don’t know which way to go. I am not doing the editing. The developer is right now supposedly and it’s been a week already.. according to gravity wiz it’[s a 15 minute thing. lol. I will suggest putting the code in the child theme functions.php, but it has to specifically reference the 2 forms that use paypal checkout, not any others on the website. And why is he referenceing wp_footer at all? Putting the code in the actual form module on the specific page(s) was my idea so that nothing else would be affected.

You can add JavaScript to a Gravity Forms html field.

You can add your overlay, css, and js to a basic html field.

This might be the easiest solution. Adding to wp_footer will add it to every page.

In your JavaScript, try adding display:block; to the PayPal-overlay element. Right now, you have it set to display:none; and you only have a fade in animation. A fade in animation, doesn’t work if the element is set to display:none

Hi Drew. This is what the hired dev came up with that is working.

// Gravity Forms + PayPal: Overlay loader with image spinner (fixed logic)
add_action(‘wp_footer’, function() { ?>

/* Fullscreen overlay */ #paypal-overlay { position: fixed; inset: 0; width: 100vw; height: 100vh; background: rgba(255,255,255,0.85); z-index: 999999; display: flex; align-items: center; justify-content: center; flex-direction: column; color: #f70000; font-family:'Open Sans',sans-serif; font-size: 18px; font-weight: 800; text-transform:uppercase; letter-spacing:.1em; opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility .3s ease; } #paypal-overlay.active { opacity: 1; visibility: visible; } /* Spinner image rotation */ #paypal-overlay img.spinner-image { width: 80px; height: 80px; margin-bottom: 16px; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Hide default Gravity Forms spinner */ .gform_ajax_spinner { display: none !important; } @media (max-width:780px){ .message{ text-align:center; } }
completing request

<scrphp }, 9999);

This is fine and is working great but I somehow knew there would be an issue and there is. This overlay is affecting ALL forms on the website … for instance the newsletter signup at The History of Akro Agate Marbles • Reference and the unsubscribe at The Kro Unsubscribe • Akro Agate Marbles which does not make sense because both those pages need to display error messages if the email already exists in the list or doesn’t match when unsubscribing, but with the overlay on those forms… it’s no good. So how do I specify JUST the order forms? and not every form on the website for this overlay???

shoot. it didn’t post right

// Gravity Forms + PayPal: Overlay loader with image spinner (fixed logic)
add_action(‘wp_footer’, function() { ?>

/* Fullscreen overlay */ #paypal-overlay { position: fixed; inset: 0; width: 100vw; height: 100vh; background: rgba(255,255,255,0.85); z-index: 999999; display: flex; align-items: center; justify-content: center; flex-direction: column; color: #f70000; font-family:'Open Sans',sans-serif; font-size: 18px; font-weight: 800; text-transform:uppercase; letter-spacing:.1em; opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility .3s ease; } #paypal-overlay.active { opacity: 1; visibility: visible; } /* Spinner image rotation */ #paypal-overlay img.spinner-image { width: 80px; height: 80px; margin-bottom: 16px; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Hide default Gravity Forms spinner */ .gform_ajax_spinner { display: none !important; } @media (max-width:780px){ .message{ text-align:center; } }
completing request

<scr
jQuery(function($){
function showOverlay(msg){
if(msg) $(‘#paypal-overlay .message’).text(msg);
$(‘#paypal-overlay’).addClass(‘active’);
}
function hideOverlay(){
$(‘#paypal-overlay’).removeClass(‘active’);
}
function bindForForm(formId){
var $form = $(“#gform_” + formId);
if(!$form.length) return;
// Avoid duplicate bindings if GF re-renders
$form.off(‘submit.paypalOverlay’).on(‘submit.paypalOverlay’, function(){
showOverlay(‘Completing Request’);
});
}
// Initial bind for any forms already on page
$(‘.gform_wrapper form[id^=“gform_”]’).each(function(){
var id = this.id.replace(‘gform_’,‘’);
bindForForm(id);
});
// Re-bind whenever GF re-renders (AJAX, multi-page, etc.)
$(document).on(‘gform_post_render’, function(e, formId){
bindForForm(formId);
});
// Also show overlay on common PayPal triggers (Smart Buttons / Hosted Fields)
// Note: some buttons live outside the form submit flow.
$(document).off(‘click.paypalOverlay’).on(‘click.paypalOverlay’, [
‘[data-paypal-button]’,
‘.gform_paypal_button’,
‘.gform_ppcp_button’,
‘button[id^=“gform_ppcp_button”]’,
#ppcp-hosted-fields-submit’,
‘.ppcp-button’,
‘.paypal-button’,
‘div[id^=“paypal-button”] button’
].join(‘,’), function(){
showOverlay(‘Connecting to PayPal…’);
});
// HIDE overlay when AJAX confirmation is injected (success on same page)
$(document).on(‘gform_confirmation_loaded’, function(e, formId){
hideOverlay();
});
// HIDE on validation errors
$(document).on(‘gform_validation_error’, function(e, formId){
hideOverlay();
});
// Safety timer: auto-hide after 45s if somehow stuck
let safetyTimer;
$(document).on(‘click submit’, ‘form[id^=“gform_”], [data-paypal-button], .gform_paypal_button, .gform_ppcp_button’, function(){
clearTimeout(safetyTimer);
safetyTimer = setTimeout(hideOverlay, 45000);
});
// If page is unloading (redirecting to PayPal or thank-you), drop overlay
window.addEventListener(‘pagehide’, hideOverlay);
window.addEventListener(‘beforeunload’, hideOverlay);
// Optional: hook PPCP programmatically if available (covers some smart-button flows)
if (window.gform_ppcp && window.gform_ppcp.buttons) {
try {
Object.keys(window.gform_ppcp.buttons).forEach(function(key){
var btn = window.gform_ppcp.buttons[key];
if (btn && btn.onClick && !btn._origOnClick) {
btn._origOnClick = btn.onClick;
btn.onClick = function(){
showOverlay(‘Connecting to PayPal…’);
return btn._origOnClick.apply(this, arguments);
};
}
});
} catch (err) { /* noop */ }
}
});
php }, 9999);

I have to get this spinner to only show on the specific forms… NOT every GF on the website.

Hi - have you tried this….?

Let us know how you get on.

Hi. Yes the custom spinner is finally complete but took a lot of custom work. odd how this was so difficult.

Great news, glad to hear things turned out well for you in the end. Thanks for feeding back.

I have other issues with specific field validations on a simple sign up form I am working on… same site, trying to change the default GF validation mess on the first/last name fields to STOP sayin “Please complete the following fields: first name, last name” I have entered my own text in advanced options and all it does is ADD it to that , not replace. I’ve tried specific functions and nothing will change that GF default “““ This field is required. Please complete the following fields: first name , last name. Going to maybe make a new post for that… can’t find any answer. The History of Akro Agate Marbles • Reference

I’m taking a look for you, but as you said: It’s best to open up a new dedicated post for this…