impedir utilizador de clicar 2 vezes no mesmo botão/imagem

Phaster

Power Member
boas

tenho uma página que aquando o click de um botão faz uma chamada ao servidor, retorna uma string em json e cria um "nível" de uma árvore adicionado elementos ao DOM, baseada em <ul> e <li>, tudo isto com javascript, no entanto se o servidor demorar um pouco mais a responder e/ou o user clique uma vez no botão e passado um pequeno instante carregue novamente, este efectua 2 chamadas do webservice seguidas.

como é que impeço o user de clicar 2 vezes no mesmo botão/imagem enquanto a função que adiciona elementos ao DOM corre?

html
Código:
<asp:Button ID="Button1" runat="server" Text="Button" onclientclick="Get_Tema(); return false;"/>
javascript

Código:
function Get_Tema() {

  if (document.getElementsByTagName("html")[0].className.indexOf("mymodal_is_here") > -1)
  return;


  var html = document.getElementsByTagName("html")[0];
  if (html.className) {
  html.className += " mymodal_is_here";
  } 

  var service = new WebJSON;
  service.GetTema(SuccessCallback_Get_Tema, OnfailureCallback_Get_Tema);

  html.className = html.className.replace("mymodal_is_here", "");

};

//returns output from service   
function SuccessCallback_Get_Tema(Resultado) {
  //displaying output on alertbox   
  //alert(Resultado);

  var colleccao = JSON.parse(Resultado);

  var lista_tema = document.createElement("ul");
  lista_tema.setAttribute("class", "lista-sem-bullets");
  for (var i = 0; i < colleccao.length; i++) {

  var elemento_tema = document.createElement("li");
  var elemento_tema_imagem_esconde_mostra = document.createElement("img");
  var elemento_tema_imagem_no = document.createElement("img");
  var elemento_tema_link = document.createElement("a");

  if (colleccao[i].FILHOS > 0) {
  elemento_tema_imagem_esconde_mostra.src = "Content/Images/img_abrir_22_22.png";
  } else if (colleccao[i].FILHOS = 0) {
  elemento_tema_imagem_esconde_mostra.src = "Content/Images/seta_dir_26_20.png";
  }

  elemento_tema_imagem_esconde_mostra.addEventListener("click", Get_Feat, false);

  elemento_tema_imagem_no.src = "Content/Images/tema.png"

  elemento_tema_link.setAttribute("MNID", colleccao[i].MNID);
  elemento_tema_link.innerText = colleccao[i].NAMEDESC

  elemento_tema.appendChild(elemento_tema_imagem_esconde_mostra);
  elemento_tema.appendChild(elemento_tema_imagem_no);
  elemento_tema.appendChild(elemento_tema_link);
   
  lista_tema.appendChild(elemento_tema);
  }

  document.getElementById("cphConteudo_divarvore").appendChild(lista_tema);

}
//returns the error after WCF  service failed to execute   
function OnfailureCallback_Get_Tema(error) {
  //displaying error on alert box   
  alert(error);

};
 
Nunca fiz nada do género, mas a primeira coisa que me ocorre é fazer disable do botão ou do link da imagem, no início da função, e voltar a ligar no fim.

Outras opções podem ser usar variáveis globais ou mecanismos de locking, mas não sei se é habitual fazer isso em javascript.
 
Resumidamente, não é possível fazer com que o cliente não envie duas vezes o mesmo pedido. O que tens que fazer é limitar de alguma maneira (depende de caso para caso) como o pedido é processado.

Caso não seja nada de extra-ordinário, o que o @nfk sugeriu serve.
 
Podes simplesmente adicionar a tag disabled

Código:
{
    var eleman = document.getElementById(id);
    eleman.disabled =true;
}

e depois quando ele já poder clicar outra vez fazer

Código:
eleman.disabled =false;
 
Podes simplesmente adicionar a tag disabled

Código:
{
    var eleman = document.getElementById(id);
    eleman.disabled =true;
}

e depois quando ele já poder clicar outra vez fazer

Código:
eleman.disabled =false;

resolveu-me o problema, obrigado

agora surgiu-me outra coisa, como faço para colocar uma barra de progresso/guif/whatever antes da chamada do webservice e enquanto o javascript corre?

já experimentei adicionar uma div com uma imagem no background antes da chamada do webservice e só a removia depois de adicionar os controlos todos mais não acontecia nada, mesmo com um breakpoint no código do webservice
 
Sim a ideia normal é criar uma div dar-lhe um valor absuluto e um index de 99999 e mostra-la quando começas um request e escondes quando acaba.

Também podes automatizar o processa (se tiveres muitos requests) onde verificas se existe algum progresso a recorrer e mostrar a div até acabar
Não me lembro como se faz utilizando só Javascript, mas em angular é qualquer coisa como

Código:
 scope.isLoading = function () {
                    return $http.pendingRequests.length > 0;
                };

                scope.$watch(scope.isLoading, function (v) {
                    if (v) {
                        $('#dataloadingdiv').show();
                    } else {
                        $('#dataloadingdiv').hide();
                    }
                });

Não sei qual é o equivalente do $http.pendingRequests.length em vanilla Javascript, mas a ideia é esta

Em Jquery tens o .ajaxStart() que executa quando um evento qualqer de ajax começa ( só pode ser usado juntando ao "document" do estilo document.ajaxStart) e o .ajaxStop() que executa quando todas as calls acabarem


Código:
$( document ).ajaxStart(function() {
$( "#loading" ).show();
});


$( document ).ajaxStop(function() {
$( "#loading" ).hide();
});
 
Última edição:
Back
Topo