Quem nunca fez um formulário com um select, um radio ou um checkbox que mostra ou esconde outro trecho do formulário? Isto é uma prática bem comum, mas que o método reset () do formulário não tem como tratar.
Pesquisando um pouco, encontrei as propriedades defaultValue, defaultSelected e defaultChecked nos objetos de formulário do DOM. Com isso, podemos simular o método reset () do formulário. A propriedade defaultValue é válida para elementos do tipo text, password, textarea e file, a propriedade defaultSelected é válida para elementos option, e a propriedade defaultChecked é válida para elementos checkbox e radio.
Com isso, podemos criar facilmente uma função para resetar os valores de um formulário para o seu padrão:
function formReset ( formID)
{
// Fazemos um laço por todos os elementos do formulário:
for ( var x = 0; x < formID.elements.length; x++)
{
// Verificamos o tipo de elemento:
switch ( formID.elements[x].type)
{
case 'text':
case 'textarea':
case 'password':
case 'file':
// Campos tipo text, textarea, password e file utilizam defaultValue:
formID.elements[x].value = formID.elements[x].defaultValue;
break;
case 'select':
case 'select-one':
// Campos tipo select são tratados de forma especial. Temos que criar outro laço em seus elementos option para utilizar defaultSelected:
for ( var y = 0; y < formID.elements[x].options.length; y++)
{
formID.elements[x].options[y].selected = formID.elements[x].options[y].defaultSelected;
}
break;
case 'radio':
case 'checkbox':
// Campos tipo radio e checkbox utilizam defaultChecked:
formID.elements[x].checked = formID.elements[x].defaultChecked;
break;
}
}
}
Você deve estar pensando: Tá, e daí? Isso o método reset () faz! Bom, é aqui que podemos começar a brincar com o reset do formulário. Para começar, podemos dentro do laço fazer com que ele verifique se o elemento possui algum evento onchange, e caso exista, execute o mesmo após alterar o valor para o padrão. Ou seja, irá simular como se o usuário estivesse alterando o valor do formulário.
Podemos fazer isso assim:
if ( typeof ( formID.elements[x].onchange) == 'function')
{
formID.elements[x].onchange ();
}
Com isso podemos incluir todo tratamento necessário do formulário no evento onchange do elemento, para que quando resetarmos o formulário através da função formReset () ele execute estas funções e retorne o formato original do formulário.
Mas não podemos executar o evento onchange de cada elemento, pois se o valor não foi alterado, não devemos executar. Isso serve principalmente para eventos checkbox. Por isso, temos que reescrever a função, ficando assim:
function formReset ( formID)
{
// Fazemos um laço por todos os elementos do formulário:
var changed = false;
for ( var x = 0; x < formID.elements.length; x++)
{
// Verificamos o tipo de elemento:
switch ( formID.elements[x].type)
{
case 'text':
case 'textarea':
case 'password':
case 'file':
// Campos tipo text, textarea, password e file utilizam defaultValue:
if ( formID.elements[x].value != formID.elements[x].defaultValue)
{
formID.elements[x].value = formID.elements[x].defaultValue;
}
break;
case 'select':
case 'select-one':
// Campos tipo select são tratados de forma especial. Temos que criar outro laço em seus elementos option para utilizar defaultSelected:
for ( var y = 0; y < formID.elements[x].options.length; y++)
{
if ( formID.elements[x].options[y].selected != formID.elements[x].options[y].defaultSelected)
{
formID.elements[x].options[y].selected = formID.elements[x].options[y].defaultSelected;
}
}
break;
case 'radio':
case 'checkbox':
// Campos tipo radio e checkbox utilizam defaultChecked:
if ( formID.elements[x].checked != formID.elements[x].defaultChecked)
{
formID.elements[x].checked = formID.elements[x].defaultChecked;
}
break;
}
// Se o elemento teve o valor alterado, executa o método onchange () (se definido):
if ( changed == true && typeof ( formID.elements[x].onchange) == 'function')
{
formID.elements[x].onchange ();
changed = false;
}
}
}
Podemos ainda incrementar um pouco mais, fazendo com que o foco seja apontado para o primeiro campo que seja do tipo text, select, password, radio ou checkbox:
function formReset ( formID)
{
// Fazemos um laço por todos os elementos do formulário:
var focusElement;
var changed = false;
for ( var x = 0; x < formID.elements.length; x++)
{
// Verificamos se ainda não existe elemento para foco setado, e o tipo de elemento. Se combinado, seta a variável:
if ( ! focusElement && ( formID.elements[x].type == 'text' || formID.elements[x].type == 'select' || formID.elements[x].type == 'password' || formID.elements[x].type == 'checkbox' || formID.elements[x].type == 'radio'))
{
focusElement = formID.elements[x];
}
// Verificamos o tipo de elemento:
switch ( formID.elements[x].type)
{
case 'text':
case 'textarea':
case 'password':
case 'file':
// Campos tipo text, textarea, password e file utilizam defaultValue:
if ( formID.elements[x].value != formID.elements[x].defaultValue)
{
formID.elements[x].value = formID.elements[x].defaultValue;
}
break;
case 'select':
case 'select-one':
// Campos tipo select são tratados de forma especial. Temos que criar outro laço em seus elementos option para utilizar defaultSelected:
for ( var y = 0; y < formID.elements[x].options.length; y++)
{
if ( formID.elements[x].options[y].selected != formID.elements[x].options[y].defaultSelected)
{
formID.elements[x].options[y].selected = formID.elements[x].options[y].defaultSelected;
}
}
break;
case 'radio':
case 'checkbox':
// Campos tipo radio e checkbox utilizam defaultChecked:
if ( formID.elements[x].checked != formID.elements[x].defaultChecked)
{
formID.elements[x].checked = formID.elements[x].defaultChecked;
}
break;
}
// Se o elemento teve o valor alterado, executa o método onchange () (se definido):
if ( changed == true && typeof ( formID.elements[x].onchange) == 'function')
{
formID.elements[x].onchange ();
changed = false;
}
}
// Antes de encerrar, caso exista um campo escolhido para foco, executa o método focus () do mesmo:
if ( focusElement)
{
focusElement.focus ();
}
}
E para finalizar, vamos fazer uma última implementação. Que tal substituir o método reset () da classe HTMLFormElement do DOM para que todos os formulários do documento utilizem a função? Simples. Basta declarar a função assim (AVISO: apenas navegadores compatíveis como padrão W3C conseguem extender esta classe.):
// Altera o método reset () para a nossa própria classe:
HTMLFormElement.prototype.reset = function ()
{
// Fazemos um laço por todos os elementos do formulário:
var focusElement;
var changed = false;
for ( var x = 0; x < this.elements.length; x++)
{
// Verificamos se ainda não existe elemento para foco setado, e o tipo de elemento. Se combinado, seta a variável:
if ( ! focusElement && ( this.elements[x].type == 'text' || this.elements[x].type == 'select' || this.elements[x].type == 'password' || this.elements[x].type == 'checkbox' || this.elements[x].type == 'radio'))
{
focusElement = this.elements[x];
}
// Verificamos o tipo de elemento:
switch ( this.elements[x].type)
{
case 'text':
case 'textarea':
case 'password':
case 'file':
// Campos tipo text, textarea, password e file utilizam defaultValue:
if ( this.elements[x].value != this.elements[x].defaultValue)
{
this.elements[x].value = this.elements[x].defaultValue;
changed = true;
}
break;
case 'select':
case 'select-one':
// Campos tipo select são tratados de forma especial. Temos que criar outro laço em seus elementos option para utilizar defaultSelected:
for ( var y = 0; y < this.elements[x].options.length; y++)
{
if ( this.elements[x].options[y].selected != this.elements[x].options[y].defaultSelected)
{
this.elements[x].options[y].selected = this.elements[x].options[y].defaultSelected;
changed = true;
}
}
break;
case 'radio':
case 'checkbox':
// Campos tipo radio e checkbox utilizam defaultChecked:
if ( this.elements[x].checked != this.elements[x].defaultChecked)
{
this.elements[x].checked = this.elements[x].defaultChecked;
changed = true;
}
break;
}
// Se o elemento teve o valor alterado, executa o método onchange () (se definido):
if ( changed == true && typeof ( this.elements[x].onchange) == 'function')
{
this.elements[x].onchange ();
changed = false;
}
}
// Antes de encerrar, caso exista um campo escolhido para foco, executa o método focus () do mesmo:
if ( focusElement)
{
focusElement.focus ();
}
}
Isso resolve em partes, pois quando um reset é acionado como evento, a função não é executada. Para isso, devemos capturar o evento reset e alterar um pouco a função, para que ela referencie o formulário através da propriedade target do evento ou da palavra-chave this. O script final fica assim:
// Altera o método reset () para a nossa própria classe:
HTMLFormElement.prototype.reset = function ( event)
{
// Verificamos como a função foi executada, setando a variável target:
var target = event ? event.target : this;
// Fazemos um laço por todos os elementos do formulário:
var focusElement;
var changed = false;
for ( var x = 0; x < target.elements.length; x++)
{
// Verificamos se ainda não existe elemento para foco setado, e o tipo de elemento. Se combinado, seta a variável:
if ( ! focusElement && ( target.elements[x].type == 'text' || target.elements[x].type == 'select' || target.elements[x].type == 'password' || target.elements[x].type == 'checkbox' || target.elements[x].type == 'radio'))
{
focusElement = target.elements[x];
}
// Verificamos o tipo de elemento:
switch ( target.elements[x].type)
{
case 'text':
case 'textarea':
case 'password':
case 'file':
// Campos tipo text, textarea, password e file utilizam defaultValue:
if ( target.elements[x].value != target.elements[x].defaultValue)
{
target.elements[x].value = target.elements[x].defaultValue;
changed = true;
}
break;
case 'select':
case 'select-one':
// Campos tipo select são tratados de forma especial. Temos que criar outro laço em seus elementos option para utilizar defaultSelected:
for ( var y = 0; y < target.elements[x].options.length; y++)
{
if ( target.elements[x].options[y].selected != target.elements[x].options[y].defaultSelected)
{
target.elements[x].options[y].selected = target.elements[x].options[y].defaultSelected;
changed = true;
}
}
break;
case 'radio':
case 'checkbox':
// Campos tipo radio e checkbox utilizam defaultChecked:
if ( target.elements[x].checked != target.elements[x].defaultChecked)
{
target.elements[x].checked = target.elements[x].defaultChecked;
changed = true;
}
break;
}
// Se o elemento teve o valor alterado, executa o método onchange () (se definido):
if ( changed == true && typeof ( target.elements[x].onchange) == 'function')
{
target.elements[x].onchange ();
changed = false;
}
}
// Antes de encerrar, caso exista um campo escolhido para foco, executa o método focus () do mesmo:
if ( focusElement)
{
focusElement.focus ();
}
}
// Captura o evento onreset de todos os formulários do documento:
window.addEventListener ( 'reset', HTMLFormElement.prototype.reset, true);
Adicionei um formulário de testes aqui. Você também pode baixar o script aqui.




