12

I have a handler for onbeforeunload

window.onbeforeunload = unloadMess;
function unloadMess(){
  var conf = confirm("Wait! Before you go, please share your stories or experiences on the message forum.");
    if(conf){
    window.location.href = "http://www.domain.com/message-forum";
    }
}

but I'm not sure how to know if the url they clicked on the page is within the site.

I just want them to alert them if they will leave the site.

Jeremy
  • 1
  • 85
  • 340
  • 366
RicardO
  • 1,219
  • 1
  • 14
  • 24
  • 24
    Please don't do this - they know they're leaving the site - they clicked the link. This kind of thing is what gives javascript a bad name. – James Gaunt Aug 23 '11 at 14:09
  • 1
    possible duplicate of [How can i get the destination url in javascript onbeforeunload event?](http://stackoverflow.com/questions/1686687/how-can-i-get-the-destination-url-in-javascript-onbeforeunload-event) – Marc B Aug 23 '11 at 14:10
  • 7
    BAD. BAD Developer. Don't make me swat you on the nose with a newspaper. – Chris Pratt Aug 23 '11 at 14:19
  • I disagree with the vote to close; it may be possible without reading the target from the event, which is what the other question is about. – Jeremy Aug 23 '11 at 14:36
  • this chain of stuffs make me crazy, i'm levaing! i dont waant to stay. dont do this man – Ricardo Binns Aug 23 '11 at 14:47
  • 1
    Only time this is ever acceptable is when the user has entered content which would otherwise be lost when they navigate away. eg. Gmail compose email dialog. A better solution would be to use $(window).unload(..) and save everything in localStorage. Or save to localStorage every n seconds, again eg. like Gmail saving drafts. – Mike Causer Jan 16 '14 at 06:13
  • This could also be used to prevent phishing attacks when people link to another domain from your domain and you want to warn the user that they are going to a different domain. I see a lot of forum websites do this and I think it's quite helpful. They don't use an alert or confirmation window, they instead send you to an intercept page. – Hanna Jul 31 '14 at 17:12
  • simply for analytical purposes is fair use, unobstrusive. – koma Nov 15 '14 at 23:18

5 Answers5

21

It's not possible to do this 100% reliably, but if you detect when the user has clicked on a link on your page, you could use that as a mostly-correct signal. Something like this:

window.localLinkClicked = false;

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

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

window.onbeforeunload = function() {
    if (window.localLinkClicked) {
        // do stuff
    } else {
        // don't
    }
}
Jeremy
  • 1
  • 85
  • 340
  • 366
1

I've got one idea, but I don't know if it's work. My suggestion is, add each link an onClick event with a function call. That function reads just the href attribute and store into a variable with global scope.

var clickedHrefAttrValue = "";
function getClickUrl(currentLink)
{
   clickedHrefAttrValue = $(currentLink).attr("href");
   return true;
}

The html for the a tags must be looks like following:

<a href="<url>" onClick="getClickUrl(this)">Linktext</a>

and in your given function:

function getClickUrl()
{
   if (clickedHrefAttrValue.indexOf("<your condition>" > -1)
   {
     //what ever you want do to
   }
}

It is just an idea, but I think it is worth to try it.

Reporter
  • 3,897
  • 5
  • 33
  • 47
0

If you are having issues because your website may have both absolute and relative local links, I have another solution (using jQuery):

Demo

/* EXTERNAL LINK WARNING
=========================================*/
$('a').on('click', function(e){
    e.preventDefault();
    var url = $(this).attr('href'),
        host = location.host;       
    if (url.indexOf(host) > -1 || url.indexOf('http','https') == -1){
        /* If we find the host name within the URL,
               OR if we do not find http or https, 
               meaning it is a relative internal link
            */
        window.location.href = url;
    } else {
        var warn = confirm('You\'re leaving the domain.\n\nAre you sure?');
        if(warn == true) {
            window.location.href = url,'_blank';
        } else {
            e.preventDefault;
        }
    }
});
kthornbloom
  • 3,660
  • 2
  • 31
  • 46
0

So I needed to do this so I could log a user out if they left the site from any page, but not if they navigate within the site. Here is my solution using JS and PHP

On every page where they need to remain logged in, set a session variable:

<?php
    session_start();
    $_SESSION["isInSession"] = true;
?>

Now create two scripts:

clear-in-session.php

<?php
    session_start();
    unset($_SESSION["isInSession"]);
?>

logout.php

<?php
    session_start();
    if(isset($_SESSION["isInSession"]) exit();
    //do logout code here
?>

Now we set 2 events in JS:

window.addEventListener('beforeunload', function(event) {
    $.ajax({
        type: 'POST',
        async: false,
        url: 'clear-in-session.php'
    });
});
window.addEventListener('unload', function(event) {
    $.ajax({
        type: 'POST',
        async: false,
        url: 'logout.php'
    });
});

To explain the order of events when the user navigates to another page in the same site:

  1. The user navigates away
  2. beforeunload is triggered, calling clear-in-session.php which removes the isInSession variable
  3. The new page is loaded, setting isInSession to true
  4. unload is triggered, calling logout.php, but because isInSession has been set back to true, the logout code is never called

When the user navigates to a page outside of the site (or to any page on the site that doesn't set isInSession):

  1. The user navigates away
  2. beforeunload is triggered, calling clear-in-session.php which removes the isInSession variable
  3. The new page is loaded
  4. unload is triggered, calling logout.php, isInSession has been deleted, so the logout code is called

Sorry for necro but this thread still comes up when searching for the answer to this question

Note: This answer uses jQuery for post calls to the php. It is entirely possible to do this in pure JS, but it was easier to illustrate in jQuery

M. Richardson
  • 81
  • 1
  • 3
-1

There is a good solution to this which I implemented in my website recently. Just imagine this, everything thats going to be in your website that navigates the user is either going to be a link (anchor tag), button, clickable image or something on these lines. Its definitely not going to be the body element.

Now what happens when a user leaves the website, he/she can either type in a url and press enter, click a bookmark or press the back/forward buttons.

When a user does do that, do this:

$(window).on('beforeunload', function(e)){
    if(e.target.activeElement.nodeName.toLowerCase() == 'body'){
       yourFunction();
});

What happens is that the body becomes the active element in the target in these cases (when user leaves the website) and this is not the case when the user clicks on internal website navigable elements.

This is a clean, easy solution. Let me know if you face any issues.

Siddharth Mehta
  • 445
  • 3
  • 7
  • 17
  • this beforeunload handler is called even when im in my application/website (same host/domain) url and press enter also its get called ? Is that a way any even should call only if user entered differ host/url other then my application ? – Krish Jan 06 '22 at 07:41