Puis-je appeler jquery click () pour suivre un lien <a> si je n'y ai pas déjà lié un gestionnaire d'événements avec bind ou click?


175

J'ai une minuterie dans mon JavaScript qui doit émuler en cliquant sur un lien pour accéder à une autre page une fois le temps écoulé. Pour ce faire, j'utilise la click()fonction de jQuery . J'ai utilisé $().trigger()et window.locationaussi, et je peux le faire fonctionner comme prévu avec les trois.

J'ai observé un comportement étrange avec click()et j'essaie de comprendre ce qui se passe et pourquoi.

J'utilise Firefox pour tout ce que je décris dans cette question, mais je suis également intéressé par ce que les autres navigateurs en feront.

Si je n'ai pas utilisé $('a').bind('click',fn)ou $('a').click(fn)défini de gestionnaire d'événements, alors l'appel $('a').click()semble ne rien faire du tout. Il n'appelle pas le gestionnaire par défaut du navigateur pour cet événement, car le navigateur ne charge pas la nouvelle page.

Cependant, si je définis d'abord un gestionnaire d'événements, cela fonctionne comme prévu, même si le gestionnaire d'événements ne fait rien.

$('a').click(function(){return true;}).click();

Cela charge la nouvelle page comme si j'avais cliqué sur le moi-même.

Ma question est donc double: est-ce un comportement étrange parce que je fais quelque chose de mal quelque part? et pourquoi l'appel click()ne fait rien avec le comportement par défaut si je n'ai pas créé mon propre gestionnaire?

ÉDITER:

Comme Hoffman l'a déterminé lorsqu'il a essayé de reproduire mes résultats, le résultat que j'ai décrit ci-dessus ne se produit pas réellement. Je ne suis pas sûr de la cause des événements que j'ai observés hier, mais je suis certain aujourd'hui que ce n'est pas ce que j'ai décrit dans la question.

Donc, la réponse est que vous ne pouvez pas "faux" clics dans le navigateur et que tout ce que jQuery fait est d'appeler votre gestionnaire d'événements. Vous pouvez toujours utiliser window.locationpour changer de page, et cela fonctionne très bien pour moi.


Réponses:


90

Intéressant, il s'agit probablement d'une "demande de fonctionnalité" (ie bug) pour jQuery. L'événement de clic jQuery ne déclenche l'action de clic (appelée événement onClick sur le DOM) que si vous liez un événement jQuery à l'élément. Vous devriez aller sur les listes de diffusion jQuery ( http://forum.jquery.com/ ) et le signaler. C'est peut-être le comportement recherché, mais je ne pense pas.

ÉDITER:

J'ai fait quelques tests et ce que vous avez dit est faux, même si vous liez une fonction à une balise «a», cela ne vous amène toujours pas au site Web spécifié par l'attribut href. Essayez le code suivant:

<html>
<head>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
 <script>
  $(document).ready(function() {
   /* Try to dis-comment this:
   $('#a').click(function () {
    alert('jQuery.click()');
    return true;
   });
   */
  });
  function button_onClick() {
   $('#a').click();
  }
  function a_onClick() {
   alert('a_onClick');
  }
 </script>

</head>
<body>
 <input type="button" onclick="button_onClick()">
 <br>
 <a id='a' href='http://www.google.com' onClick="a_onClick()"> aaa </a>

</body>
</html> 

Il ne va jamais sur google.com sauf si vous cliquez directement sur le lien (avec ou sans le code commenté). Notez également que même si vous liez l'événement de clic au lien, il ne devient toujours pas violet une fois que vous cliquez sur le bouton. Il ne devient violet que si vous cliquez directement sur le lien.

J'ai fait quelques recherches et il semble que le .click ne soit pas supposé fonctionner avec les balises 'a' car le navigateur ne supporte pas le "faux clic" avec javascript. Je veux dire, vous ne pouvez pas "cliquer" sur un élément avec javascript. Avec les balises «a», vous pouvez déclencher son événement onClick mais le lien ne changera pas de couleur (en couleur du lien visité, la couleur par défaut est le violet dans la plupart des navigateurs). Cela n'aurait donc pas de sens de faire fonctionner l'événement $ (). Click avec les balises 'a' puisque l'acte d'aller à l'attribut href ne fait pas partie de l'événement onClick, mais est codé en dur dans le navigateur.


7
J'ai essayé votre code, et il fait exactement ce que vous avez dit, mais mon code fait comme je l'ai décrit ci-dessus. Je vais faire d'autres expériences et voir si je peux rassembler un exemple simple de mes résultats que vous pouvez essayer.
Mnebuerquo

1
D'accord. Cela a dû être quelque chose que j'ai mal fait. J'étais absolument certain au moment où j'ai posté ma question que cela fonctionnait, mais depuis que j'ai essayé votre exemple, le mien ne fonctionne plus. Je vais simplement revenir à l'utilisation de window.location pour changer la page et ne pas essayer de simuler le clic.
Mnebuerquo

