28

I'm building a fail safe for my form that is going to warn users that if they leave the page their form data will be lost (similar to what gmail does).

window.onbeforeunload = function () {    
        if (formIsDirty) {
            return "You have unsaved data on this form. Don't leave!";
        }
}

The above function works great in firefox, but in IE it is triggered by any href link, even ones that are links to javascript and not other pages.

for example....

<a href='javascript:someFunction();'>click</a>

I'm wondering if there is any way to get around this, as I do not want the user thinking that they are leaving the page when they are simply clicking a button on it. I do not have the option of rewriting all the various links as they are built in and numerous.

Any ideas?

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
Maxx
  • 3,925
  • 8
  • 33
  • 38
  • 4
    Just don't use such links. Use unobtrusive Javascript instead. – SLaks Oct 04 '11 at 15:14
  • It's not an option. We're using a highly complex system which already has all this stuff built in. I would prefer not to reinvent the wheel in this instance. – Maxx Oct 04 '11 at 15:22
  • Can you change the links after the page has loaded? – Tim Down Oct 04 '11 at 15:32
  • "Don't leave !" is dictatorial. You should better warn "If you leave, the unsaved data will be lost." If the user wants to leave, the user will leave, no matter what you try. The more you take abusive tactics, the more browsers and users will ignore them. – Nicolas Barbulesco Nov 29 '13 at 10:33

6 Answers6

37

You may remove and re-assign the onbeforeunload when hovering those links:

jQuery(
  function($)
  {
      //store onbeforeunload for later use
    $(window).data('beforeunload',window.onbeforeunload);  

      //remove||re-assign onbeforeunload on hover 
    $('a[href^="javascript:"]')
      .hover( 
             function(){window.onbeforeunload=null;},
             function(){window.onbeforeunload=$(window).data('beforeunload');}
            );

  }
);
Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • I was considering doing something like this. I guess I'll give it a try and deal with the hours of regression testing if it appears to work. Thank you. – Maxx Oct 04 '11 at 18:37
  • 1
    I ended up going with this solution. It works as expected and is fairly solid for this kind of workaround. Thank you for the help. – Maxx Oct 10 '11 at 15:29
  • This works great. However, you can also simply return false in your function that is bound to the anchor tag - at least that is how I was able to get around this. – anAgent Jun 12 '12 at 18:13
  • Simply returning false doesn't seem to do the trick on IE. I had to resort to using the onhover trick – shrisha Dec 05 '12 at 08:00
  • IE is the devil! Unless gov-types are forcing me, I only use Chrome / Firefox. The few 'benefits' in using IE do not seem so conducive to being productive. – Hardryv Apr 11 '13 at 17:52
  • This answer is interesting, but it is not clear enough. What is this "jQuery" ? What is this $ alone ? – Nicolas Barbulesco Nov 29 '13 at 10:39
  • I'd like more details about what exactly this is doing, please. – HPWD Mar 13 '14 at 16:21
8

I just ran into a similar problem and found a very easy solution:

$("a").mousedown(function() {
    $(window).unbind();
});

This will remove the onbeforeunload event just before the click event is triggered.

Ginchen
  • 790
  • 7
  • 20
3

Move any script to a click event handler instead, with a fallback page for users without JavaScript:

<a href="foo.html" onclick="someFunction(); return false">click</a>

The unobtrusive JS champions out there will probably object to the use of the onclick attribute, but the fact is that it works, it's the simplest way to add an event handler and the simplest way to provide an example. For better separation of concerns, you could instead use either a DOM0 onclick property, addEventListener() / attachEvent() or a library.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • 1
    This would still trigger the onbeforeunload event. Also, I do not have the luxury of rewriting the links. – Maxx Oct 04 '11 at 15:21
  • Thank you for the update, but this does not prevent the onbeforeunload event from triggering. – Maxx Oct 04 '11 at 15:29
  • @Maxx: It won't trigger the `beforeunload` event so long as `someFunction()` doesn't throw an error: the `return false` sees to that. – Tim Down Oct 04 '11 at 15:31
1

If you include a bookmark symbol in the href of the a tag you should be able to still use the onclick event to include your JavaScript.

<a href="#" onclick='someFunction();'>click</a>

I’ve run a number of tests and this appears to execute the JavaScript without triggering the onbeforeunload event. I’d be curious to know if this works for others or if you still have the same problem after implementing a tags in this manner.

1

(Like some of the other answers, this requires changing how the JavaScript is bound. If that doesn't work for you, disregard.)

I found that in IE 7 through IE 10, simply using jQuery .click() with preventDefault works without showing the onbeforeunload message (IE 11 does not show the beforeunload message for any of my test cases). This is true whether the href is '#' or javascript:void(0). I expect the conclusion holds if attachEvent/addEventListener is used directly, but I didn't test that.

There is a demo of the below at http://jsbin.com/tatufehe/1 . Both of the versions (in green) with preventDefault work (don't show the beforeunload dialog). The one without preventDefault does show it (as a comparison).


$( document ).ready( function () {
  $( 'a' ).click( function ( evt ) {
    $( '#display' ).text( 'You clicked: ' + $( this ).text() );

    if ( $(this).hasClass( 'withPreventDefault' ) ) {
      evt.preventDefault();
    }
  } );
})

window.onbeforeunload = function () {
  return "Are you sure you want to leave?";   
};

<p id="display"></p>

<p><a class="withPreventDefault" href="#">Number sign link *with* preventDefault</a></p>

<p><a class="withPreventDefault" href="javascript:void(0);">JavaScript href link *with* preventDefault</a></p>

<p><a href="javascript:void(0);">JavaScript href link *without* preventDefault</a></p>
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
0

If the user mouse is on a link and they trigger refresh page with the keyboard or activate a link with the keyboard, the prompt won't show up. So Dr.Molle approach will not work in this rare case.

danial
  • 4,058
  • 2
  • 32
  • 39