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:
- Ao fechar aba/navegador;
- Ao clicar em qualquer outro link, senão o submit do formulário;
- 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?
- Utilizei o $.data() do jQuery porque eu não gosto de utilizar o var para declarar variáveis globais;
- 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;
- Por default, eu seto o evento onbeforeunload e dentro dele eu verifico se algo foi mudado no formulário;
- 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.