I was looking for a better solution to this. What we want is simply exclude one or more triggers from creating our "Are you sure?" dialog box. So we shouldn't create more and more workarounds for more and more side effects. What if the form is submitted without a click
event of the submit button? What if our click-handler removes the isDirty
status but then the form-submit is otherwise blocked afterwards? Sure we can change the behaviour of our triggers, but the right place would be the logic handling the dialog. Binding to the form's submit
event instead of binding to the submit button's click
event is an advantage of the answers in this thread above some others i saw before, but this IMHO just fixes the wrong approach.
After some digging in the event object of the onbeforeunload
event I found the .target.activeElement
property, which holds the element, which triggered the event originally. So, yay, it is the button or link or whatever we clicked (or nothing at all, if the browser itself navigated away). Our "Are you sure?" dialog logic then reduces itself to the following two components:
The isDirty
handling of the form:
$('form.pleaseSave').on('change', function() {
$(this).addClass('isDirty');
});
The "Are you sure?" dialog logic:
$(window).on('beforeunload', function(event) {
// if form is dirty and trigger doesn't have a ignorePleaseSave class
if ($('form.pleaseSave').hasClass('isDirty')
&& !$(event.target.activeElement).hasClass('ignorePleaseSave')) {
return "Are you sure?"
}
// special hint: returning nothing doesn't summon a dialog box
});
It's simply as that. No workarounds needed. Just give the triggers (submit and other action buttons) an ignorePleaseSave
class and the form we want to get the dialog applied to a pleaseSave
class. All other reasons for unloading the page then summons our "Are you sure?" dialog.
P.S. I am using jQuery here, but I think the .target.activeElement
property is also available in plain JavaScript.