Javascript – Aviso de Dados Não Salvos

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

Este tipo de recurso é muito interessante e pode evitar muita dor de cabeça por parte da pessoa que estiver utilizando o seu sistema. No meu caso, este recurso foi aplicado a um CMS. A finalidade da implantação deste recurso no CMS era para que os jornalistas fossem avisados quando algum dado no formulário fosse alterado, porém, o usuário intencionalmente (ou não) tenta mudar de página e este dado dado seria perdido. Se tratando de um CMS focado para jornalistas onde o conteúdo digitado é extremamente importante, todos recurso que for desenvolvido para evitar perda de conteúdo é extremamente bem-vindo.

onBeforeUnload Event

O evento onbeforeunload não tem uma finalidade exclusiva para ele, é um evento como outro qualquer, mas 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 pagina é o evento onbeforeunload. Sempre que ele é setado, você vai ver um confirm dialog, igual o da imagem abaixo.

Aviso de perda de conteúdo

O Problema

Se fosse só setar o efeito e ele fazia todo o resto, seria fácil, né? Pois é… mas não é assim (#lol). Temos que fazer 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 por que 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 houve a intenção de salvar o formulário.
Bom, é isso!
Dúvidas, sugestões, comentários are extremely encouraged.

Posts Relacionados: