Posso chiamare jquery click () per seguire un link <a> se non ho già associato un gestore eventi a bind o click?


175

Ho un timer nel mio JavaScript che deve emulare facendo clic su un collegamento per passare a un'altra pagina allo scadere del tempo. Per fare ciò sto usando la click()funzione di jQuery . Ho usato $().trigger()e window.locationanche, e posso farlo funzionare come previsto con tutti e tre.

Ho osservato alcuni comportamenti strani con click()e sto cercando di capire cosa succede e perché.

Sto usando Firefox per tutto ciò che descrivo in questa domanda, ma sono anche interessato a ciò che altri browser faranno con questo.

Se non ho usato $('a').bind('click',fn)o $('a').click(fn)per impostare un gestore eventi, quindi chiamare$('a').click() sembra non fare nulla. Non chiama il gestore predefinito del browser per questo evento, poiché il browser non carica la nuova pagina.

Tuttavia, se imposto prima un gestore eventi, allora funziona come previsto, anche se il gestore eventi non fa nulla.

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

Questo carica la nuova pagina come se avessi fatto clic su a me stesso.

Quindi la mia domanda è duplice: questo strano comportamento è perché sto facendo qualcosa di sbagliato da qualche parte? e perché chiamare non click()fa nulla con il comportamento predefinito se non ho creato un gestore per conto mio?

MODIFICARE:

Come ha determinato Hoffman quando ha cercato di duplicare i miei risultati, il risultato che ho descritto sopra non accade in realtà. Non sono sicuro di ciò che ha causato gli eventi osservati ieri, ma sono certo oggi che non era quello che ho descritto nella domanda.

Quindi la risposta è che non è possibile "falsificare" i clic nel browser e che tutto ciò che jQuery fa è chiamare il gestore dell'evento. Puoi ancora usare window.locationper cambiare pagina, e per me funziona benissimo.


2
Potrebbe essere una soluzione: stackoverflow.com/questions/31687759/...
Sukrit Chhabra

Risposte:


90

Interessante, questa è probabilmente una "richiesta di funzionalità" (cioè bug) per jQuery. L'evento click jQuery innesca l'azione click (chiamata evento onClick sul DOM) sull'elemento se si associa un evento jQuery all'elemento. Dovresti andare alle mailing list di jQuery ( http://forum.jquery.com/ ) e segnalarlo. Questo potrebbe essere il comportamento desiderato, ma io non la penso così.

MODIFICARE:

Ho fatto alcuni test e quello che hai detto è sbagliato, anche se associ una funzione a un tag "a", non ti porta ancora al sito Web specificato dall'attributo href. Prova il seguente codice:

<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> 

Non va mai su google.com a meno che non si faccia clic direttamente sul collegamento (con o senza il codice commentato). Si noti inoltre che anche se si associa l'evento click al collegamento, esso non diventa viola dopo aver fatto clic sul pulsante. Diventa viola solo se fai clic direttamente sul link.

Ho fatto qualche ricerca e sembra che .click non supponga di funzionare con i tag 'a' perché il browser non supporta il "clic falso" con javascript. Voglio dire, non puoi "fare clic" su un elemento con JavaScript. Con i tag "a" puoi attivare il suo evento onClick ma il collegamento non cambierà i colori (al colore del collegamento visitato, il valore predefinito è viola nella maggior parte dei browser). Quindi non avrebbe senso far funzionare l'evento $ (). Click con i tag 'a' poiché l'atto di andare all'attributo href non fa parte dell'evento onClick, ma è codificato nel browser.


7
Ho provato il tuo codice, e fa esattamente come hai detto, ma il mio codice fa come ho descritto sopra. Farò altri esperimenti e vedrò se riesco a mettere insieme un semplice esempio dei miei risultati che puoi provare.
Mnebuerquo,

1
Ok. Deve essere stato qualcosa di sbagliato. Ero assolutamente certo al momento in cui ho pubblicato la mia domanda che funzionava, ma da quando ho provato il tuo esempio il mio non funziona più. Tornerò semplicemente a utilizzare window.location per cambiare pagina e non provare a simulare il clic.
Mnebuerquo,

In effetti, click () non ha lo scopo di creare clic falsi, ma a volte possiamo usarlo per fare clic su pulsanti o moduli con iniezioni di javascript o solo per comodità durante la creazione di un tasto di scelta rapida temporaneo sopra le funzioni javascript esistenti.
Aero Wang,

241

Un'altra opzione è ovviamente usare solo javascript alla vaniglia:

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

1
Questo non funziona in Safari e, secondo le specifiche HTML, solo gli input devono implementarlo.
Jeremy Kauffman,

4
Dang! Questo funziona! Ma devo dire che non è abbastanza "vaniglia" javascript poiché utilizza un elemento jquery, quindi è javery jquery una specie di vaniglia .... Funziona in Firefox 24 e IE 10.
bgmCoder

@BGM, ok, ma il clic () non è su un elemento jquery. È possibile sostituirlo con getElementById (".."). Click ()
Peter

wow ferito pieno, funziona come mi aspettavo. +1 dato :). Per altri utenti, puoi anche usare come: var lnk = document.getElementById ("a_link"); if (lnk == null) {// do some ....} else {lnk.click (); }
Iqbal,

Testato su vari browser, IE10 e Jquery 1.6.4 non possono gestirlo.
Hannes Schneidermayer,

65

Se guardi il codice per la $.clickfunzione Scommetto che c'è un'istruzione condizionale che controlla se l'elemento ha listener registrati per l' clickevento prima che proceda. Perché non ottenere semplicemente l' hrefattributo dal link e modificare manualmente la posizione della pagina?

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

EDIT: Ecco perché non fa clic, dalla triggerfunzione, sorgente jQuery per la versione 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) {}
    }

