quinta-feira, 1 de janeiro de 2009

Javascript: Mostrar um alerta sempre que abandona um formulário sem gravar

Uma das grandes limitações que as aplicações Web sempre tiveram, foi a facilidade com que um utilizador pode perder informações introduzidas num formulário (apenas por seleccionar um link que não era suposto).

Se bem que este problema já começou a ser um pouco ultrapassado com a nova moda de colocar um “div de fundo”, dando a impressão que está a usar um formulário modal, em muitas situações esta limitação continua a ser bem real.

Há alguns anos atrás participei num projecto em que um dos requisitos era alertar o utilizador sempre que carregava num link, sem antes ter guardado a informação alterada. Depois da equipa muito pesquisar na Net sobre a melhor forma de implementar este requisito em Javascript, encontrámos uma propriedade muito interessante – defaultValue – disponível para qualquer elemento de um Form.

Baseámo-nos num script do Bob Mattler (infelizmente perdi a referência) com alguma modificações nossas.

Para implementar basta:
• Colocar uma referência na Master Page para o JS.
• Em cada link da vossa aplicação, nomeadamente nos menus, colocar a instrução onclick="formAlterado=true;" e já está.


/*********************************
** Verifica Alterações em Form **
*********************************/

window.onbeforeunload=verificaAlteracoes; //regista o evento para correr no unload de qualquer página

var formAlterado = false;
var msgAlterado = 'Colocar aqui a mensagem de erro';

function verificaAlteracoes() {
if (formAlterado){
//só queremos validação nos forms que são para gravar
if (document.getElementById('lnkGravar') && isFormChanged()) {
event.returnValue = msgAlterado;
}
formAlterado = false;
}
}

function isFormChanged() {
var rtnVal = false;
var frm = document.forms[0];
var ele = frm.elements;

//Percorre todos os elementos do Form
for ( i=0; i < ele.length; i++ ) {
if ( ele[i].type.length > 0 ) {
if ( isElementChanged( ele, i ) ) {
rtnVal = true;
break;
}
}
}
return rtnVal;
}

function isElementChanged( ele, i ) {
switch ( ele[i].type ) {
case "text" :
if ( ele[i].value != ele[i].defaultValue )
return true;
break;
case "textarea" :
if ( ele[i].value != ele[i].defaultValue )
return true;
break;
case "radio" :
if ( ele[i].checked != ele[i].defaultChecked )
return true;
break;
case "select-one" :
if (ele[i].options.selectedIndex != -1 &&
ele[i].options[ele[i].options.selectedIndex].selected !=
ele[i].options[ele[i].options.selectedIndex].defaultSelected){

if (ele[i].options.selectedIndex == 0 && ele[i].options[0].value == ''){
for ( var x =0 ; x < ele[i].length; x++ ) {
//verifica se existia algum default selected
if ( ele[i].options[x].defaultSelected )
return true;
}
}
else
return true;
}
break;
case "select-multiple" :
if (ele[i].options.selectedIndex != -1 &&
ele[i].options[ele[i].options.selectedIndex].selected !=
ele[i].options[ele[i].options.selectedIndex].defaultSelected){

if (ele[i].options.selectedIndex == 0 && ele[i].options[0].value == ''){
for ( var x =0 ; x < ele[i].length; x++ ) {
//verifica se existia algum default selected
if ( ele[i].options[x].defaultSelected )
return true;
}
}
else
return true;
}
break;
case "checkbox" :
if ( ele[i].checked != ele[i].defaultChecked )
return true;
break;
}
return false;
}



Sem comentários: