Front End

11 abr, 2012

JavaScript: aviso de dados não salvos

Publicidade

Sabe quando você está escrevendo um e-mail e, quando tenta sair da tela, o browser te dá um aviso, comunicando a possível perda de dados? Pois é sobre isso que vamos falar! O Gmail faz isso e o Rally também, mas muita gente ainda não sabe como isso é feito de fato.

Esse tipo de recurso é muito interessante e pode evitar muita dor de cabeça para quem estiver utilizando o seu sistema. No meu caso, esse recurso foi aplicado a um CMS. A finalidade da implantação era para que os jornalistas fossem avisados quando algum dado no formulário fosse alterado, porém, se o usuário intencionalmente (ou não) tentasse mudar de página, esse dado seria perdido. Tratando-se de um CMS focado para jornalistas, no qual o conteúdo digitado é extremamente importante, todos os recursos que forem desenvolvidos para evitar a perda de conteúdo são extremamente bem-vindos.

onBeforeUnload Event

O evento onbeforeunload não tem uma finalidade exclusiva para ele. É um evento como outro qualquer, que ele é invocado sempre que o usuário tenta sair da página atual, mas, quando ele não está setado, simplesmente nada acontece. O evento responsável por pedir para que o usuário confirme ou não a mudança de página é o onbeforeunload. Sempre que ele for setado, você vai ver um confirm dialog igual ao da imagem abaixo:

O problema

Se fosse só setar o efeito e ele fizesse todo o resto seria fácil, não é? Bom, mas não é bem assim. Temos que fazer com que um script peça a intervenção do usuário nas seguinte situações:

  1. Ao fechar aba/navegador;
  2. Ao clicar em qualquer outro link, senão o submit do formulário;
  3. O alerta deve aparecer somente se algo for alterado no formulário.

A solução

$(function(){
var formObject = $('.new_materia, .edit_materia');
formObject.data('original_serialized_form', formObject.serialize());

$(':submit').click(function() {
window.onbeforeunload = null;
});

window.onbeforeunload = function() {
if (formObject.data('original_serialized_form') !== formObject.serialize()) {
return "As mudanças deste formulário não foram salvas. Saindo desta página, todas as mudanças serão perdidas.";
}
};
});

Como funciona?

  1. Utilizei o $.data() do jQuery porque eu não gosto de utilizar o var para declarar variáveis globais;
  2. Utilizei o $.serialize() do jQuery para serializar o formulário para comparar o estado do formulário no futuro. E foi a forma mais inteligente que encontrei para identificar se algo realmente foi mudado no formulário;
  3. Por default, eu seto o evento onbeforeunload e dentro dele eu verifico se algo foi mudado no formulário;
  4. O único caso em que eu tenho que remover o evento onbeforeunload é quando existe a intenção de salvar o dado, no caso utilizei o :submit com evento $.click() para remover o evento e cancelar o alerta, caso haja a intenção de salvar o formulário.

Bom, é isso! Dúvidas ou sugestões, só deixar nos comentários.