web-dev-qa-db-fra.com

Comment puis-je simuler un clic sur une balise d'ancrage?

Je veux simuler un clic sur une balise d'ancrage avec tous les extras comme le traitement correct de la cible.

Il semble exister une méthode "[click ()] [3]" pour l'objet DOM d'ancrage, mais tous les navigateurs ne la prennent pas en charge. Firefox lève cette erreur:

Erreur: anchorObj.click n'est pas une fonction

Cela fonctionne aussi étrangement sur Opera 10 et Konqueror, causant des clics infinis quand il est appelé à l'intérieur du gestionnaire onclick d'un div environnant. Je suppose que seul IE8 fonctionne bien avec cela. Quoi qu'il en soit, je ne le veux pas car les principaux navigateurs ont généralement des problèmes avec cela. 

J'ai trouvé cette solution alternative pour Firefox dans les forums Mozilla:

var evt = document.createEvent("MouseEvents"); 
evt.initMouseEvent("click", true, true, window, 
    0, 0, 0, 0, 0, false, false, false, false, 0, null); 
anchorObj.dispatchEvent(evt); 

Cela semble trop laid et encombrant pour moi. Je ne sais pas dans quelle mesure il est compatible et je veux éviter autant que possible d'écrire du code spécifique à votre navigateur.

Je ne peux pas utiliser location.href = anchorObj.href; car il ne gère pas l'attribut "cible". Je peux coder en fonction de la valeur de la cible, mais j'aimerais aussi l'éviter.

Il est suggéré de passer à JQuery, mais je ne sais pas si elle gère bien la propriété cible, car je n'y ai pas travaillé auparavant.

45
Sedat Kapanoglu

Voici un scénario de test complet qui simule l'événement click, appelle tous les gestionnaires attachés (quelle que soit leur nature), conserve l'attribut "target" ("srcElement" dans IE), des bulles semblables à celles d'un événement normal et émule la prévention de récursivité d'IE. Testé dans FF 2, Chrome 2.0, Opera 9.10 et bien sûr IE (6):

<!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">
<head>
<script>
function fakeClick(event, anchorObj) {
  if (anchorObj.click) {
    anchorObj.click()
  } else if(document.createEvent) {
    if(event.target !== anchorObj) {
      var evt = document.createEvent("MouseEvents"); 
      evt.initMouseEvent("click", true, true, window, 
          0, 0, 0, 0, 0, false, false, false, false, 0, null); 
      var allowDefault = anchorObj.dispatchEvent(evt);
      // you can check allowDefault for false to see if
      // any handler called evt.preventDefault().
      // Firefox will *not* redirect to anchorObj.href
      // for you. However every other browser will.
    }
  }
}
</script>
</head>
<body>

<div onclick="alert('Container clicked')">
  <a id="link" href="#" onclick="alert((event.target || event.srcElement).innerHTML)">Normal link</a>
</div>

<button type="button" onclick="fakeClick(event, document.getElementById('link'))">
  Fake Click on Normal Link
</button>

<br /><br />

<div onclick="alert('Container clicked')">
    <div onclick="fakeClick(event, this.getElementsByTagName('a')[0])"><a id="link2" href="#" onclick="alert('foo')">Embedded Link</a></div>
</div>

<button type="button" onclick="fakeClick(event, document.getElementById('link2'))">Fake Click on Embedded Link</button>

</body>
</html>

Démo ici.

Cela évite la récursivité dans les navigateurs non-IE en inspectant l'objet événement à l'origine du clic simulé, en inspectant l'attribut target de l'événement (qui reste inchangé pendant la propagation ).

Evidemment IE contient-il en interne une référence à son objet global event . Le niveau 2 du DOM ne définit pas cette variable globale. Pour cette raison, le simulateur doit transmettre sa copie locale de event.

62
Crescent Fresh

eh bien, vous pouvez très rapidement tester l'envoi des clics via jQuery comme

$('#link-id').click();

Si vous ne parvenez toujours pas à respecter la cible, vous pouvez toujours le faire.

$('#link-id').click( function( event, anchor )
{
  window.open( anchor.href, anchor.target, '' );
  event.preventDefault();
  return false;
});
11
Peter Bailey

Cité de https://developer.mozilla.org/en/DOM/element.click

La méthode de clic est destinée à être utilisée avec des éléments INPUT de type bouton, case à cocher, radio, réinitialisation ou soumission. Gecko n'implémente pas la méthode de clic sur d'autres éléments susceptibles de réagir à des clics de souris tels que des liens (éléments A), et ne déclenche pas nécessairement l'événement de clic d'autres éléments.

Les DOM non Gecko peuvent se comporter différemment. 

Malheureusement, il semble que vous ayez déjà découvert la meilleure solution à votre problème.

En remarque, je conviens que votre solution semble moins qu'idéale, mais si vous encapsulez la fonctionnalité dans une méthode (comme le ferait JQuery), ce n'est pas si grave.

11
Chris Shouts

Il y a un moyen plus simple d'y parvenir,

HTML 

<a href="https://getbootstrap.com/" id="fooLinkID" target="_blank">Bootstrap is life !</a>

JavaScript 

// Simulating click after 3 seconds
setTimeout(function(){
  document.getElementById('fooLinkID').click();
}, 3 * 1000);

Utilisation de javascript simple pour simuler un clic et adresse de la propriété cible.

Vous pouvez vérifier les exemples de travail ici/ jsFiddle .

6
Gaurav Gandhi

Aucune des solutions ci-dessus ne répond à l'intention générique de la demande initiale. Et si nous ne connaissions pas l'identifiant de l'ancre? Et si elle n'a pas d'identifiant? Que se passe-t-il s'il n'y a même pas de paramètre href (par exemple, l'icône précédent/suivant dans un carrousel)? Et si nous voulions appliquer l'action à plusieurs ancres avec différents modèles de manière agnostique? Voici un exemple qui fait quelque chose au lieu d'un clic, puis simule le clic plus tard (pour n'importe quelle ancre ou autre tag):

var clicker = null;
$('a').click(function(e){ 
    clicker=$(this); // capture the clicked dom object
    /* ... do something ... */
    e.preventDefault(); // prevent original click action
});
clicker[0].click(); // this repeats the original click. [0] is necessary.
0
Vision Hive