En effet, le click () n'est pas destiné à créer de faux clics mais parfois nous pouvons l'utiliser pour cliquer sur des boutons ou des formulaires avec des injections javascript ou tout simplement pour la commodité tout en créant un raccourci clavier temporaire en plus des fonctions javascript existantes.
Aero Wang

241

Une autre option est bien sûr d'utiliser simplement du javascript vanille:

document.getElementById("a_link").click()

1
Cela ne fonctionne pas dans Safari, et selon les spécifications HTML, seules les entrées doivent l'implémenter.
Jeremy Kauffman

4
Dang! Cela fonctionne! Mais je dois dire que ce n'est pas tout à fait du javascript "vanille" puisqu'il utilise un élément jquery, donc c'est du javascript jquery en quelque sorte vanille .... Cela fonctionne dans Firefox 24 et IE 10.
bgmCoder

@BGM, ok, mais le clic () n'est pas sur un élément jquery. Vous pouvez le remplacer par getElementById (".."). Click ()
Peter

wow blessure complète, fonctionne comme je m'y attendais. +1 donné :). Pour les autres utilisateurs, vous pouvez également utiliser comme: var lnk = document.getElementById ("a_link"); if (lnk == null) {// en faire ....} else {lnk.click (); }
Iqbal

Testé dans divers navigateurs, IE10 et Jquery 1.6.4 ne peuvent pas gérer cela.
Hannes Schneidermayer

65

Si vous regardez le code de la $.clickfonction, je parie qu'il y a une instruction conditionnelle qui vérifie si l'élément a des écouteurs enregistrés pour l' clickévénement avant qu'il ne se poursuive. Pourquoi ne pas simplement obtenir l' hrefattribut à partir du lien et modifier manuellement l'emplacement de la page?

 window.location.href = $('a').attr('href');

EDIT: Voici pourquoi il ne clique pas, à partir de la triggerfonction, source jQuery pour la version 1.3.2:

 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
    if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
        event.result = false;

    // Trigger the native events (except for clicks on links)
    if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
        this.triggered = true;
        try {
            elem[ type ]();
        // prevent IE from throwing an error for some hidden elements
        } catch (e) {}
    }