Dopo aver chiamato i gestori (se ce ne sono), jQuery attiva un evento sull'oggetto. Tuttavia chiama i gestori nativi solo per gli eventi click se l'elemento non è un collegamento. Immagino che questo sia stato fatto apposta per qualche motivo. Questo dovrebbe essere vero anche se un gestore eventi è definito o meno, quindi non sono sicuro del perché nel tuo caso il collegamento di un gestore eventi abbia causato la onClickchiamata al gestore nativo . Dovrai fare quello che ho fatto e passare attraverso l'esecuzione per vedere dove viene chiamato.


Posso certamente usare window.location e l'href come ho detto nella domanda. Sto cercando di capire cosa succede in jquery click () e cosa causa i risultati che ho osservato.
Mnebuerquo,

Ho modificato la mia risposta per mostrare dove nella fonte jQuery gestisce le chiamate $ .click () sui collegamenti.
Ryan Lynch,

2
window.location funziona, ma non pubblica HTTP Referrer e interrompe il pulsante Indietro.
Chase Seibert,

5

I gestori di clic sui tag di ancoraggio sono un caso speciale in jQuery.

Penso che potresti essere confuso tra l'evento onclick dell'ancora (noto dal browser) e l'evento click dell'oggetto jQuery che avvolge la nozione di DOM del tag anchor.

Puoi scaricare la fonte jQuery 1.3.2 qui .

Le sezioni rilevanti della fonte sono le righe 2643-2645 (l'ho diviso in più righe per facilitarne la comprensione):

// 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 non supporta il comportamento predefinito dei collegamenti "cliccati" a livello di codice.

Quello che puoi fare è creare un modulo e inviarlo. In questo modo non è necessario utilizzare window.locationo window.open, che sono spesso bloccati come popup indesiderati dai browser.

Questo script ha 2 metodi diversi: uno che tenta di aprire 3 nuove schede / finestre (ne apre solo 1 in IE e Chrome, più informazioni di seguito) e uno che genera un evento personalizzato al clic del link.

Ecco come:

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;
    });

});

Quello che fa è per ogni elemento di collegamento:

  1. Crea un modulo
  2. Dagli attributi
  3. Aggiungilo al DOM in modo che possa essere inviato
  4. Invialo
  5. Rimuovi il modulo dal DOM, rimuovendo tutte le tracce * Inserisci risata diabolica *

Ora hai una nuova scheda / finestra di caricamento "https://google.nl"(o qualsiasi URL che desideri, basta sostituirlo). Sfortunatamente quando provi ad aprire più di una finestra in questo modo, ricevi una Popup blockedbarra dei messaggi quando provi ad aprire la seconda (la prima è ancora aperta).


Maggiori informazioni su come sono arrivato a questo metodo sono disponibili qui:

Aprire una nuova finestra / scheda senza usare window.openowindow.location.href


3

Attiva un elemento Collegamento ipertestuale che si trova all'interno dell'elemento che desideri collegare a jquery .click ()

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

Nel tuo script si collega al contenitore principale su cui si desidera l'evento click. Quindi si utilizza la metodologia jquery standard per trovare l'elemento (tipo, classe, id) e attivare il clic. Quello che succede è che jquery entra in una funzione ricorsiva per attivare il clic e tu interrompi la funzione ricorsiva prendendo l'evento 'e' e la funzione stopPropagation () e restituendo false perché non vuoi che jquery faccia altro che attivare il collegamento.

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

La soluzione alternativa è quella di avvolgere i contenitori nell'elemento e posizionarli come contenitori all'interno anziché. Impostare gli span in modo che il blocco display sia conforme agli standard w3c.


3

È possibile utilizzare jQuery per selezionare l'oggetto jQuery per quell'elemento. Quindi, ottieni l'elemento DOM sottostante e chiama il suo click()metodo.

per id

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

oppure usa jQuery per fare clic su un gruppo di collegamenti per classe CSS

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

2

Non fa nulla perché nessun evento è stato associato all'evento. Se ricordo bene, jQuery mantiene il proprio elenco di gestori di eventi associati a NodeList per prestazioni e altri scopi.


2

Se hai bisogno di questa funzione per un caso o pochissime cassette. (la tua intera app non richiede questa funzionalità) Preferirei lasciare jQuery così com'è (per molti motivi, inclusa la possibilità di aggiornare a versioni più recenti, CDN ecc.) e avere la seguente soluzione alternativa:

// 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

Per aprire il collegamento ipertestuale nella stessa scheda, utilizzare:

$(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;
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.