2012-08-01 20 views
25

Estoy usando window.onbeforeunload para evitar que el usuario se desplace después de cambiar los valores en un formulario. Esto funciona bien, excepto que también muestra la advertencia cuando el usuario envía el formulario (no deseado).window.onbeforeunload - Mostrar solo una advertencia cuando no se envía el formulario

¿Cómo puedo hacer esto sin mostrar la advertencia cuando se envía el formulario?

código actual:

var formHasChanged = false; 

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) { 
    formHasChanged = true; 
}); 

$(document).ready(function() { 
    window.onbeforeunload = function (e) { 
     if (formHasChanged) { 
      var message = "You have not saved your changes.", e = e || window.event; 
      if (e) { 
       e.returnValue = message; 
      } 
      return message; 
     } 
    } 
}); 

Respuesta

26

Utilizando caso presente de la forma de establecer un indicador que podría funcionar para usted .

var formHasChanged = false; 
var submitted = false; 

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) { 
    formHasChanged = true; 
}); 

$(document).ready(function() { 
    window.onbeforeunload = function (e) { 
     if (formHasChanged && !submitted) { 
      var message = "You have not saved your changes.", e = e || window.event; 
      if (e) { 
       e.returnValue = message; 
      } 
      return message; 
     } 
    } 
$("form").submit(function() { 
    submitted = true; 
    }); 
}); 
+0

Acepté esto sobre @ Derek porque ya tenía código de envío personalizado y necesitaba verificar los dos valores por separado. – mtmurdock

10

Usted puede controlar el evento submit(), que tendrá lugar sólo para su envío del formulario.

Dentro de ese evento, establezca su variable de indicador formHasChanged en falso para permitir que continúe la descarga. Además, es sólo una sugerencia, pero ya que el propósito de esa variable indicador habrá cambiado, por lo que es posible que desee cambiar su nombre algo así como 'warnBeforeUnload'

$(document).submit(function(){ 
    warnBeforeUnload = false; 
}); 
11

podría utilizar .on() para vincular onbeforeunload y luego usar .OFF() para desvincularla de envío del formulario

$(document).ready(function() { 
    // Warning 
    $(window).on('beforeunload', function(){ 
     return "Any changes will be lost"; 
    }); 

    // Form Submit 
    $(document).on("submit", "form", function(event){ 
     // disable warning 
     $(window).off('beforeunload'); 
    }); 
} 
2

que estaba buscando una mejor solución a esto. Lo que queremos es simplemente excluir uno o más factores desencadenantes de la creación de nuestro "¿Estás seguro?" caja de diálogo. Por lo tanto, no deberíamos crear más y más soluciones para más y más efectos secundarios. ¿Qué ocurre si el formulario se envía sin un evento click del botón Enviar? ¿Qué pasa si nuestro manejador de clics elimina el estado isDirty pero luego el formulario enviado se bloquea después? Claro que podemos cambiar el comportamiento de nuestros disparadores, pero el lugar correcto sería la lógica que maneja el diálogo. Vincular al evento submit del formulario en lugar de vincular al evento click del botón Enviar es una ventaja de las respuestas en este hilo por encima de otras que vi antes, pero este mensaje de mi humilde opinión simplemente soluciona el problema.

Después de buscar en el evento objeto del evento onbeforeunload encontré la propiedad .target.activeElement, que contiene el elemento, que desencadenó el evento originalmente. Entonces, yay, es el botón o enlace o lo que sea que hayamos hecho clic (o nada en absoluto, si el navegador se ha navegado). Nuestro "¿Estás seguro?" la lógica de diálogo y luego se reduce a los dos componentes siguientes:

  1. isDirty El manejo de la forma: "¿Está seguro"

    $('form.pleaseSave').on('change', function() { 
        $(this).addClass('isDirty'); 
    }); 
    
  2. El la lógica de diálogo:

    $(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 
    }); 
    

Es simplemente como eso. No se necesitan soluciones. Simplemente dé los disparadores (enviar y otros botones de acción) una clase ignorePleaseSave y la forma en que queremos que el diálogo se aplique a una clase pleaseSave. Todas las otras razones para descargar la página luego convoca nuestro "¿Estás seguro?" diálogo.

P.S. Estoy usando jQuery aquí, pero creo que la propiedad .target.activeElement también está disponible en JavaScript.

+0

Esto parece ser específico del navegador. Funciona bien en Chrome, pero el objetivo en Firefox siempre es 'body' –

+0

Acaba de probarse en Firefox 40, event.target.activeElement da de hecho el elemento clocked, como lo hace en Chrome. Mi solución funciona bien en ambos buscadores para mí. – spackmat

+0

Me gusta este enfoque pero no pude hacerlo funcionar en IE. Pero ignorar por completo el evento y usar document.activeElement me sirvió de algo (solo probado en Chrome e IE hasta el momento) – Doogal

Cuestiones relacionadas