Confirming your users choice to navigate away from a node edit form.

Stop! Who goes there?!?Notifying a user that they are leaving a form involves a few simple steps.

Adding some much needed jQuery goodness.

Add the javascript file via hook_form_alter


function phase2_form_alter(&$form, $form_state, $form_id) { if (isset($form[‘type’]) && isset($form[’#node’]) && $form[‘type’][’#value’] .

Frank Febbraro, Chief Technology Officer
#Drupal | Posted

Notifying a user that they are leaving a form involves a few simple steps.

Adding some much needed jQuery goodness.

Add the javascript file via hook_form_alter

  1. function phase2_form_alter(&$form, $form_state, $form_id) {
  2. if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] . '_node_form' == $form_id) {
  3. drupal_add_js(drupal_get_path('module', 'phase2') . '/node-edit-protection.js');
  4. }
  5. }

Catching any modification to a form element.

This marks the form as dirty. I am catching the blur event as a means of marking the form as dirty. So I want to grab each and every input item on the node form and when the blur event happens I want to set the dirty flag.

[js]$(".node-form :input").each(function() {
  $(this).blur(function() {
    $(window).attr('phase2_confirm_edited', true);
  });
});[/js]

Allow node form submit button clicks to pass through

We don’t want to prompt the user to confirm a save/process on the page that they meant to do, so for all of the submit buttons on the node form, set a flag that tells all that would make us confirm that this was intended. We also add a processed class to the form buttons because we don’t want to attach a notification check (in the next step) to form submit buttons.

[js]$(".node-form input[@type='submit']").each(function() {
  $(this).addClass('processed');
  $(this).click(function() {
    $(window).attr('phase2_confirm_clicked', true);
  });
});[/js]

Catching any link or button click that may take them to another page, and if the form is dirty confirming the move with the user.

For all other links or buttons (or form buttons) on the page, if they are clicked and the form is dirty, confirm the request to load another page. Note the :not(.processed), this is how we tell it to ignore registering a click handler on the main form submit buttons themselves (that is why we added the class to them in the previous step).

[js]$("a, button, input[@type='submit']:not(.processed)").each(function() {
  $(this).click(function() {
    var edited = $(window).attr('phase2_confirm_edited');
    if(edited) {
      $(window).attr('phase2_confirm_clicked', true);
      return Drupal.phase2.confirmNavigate();
    }
  });
});[/js]

As a last resort, catching a window unload event which is triggered when the browser is leaving the current URL and loading another.

If we miss something that is not a link or button and the form is dirty and it was not an allowed submit click, then we need to notify the user as well.

[js]$(window).unload(function() {
  var clicked = $(this).attr('phase2_confirm_clicked');
  var edited = $(this).attr('phase2_confirm_edited');
  if(edited && !clicked) {
    return Drupal.phase2.confirmNavigate();
  }
});[/js]

Finally don’t forget to put the previously mentioned Javascript into the Drupal.behaviors setup as such:

[js]Drupal.behaviors.nodeEditProtect = function (context) {
    // Put all your junk here
};[/js]

Hope this helps everyone and does not make your users want to put you in a burlap sack and beat you with reeds.

 

 

 

Frank Febbraro

Chief Technology Officer