1

I am trying to sort out a way to trigger a bootstrap modal when the user navigates away from my site, not an individual page. Please before this gets marked as a duplicate, I have tried several different solutions, mainly this on: Display a warning when leaving the site, not just the page

With this solution, it is not working as expected. I am getting browser alerts with every page navigation and should be getting them only when leaving the site. Here is my supporting code:

window.localLinkClicked = false;

$("a").on("click", function() {
    var url = $(this).attr("href");

    // check if the link is relative or to your domain
    if (! /^http?:\/\/./.test(url) || /http?:\/\/app\.tendesign\.us/.test(url)) {
        window.localLinkClicked = true;
    }
});

window.onbeforeunload = function() {
    if (window.localLinkClicked) {
        alert('do stuff');// do stuff
    } else {
        alert('dont do stuff');// don't
    }
}

I also want the user to be warned not just by clicking on the link, but closing browser tab etc...

Community
  • 1
  • 1
Sandra Willford
  • 3,459
  • 11
  • 49
  • 96

1 Answers1

1

This script challenge got my focus.
Thanks to you, Sandra, who gave me the opportunity of a fun code time on a boring monday evening.

First, I had in mind (because I've read it somewhere... I don't know when) that the beforeunload event is handled differently depending on the browser and is, therefore, not a safe option.
For example, Chrome is not allowing an alert or a prompt on that event, which is exactly what you tried.

But it still, it allows a function to run.
Based on this old answer, I've tested something for you.

As of 2017, the message returned (as suggested in the 2012 answer) is not displayed in Chrome.
But a return true; works as expected with a default Chrome message:

enter image description here

Now, You don't want this function binded to the beforeunload event to execute if the target that triggered the event is an internal link.

And I've added to requirements : "Not on page refresh!"
(keydown on F5)

Okay.

So here is what I have now, which triggers on close tab/browser and on external link click only.
(Taking account of full and/or relative URL).

I've tested it only on Chrome, which I think is the most severe on this event.
It's working.

And this code is fully "Rubber Duck" compliant.
Cheers!
;)

$(document).ready(function(){

    console.log("Page has just loaded.");

    // Flag to determine if a link click is local or external.
    window.localLinkClicked = false;

    // flag for the refresh key [F5]
    var refreshKey=false;

    // Link click handler.
    $("a").on("click", function(e) {

        // Get the link URL
        var url = $(this).attr("href");
        console.log("Link clicked. URL: "+url);

        // Check if the link is relative to your domain:

        // [SUB_DOMAIN] example: www
        // [DOMAIN] example: google
        // [TLD] example: com
        // This regexp (regular expression) takes in account secured and unsecured domains (http:// and https://)

        if ( !/^(http)(s?):\/\//.test(url) || /^(http)(s?):\/\/[SUB-DOMAIN]\.[DOMAIN]\.[TLD]\//.test(url) ) {
            window.localLinkClicked = true;
        }else{
            window.localLinkClicked = false;
        }
        console.log("Local click ? " + window.localLinkClicked);

        if (!window.localLinkClicked) {
            var leave = confirm("Do you really want to leave our website to follow this link?");
            if(leave){
                refreshKey=true;
                alert("Okay, see you soon!");
            }else{
                e.preventDefault();
                console.log("User has cancelled his navigation.")
            }
        }

        // Reset the local click flag
        setTimeout(function(){
            window.localLinkClicked = false;
        },10);
    });

    // Handler to detect the refresh key
    $(window).on("keydown",function(e){
        //console.log(e.which);

        if(e.which==116 ){
            console.log("User is REFRESHING the page. Do not trigger the confirm to leave.");
            refreshKey=true;
        }else{
            refreshKey=false;
        }
    });

    // On beforeunload event handler.
    $(window).on('beforeunload', function(e) {
        if(typeof(e)!="undefined" && e.target.tagName!="undefined" && (!refreshKey && !window.localLinkClicked) ){
            return true;
        }

    });
});
Community
  • 1
  • 1
Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64