Après avoir appelé des gestionnaires (s'il y en a), jQuery déclenche un événement sur l'objet. Cependant, il n'appelle des gestionnaires natifs pour les événements de clic que si l'élément n'est pas un lien. Je suppose que cela a été fait à dessein pour une raison quelconque. Cela devrait être vrai, qu'un gestionnaire d'événements soit défini ou non, donc je ne sais pas pourquoi dans votre cas, l'attachement d'un gestionnaire d'événements a provoqué l' onClickappel du gestionnaire natif . Vous devrez faire ce que j'ai fait et parcourir l'exécution pour voir où elle est appelée.


Je peux certainement utiliser window.location et href comme je l'ai mentionné dans la question. J'essaie de comprendre ce qui se passe dans jquery click (), et ce qui cause les résultats que j'ai observés.
Mnebuerquo

J'ai modifié ma réponse pour montrer où dans la source jQuery il traite les appels $ .click () sur les liens.
Ryan Lynch

2
window.location fonctionne, mais ne publie pas le référent HTTP et interrompt le bouton de retour.
Chase Seibert le

5

Les gestionnaires de clics sur les balises d'ancrage sont un cas particulier dans jQuery.

Je pense que vous pourriez être confus entre l'événement onclick de l'ancre (connu par le navigateur) et l'événement click de l'objet jQuery qui englobe la notion DOM de la balise d'ancrage.

Vous pouvez télécharger la source jQuery 1.3.2 ici .

Les sections pertinentes de la source sont les lignes 2643-2645 (j'ai divisé ceci en plusieurs lignes pour le rendre plus facile à comprendre):

// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if (
     (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && 
       elem["on"+type] && 
       elem["on"+type].apply( elem, data ) === false
   )
     event.result = false;

5

JS / jQuery ne prend pas en charge le comportement par défaut des liens «cliqués» par programmation.

Ce que vous pouvez faire, c'est créer un formulaire et le soumettre. De cette façon, vous n'avez pas à utiliser window.locationou window.open, qui sont souvent bloqués en tant que fenêtres contextuelles indésirables par les navigateurs.

Ce script a 2 méthodes différentes: une qui essaie d'ouvrir 3 nouveaux onglets / fenêtres (il n'en ouvre qu'un dans IE et Chrome, plus d'informations ci-dessous) et une qui déclenche un événement personnalisé lors d'un clic sur le lien.

Voici comment:

HTML

<html>
<head>
    <script src="jquery-1.9.1.min.js" type="text/javascript"></script>
    <script src="script.js" type="text/javascript"></script>
</head>
<body>
    <button id="testbtn">Test</button><br><br>

    <a href="https://google.nl">GOOGLE</a><br>
    <a href="http://en.wikipedia.org/wiki/Main_Page">WIKI</a><br>
    <a href="https://stackoverflow.com/">SO</a>
</body>
</html>

jQuery (script.js)

$(function()
{ 
    // Try to open all 3 links by pressing the button
    // - Firefox opens all 3 links
    // - Chrome only opens 1 of them without popup warning
    // - IE only opens 1 of them WITH popup warning
    $("#testbtn").on("click", function()
    {
        $("a").each(function()
        {
            var form = $("<form></form>");
            form.attr(
            {
                id     : "formform",
                action : $(this).attr("href"),
                method : "GET",
                // Open in new window/tab
                target : "_blank"
            });

            $("body").append(form);
            $("#formform").submit();
            $("#formform").remove();
        });
    });

    // Or click the link and fire a custom event 
    // (open your own window without following the link itself)
    $("a").on("click", function()
    {
        var form = $("<form></form>");
        form.attr(
        {
            id     : "formform",
            // The location given in the link itself
            action : $(this).attr("href"), 
            method : "GET",
            // Open in new window/tab
            target : "_blank"              
        });

        $("body").append(form);
        $("#formform").submit();
        $("#formform").remove();

        // Prevent the link from opening normally
        return false;
    });

});

Ce qu'il fait est pour chaque élément de lien:

  1. Créer un formulaire
  2. Donnez-lui des attributs
  3. Ajoutez-le au DOM pour qu'il puisse être soumis
  4. Soumet le
  5. Supprimez le formulaire du DOM, en supprimant toutes les traces * Insérez un rire diabolique *

Maintenant vous avez un nouvel onglet / fenêtre de chargement "https://google.nl"(ou n'importe quelle URL que vous voulez, remplacez-le simplement). Malheureusement, lorsque vous essayez d'ouvrir plus d'une fenêtre de cette façon, vous obtenez une Popup blockedbarre de messages lorsque vous essayez d'ouvrir la seconde (la première est toujours ouverte).


Plus d'informations sur la façon dont je suis arrivé à cette méthode se trouvent ici:

Ouverture d'une nouvelle fenêtre / onglet sans utiliser window.openouwindow.location.href


3

Déclenchez un élément Hyperlink qui se trouve à l'intérieur de l'élément auquel vous souhaitez connecter la jquery .click ()

<div class="TopicControl">
    <div class="articleImage">
       <a href=""><img src="" alt=""></a>
    </div>
</div>

Dans votre script, vous vous connectez au conteneur principal sur lequel vous souhaitez que l'événement de clic. Ensuite, vous utilisez la méthodologie jquery standard pour trouver l'élément (type, classe, id) et déclencher le clic. Ce qui se passe, c'est que jquery entre dans une fonction récursive pour déclencher le clic et que vous interrompez la fonction récursive en prenant l'événement 'e' et la fonction stopPropagation () et retournez false parce que vous ne voulez pas que jquery fasse autre chose que déclencher le lien.

$('.TopicControl').click(function (event) {
         $(this).find('a').click();
        event.stopPropagation();
        return false;
     });

Une solution alternative consiste à envelopper les conteneurs dans l'élément et à les placer comme conteneurs à l'intérieur au lieu de ceux. Définissez les portées pour afficher le bloc pour se conformer aux normes w3c.


3

Vous pouvez utiliser jQuery pour sélectionner l'objet jQuery pour cet élément. Ensuite, récupérez l'élément DOM sous-jacent et appelez sonclick() méthode.

par identifiant

$("#my-link").each(function (index) { $(this).get(0).click() });

ou utilisez jQuery pour cliquer sur un tas de liens par classe CSS

$(".my-link-class").each(function (index) { $(this).get(0).click() });

2

Il ne fait rien car aucun événement n'a été lié à l'événement. Si je me souviens bien, jQuery maintient sa propre liste de gestionnaires d'événements liés à NodeLists à des fins de performances et à d'autres fins.


2

Si vous avez besoin de cette fonctionnalité pour un cas ou très peu de cas. (toute votre application ne nécessite pas cette fonctionnalité) Je préfère laisser jQuery tel quel (pour de nombreuses raisons, y compris la possibilité de mettre à jour vers des versions plus récentes, CDN, etc.) et avoir la solution de contournement suivante:

// For modren Browsers
$(ele).trigger("click");

// Relaying on Paul Irish's conditional class names http://bit.ly/HWIpAp (via HTML5 Boilerplate http://bit.ly/HUzi3I) where each IE version gets a class of its Version
$("html.ie7").length && (function(){
    var eleOnClickattr = $(ele).attr("onclick") 
    eval(eleOnClickattr);
  })()

1

Pour ouvrir le lien hypertexte dans le même onglet, utilisez:

$(document).on('click', "a.classname", function() {
    var form = $("<form></form>");
    form.attr(
    {
        id     : "formid",
        action : $(this).attr("href"),
        method : "GET",
    });

    $("body").append(form);
    $("#formid").submit();
    $("#formid").remove();
    return false;
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.