web-dev-qa-db-fra.com

Empêcher l'action onclick avec jQuery

il y a des liens avec des actions d'événement onclick

<a href="#" onclick="alert('panic!')">Let's panic</a>
<a href="#" onclick="alert('panic!')" disabled="disabled">I can't panic no more</a>

J'ai besoin d'empêcher l'exécution des actons d'événement sur les liens avec l'attribut désactivé sans supprimer les actions onclick.

$('a[disabled]').click(function(e){
  e.stopPropagation();
  return false;
});

Ce code ne m'aide pas.

mise à jour Même ce code ne fonctionne pas

<html><head><script type='text/javascript' src='jquery-1.3.2.js'></script></head>
<body>
<a href='#' onclick="alert('HA-ha!')" disabled="disabled" class="disabled">TEST</a>
<script type="text/javascript">
    $('a[disabled], a.disabled').click(function(e){
        console.log('override?');
        e.stopImmediatePropagation();           
            e.preventDefault();
        e.stopPropagation();
        return false;       
    });
</script>
</body></html>
30
Andrew Rumm

jQuery ne va pas résoudre celui-ci OOTB. Cela peut aider, mais rien de stopPropagation, stopImmediatePropagation, preventDefault, return false Ne fonctionnera si vous les attachez simplement à l'élément. Vous devez remplacer le gestionnaire de clics de l'élément.

Cependant, vous indiquez dans votre question "sans supprimer les actions onclick" . Vous devez donc remplacer le comportement par défaut au moment où l'événement est déclenché (par opposition à l'approche plus simple consistant simplement à nullà supprimer l'attribut onclick pour les ancres désactivées):

Voici ce que je veux dire:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<title>Disable clicks</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
  <a href="#" onclick="alert('panic!')">Let's panic</a>
  <a href="#" onclick="alert('panic!')" disabled="disabled">I can't panic no more</a>

  <script>
  $('a[onclick]').each(function(){
    $(this).data('onclick', this.onclick);

    this.onclick = function(event) {
      if($(this).attr('disabled')) { // HERE
        return false;
      };

      $(this).data('onclick').call(this, event || window.event);
    };
  });
  </script>
</body>
</html>

Démo ici.

L'approche consiste à remplacer le gestionnaire de clics en ligne (onclick) avec une logique préemptive pour détecter le cas où l'ancre est "désactivée" et puis annuler l'événement (avec return false).

L'avantage est que pour réactiver une ancre, il vous suffit de .removeAttr('disabled') dessus.

54
Crescent Fresh

disabled n'est pas une propriété des ancres. Utilisez quelque chose comme rel='disabled' au lieu.

$('a[rel="disabled"]').click( function() { return false; } );

Mise à jour:

Ah, bien sûr. Il déclenche toujours le alert car il est en fait en ligne dans le balisage! Je ne fais jamais ça et je n'ai donc pas remarqué. Retirez ce gestionnaire de clics du balisage et faites-le dans jQuery en premier lieu et vous pourrez alors simplement faire quelque chose comme:

$('a').click( function() {
  if( $(this).attr('rel') == 'disabled' ) { return; }
  // do stuff here when not disabled
  return false; // so your '#' href doesn't get used
} );
7
rfunduk

Le problème est que jQuery ajoute des événements dans l'ordre. Pour arrêter d'autres événements, les événements que vous devez arrêter doivent venir après votre code d'arrêt. Puisque vous avez du code dans votre clic, vous devrez modifier la commande. Voici ce que je ferais:

<a href='#' onclick="alert('HA-ha!')" class="disabled">TEST</a>
<a href='#' onclick="alert('HA-ha!')">TEST</a>
<script type="text/javascript">
    $('a').each(function(){
        // Cache event
        var existing_event = this.onclick;

        // Remove the event from the link
        this.onclick = null;

        // Add a check in for the class disabled
        $(this).click(function(e){ 
            if($(this).hasClass('disabled')){
                e.stopImmediatePropagation();
                e.preventDefault();
            }                
        });

        // Reattach your original onclick, but now in the correct order
        // if it was set in the first place
        if(existing_event) $(this).click(existing_event);
    });
</script>

L'avantage est simplement de supprimer/ajouter la classe désactivée à l'aide de jQuery: $('a#whatever').addClass('disabled') ou de la supprimer $('a#whatever').removeClass('disabled') et aucun autre nettoyage/configuration n'est requis.

5
Doug Neiner

Tous les gestionnaires de clics ajoutés par jQuery semblent se déclencher après ceux ajoutés dans le balisage. Ma solution serait d'appliquer les gestionnaires de clics à l'aide de jQuery au lieu de dans le balisage, mais vous pouvez ne pas avoir suffisamment de contrôle sur le code pour ce faire. Si vous le faites, n'appliquez simplement pas le gestionnaire de clic aux balises d'ancrage avec la classe désactivée (et, oui, j'utiliserais une classe plutôt qu'un attribut inapproprié). Si vous n'avez pas de contrôle sur le balisage, vous souhaiterez peut-être remplacer le gestionnaire de clics à l'aide de jQuery, en le stockant pour une réapplication ultérieure.

   $(function() {
      $('a.disabled').each( function() {
         var $this = $(this);
         var click = $this.attr('onclick');
         if (click) {
             $this.data('click',click);
             // add return false to prevent default action
             $this[0].onclick =  function() { return false; };
         }
      });

      $('#restoreClick').click( function() {
          $('a.disabled').each( function() {
              var $this = $(this);
              $this.removeClass('disabled');
              var click = $this.data('click');
              if (click) {
                  $this[0].onclick = click;
              }
          });
      });
   });

Testé avec:

<div>
    <a href="#" onclick="alert('panic!')">Let's panic</a>
    <a href="#" onclick="alert('panic!')" class="disabled">I can't panic no more</a>
</div>
<div>
    <input type="button" id="restoreClick" value="Restore" />
</div>
1
tvanfosson

J'ai trouvé une solution assez simple pour empêcher les onclicks aujourd'hui, mais en conservant l'action si vous en avez besoin.

<a href="javascript:alert('panic!')" >Let's panic</a>
<a href="javascript:alert('panic!')" disabled="disabled">I can't panic no more</a>

$('a').click(function(e){
    if($(this).attr('disabled')) e.preventDefault();
});

Je ne suis pas un grand fan de l'utilisation de "javascript:", mais c'était de loin la solution la plus simple au problème.

J'espère que cela aide!

0
MrBojangles