Page 1 of 1

NorPrice with Fancybox V4/V5

Posted: Mon Jun 09, 2025 9:52 am
by graphicz
Please do make copies of all files before editing and do a full snapshot of your site first. This is posted as a goodwill gesture without any warranty express or implied. I used ChatGPT to help me reach this solution.

To make fb_show() in norpricesupport.js compatible with Fancybox 5, you need to update the call to .fancybox.open() to match the new Fancybox 5 API. Fancybox 5 no longer uses jQuery, and it now relies on vanilla JS and data attributes.

However, since norpricesupport.js is a legacy jQuery script, and the fb_show() function dynamically calls Fancybox, you'll need to adapt the code in a way that invokes the Fancybox 5 API in vanilla JS.

Loading Fancybox 5:
Ensure you include the correct Fancybox 5 CSS and JS files before norpricesupport.js:

Drop jQuery Fancybox V1.3.4 and Remove any old Fancybox 1.3.4 references, as they conflict with Fancybox 5.

Move Norprice support out of Javascript header functions to the <head> Below Javascript Header functions Thus:

Code: Select all

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css" />
<style>.fancybox__container {z-index: 999999;}</style>
<script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js"></script>
<script>
window.addEventListener("message", function(e) {
    if (e.data === 'fancy_close') {
        Fancybox.close();  // Closes any open Fancybox modal
    }
}, false);
</script>
<actinic:variable name="NorPriceSupport" />
The close message also appears in norprice support.js see later.

Do not load Fancybox 5 via ES module syntax: This does not expose the Fancybox class globally, so the call to Fancybox.show(...) in norpricesupport.js fails silently — because Fancybox is undefined in the global scope.

Use the UMD Version Instead: The UMD (Universal Module Definition) version does expose Fancybox globally, which is what the script expects.

We need to define (force) the modal size with additional styles in the <head>

We need to ensure that only NorPrice currency popups get the custom size so should not globally style .fancybox__container if you're using Fancybox for other purposes elsewhere on the site. Instead, we can assign a unique class to this particular instance of Fancybox when it opens, and then target that class in your CSS.

Code: Select all

<style>
/* Only apply to NorPrice modals */
.np-fancybox.fancybox__container {
    max-width: 470px !important;
    max-height: 180px !important;
    width: 470px !important;
    height: 180px !important;
}

.np-fancybox .fancybox__slide {
    padding: 0 !important;
}

.np-fancybox .fancybox__iframe {
    width: 470px !important;
    height: 180px !important;
    max-width: 470px !important;
    max-height: 180px !important;
}
</style>
I had trouble with modal not closing after selecting a currency. The difficulty was passing the fancybox_close message to the parent html.

I therefore opted to call closeFancybox() after the dropdown sets the currency with a delay to allow time for the selection to take place. Closing the Fancybox directly from the iframe (popup) after a delay when the currency is selected is a clean, reliable solution — and more straightforward than passing messages to the parent window. My delay is 1200 ms but you can edit this if wished.

So we Update the setrate() function in norpricepopup.html like this:

Code: Select all

function setrate(sel){
    val = sel.options[sel.selectedIndex].value;
    var bits = val.split(/:/);
    var shownrate = (bits[2] / homerate).toFixed(4);
    showcurrentrate(shownrate);
    document.cookie = "destcurr=" + escape(bits[0] + ':' + bits[2] + ':' + homerate) + '; path=/';

    if (parent && parent.Fancybox) {
        showratebeingset();
        setTimeout(function() {
            parent.Fancybox.close();  // Close Fancybox from within iframe
        }, 1200);
    }
}
Finally we edit norpricesupport.js

There are three code blocks we need to edit:

Code: Select all

function fb_show(link, height, width){	

Code: Select all

$(window).on("message", function(e) 
and

Code: Select all

function setcookieandreload(newcurr) {
These are the three amended blocks:

Code: Select all

function fb_show(link, height, width) {
    Fancybox.show([{
        src: link,
        type: "iframe",
        customClass: "np-fancybox"
    }], {
        autoSize: false,
        dragToClose: false,
        width: width,
        height: height,
        iframe: {
            preload: false,
            attr: {
                style: 'width:' + width + 'px;height:' + height + 'px;max-width:' + width + 'px;max-height:' + height + 'px;border:0;'
            }
        },
        on: {
            destroy: norpricereload
        }
    });
}

Code: Select all

// Close Fancybox when we receive message from iframe (norpricepopup.html)
window.addEventListener("message", function(e) {
    if (e.data === 'fancy_close') {
        const instance = Fancybox.getInstance();
        if (instance) {
            instance.close();
        } else {
            console.warn("No Fancybox instance found.");
        }
    }
}, false);

Code: Select all

// Called from norpricepopup.html via setTimeout after 200ms
function setcookieandreload(newcurr) {
    if (np_ecodes[newcurr]) {
        document.cookie = "destcurr=" + escape(newcurr + ':' + np_ecodes[newcurr].rate + ':' + np_ecodes[np_hidemain].rate) + '; path=/';
        norpricereload();
        setTimeout(function () {
            window.parent.postMessage('fancy_close', '*');
        }, 1200); // 200ms delay before closing modal
        return;
    }
    alert('Unknown currency ' + newcurr);
}

Complete norpricesupport.js and Complete norpricepopup.html are attached as .txt files to alow upload. Save and remove the .txt