¿Puedo llamar a jquery click () para seguir un enlace <a> si aún no he vinculado un controlador de eventos con bind o click?

175

Tengo un temporizador en mi JavaScript que necesita emular haciendo clic en un enlace para ir a otra página una vez que transcurre el tiempo. Para hacer esto estoy usando la click()función de jQuery . Lo he usado $().trigger()y window.locationtambién, y puedo hacerlo funcionar según lo previsto con los tres.

He observado algunos comportamientos extraños click()y estoy tratando de entender qué sucede y por qué.

Estoy usando Firefox para todo lo que describo en esta pregunta, pero también estoy interesado en lo que otros navegadores harán con esto.

Si no he usado $('a').bind('click',fn)o $('a').click(fn)para configurar un controlador de eventos, llamar no $('a').click()parece hacer nada. No llama al controlador predeterminado del navegador para este evento, ya que el navegador no carga la nueva página.

Sin embargo, si configuro un controlador de eventos primero, entonces funciona como se esperaba, incluso si el controlador de eventos no hace nada.

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

Esto carga la nueva página como si hubiera hecho clic en el mismo.

Entonces mi pregunta es doble: ¿Es este comportamiento extraño porque estoy haciendo algo mal en alguna parte? ¿Y por qué las llamadas no click()hacen nada con el comportamiento predeterminado si no he creado un controlador propio?

EDITAR:

Como Hoffman determinó cuándo intentó duplicar mis resultados, el resultado que describí anteriormente en realidad no sucede. No estoy seguro de qué causó los eventos que observé ayer, pero hoy estoy seguro de que no fue lo que describí en la pregunta.

Entonces, la respuesta es que no puede hacer "falsos" clics en el navegador y que todo lo que hace jQuery es llamar a su controlador de eventos. Todavía puede usar window.locationpara cambiar de página, y eso funciona bien para mí.

Mnebuerquo
fuente
2
Podría ser una solución: stackoverflow.com/questions/31687759/…
Sukrit Chhabra

Respuestas:

90

Interesante, esta es probablemente una "solicitud de función" (es decir, un error) para jQuery. El evento click de jQuery solo activa la acción click (llamada evento onClick en el DOM) en el elemento si vincula un evento jQuery al elemento. Debe ir a las listas de correo de jQuery ( http://forum.jquery.com/ ) y reportar esto. Este podría ser el comportamiento deseado, pero no lo creo.

EDITAR:

Hice algunas pruebas y lo que dijiste está mal, incluso si unes una función a una etiqueta 'a', todavía no te lleva al sitio web especificado por el atributo href. Prueba el siguiente código:

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

Nunca va a google.com a menos que haga clic directamente en el enlace (con o sin el código comentado). También tenga en cuenta que incluso si vincula el evento de clic al enlace, aún no se vuelve púrpura una vez que hace clic en el botón. Solo se vuelve púrpura si hace clic directamente en el enlace.

Investigué un poco y parece que el .click no debe funcionar con las etiquetas 'a' porque el navegador no admite "clic falso" con javascript. Quiero decir, no puedes "hacer clic" en un elemento con javascript. Con las etiquetas 'a' puede activar su evento onClick, pero el enlace no cambiará de color (al color del enlace visitado, el valor predeterminado es púrpura en la mayoría de los navegadores). Por lo tanto, no tendría sentido hacer que el evento $ (). Click funcione con las etiquetas 'a' ya que el acto de ir al atributo href no forma parte del evento onClick, sino que está codificado en el navegador.

Hoffmann
fuente
77
Probé su código, y hace exactamente lo que usted dijo, pero mi código hace lo que describí anteriormente. Haré algunos experimentos más y veré si puedo armar un ejemplo simple de mis resultados que puedas probar.
Mnebuerquo
1
Okay. Debe haber sido algo que hice mal. Estaba absolutamente seguro en el momento en que publiqué mi pregunta de que estaba funcionando, pero desde que probé su ejemplo, el mío ya no funciona. Volveré a usar window.location para cambiar la página y no intentar fingir el clic.
Mnebuerquo
De hecho, el clic () no está destinado a crear clics falsos, pero a veces podemos usarlo para hacer clic en botones o formularios con inyecciones de JavaScript o simplemente por conveniencia al crear una tecla de acceso rápido temporal sobre las funciones de JavaScript existentes.
Aero Wang
241

Otra opción es, por supuesto, usar solo JavaScript de vainilla:

document.getElementById("a_link").click()
Peter
fuente
1
Esto no funciona en Safari, y de acuerdo con las especificaciones HTML, solo las entradas deben implementar esto.
Jeremy Kauffman
44
Dang! Esto funciona! Pero debo decir que no es un javascript "vainilla" ya que está usando un elemento jquery, por lo que es una especie de jaque jquery vainilla ... Funciona en Firefox 24 e IE 10.
bgmCoder
@BGM, está bien, pero el clic () no está en un elemento jquery. Puede reemplazarlo por getElementById (".."). Haga clic ()
Peter
wow wounder completo, funciona como esperaba. +1 dado :). Para otros usuarios, también puede usar como: var lnk = document.getElementById ("a_link"); if (lnk == null) {// haz algo ....} else {lnk.click (); }
Iqbal
Probado en varios navegadores, IE10 y Jquery 1.6.4 no pueden manejar esto.
Hannes Schneidermayer
65

Si observa el código de la $.clickfunción, apuesto a que hay una declaración condicional que verifica si el elemento tiene oyentes registrados para el clickevento antes de que continúe. ¿Por qué no solo obtener el hrefatributo del enlace y cambiar manualmente la ubicación de la página?

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

EDITAR: Esta es la razón por la cual no hace clic, desde la triggerfunción, fuente jQuery para la versión 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) {}
    }

Después de llamar a los controladores (si hay alguno) jQuery desencadena un evento en el objeto. Sin embargo, solo llama a controladores nativos para eventos de clic si el elemento no es un enlace. Supongo que esto se hizo a propósito por alguna razón. Sin embargo, esto debería ser cierto independientemente de si un controlador de eventos está definido o no, por lo que no estoy seguro de por qué en su caso, adjuntar un controlador de eventos provocó onClickque se llamara al controlador nativo . Tendrás que hacer lo que hice y pasar por la ejecución para ver dónde se llama.

Ryan Lynch
fuente
Ciertamente puedo usar window.location y href como mencioné en la pregunta. Estoy tratando de entender qué sucede en jquery click () y qué causa los resultados que observé.
Mnebuerquo
Edité mi respuesta para mostrar dónde en jQuery source se trata de llamadas $ .click () en enlaces.
Ryan Lynch
2
window.location funciona, pero no publica HTTP Referrer y rompe el botón de retroceso.
Chase Seibert
5

Los controladores de clics en las etiquetas de anclaje son un caso especial en jQuery.

Creo que puede confundirse entre el evento onclick del ancla (conocido por el navegador) y el evento click del objeto jQuery que envuelve la noción del DOM de la etiqueta del ancla.

Puede descargar la fuente jQuery 1.3.2 aquí .

Las secciones relevantes de la fuente son las líneas 2643-2645 (he dividido esto en varias líneas para que sea más fácil de comprender):

// 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;
marshally
fuente
5

JS / jQuery no admite el comportamiento predeterminado de los enlaces "cliqueados" mediante programación.

Lo que puede hacer es crear un formulario y enviarlo. De esta manera, no tiene que usar window.locationo window.open, que a menudo están bloqueados como ventanas emergentes no deseadas por los navegadores.

Este script tiene 2 métodos diferentes: uno que intenta abrir 3 pestañas / ventanas nuevas (abre solo 1 en IE y Chrome, más información a continuación) y otro que activa un evento personalizado al hacer clic en el enlace.

Aquí es cómo:

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

});

Lo que hace es para cada elemento de enlace:

  1. Crea un formulario
  2. Darle atributos
  3. Añádelo al DOM para que pueda enviarse
  4. Envialo
  5. Elimina el formulario del DOM, eliminando todos los rastros * Inserta risa malvada *

Ahora tiene una nueva pestaña / ventana de carga "https://google.nl"(o cualquier URL que desee, simplemente reemplácela). Desafortunadamente, cuando intentas abrir más de una ventana de esta manera, obtienes una Popup blockedbarra de mensajes cuando intentas abrir la segunda (la primera todavía está abierta).


Aquí encontrará más información sobre cómo llegué a este método:

Abrir una nueva ventana / pestaña sin usar window.openowindow.location.href

Richard de Wit
fuente
3

Active un elemento de hipervínculo que esté dentro del elemento que desea conectar a jquery .click ()

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

En su script, se conecta al contenedor principal en el que desea el evento de clic. Luego, utiliza la metodología estándar de jquery para encontrar el elemento (tipo, clase, id) y disparar el clic. Lo que sucede es que jquery ingresa una función recursiva para disparar el clic y se rompe la función recursiva tomando la función de evento 'e' y stopPropagation () y devuelve falso porque no desea que jquery haga nada más que disparar el enlace.

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

La solución alternativa es envolver los contenedores en el elemento y colocarlos como contenedores dentro en lugar de 's. Configure los tramos para mostrar el bloque de acuerdo con los estándares w3c.

Paul Styles
fuente
3

Puede usar jQuery para seleccionar el objeto jQuery para ese elemento. Luego, obtenga el elemento DOM subyacente y llame a su click()método.

por id

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

o use jQuery para hacer clic en un montón de enlaces por clase CSS

$(".my-link-class").each(function (index) { $(this).get(0).click() });
10 grano de arena
fuente
2

No hace nada porque no se han vinculado eventos al evento. Si recuerdo correctamente, jQuery mantiene su propia lista de controladores de eventos que están vinculados a NodeLists para el rendimiento y otros fines.

JasonWyatt
fuente
2

Si necesita esta función para un caso o muy pocos casos. (toda su aplicación no requiere esta función) Prefiero dejar jQuery como está (por muchas razones, incluida la posibilidad de actualizar a versiones más nuevas, CDN, etc.) y tener la siguiente solución:

// 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);
  })()
adardesign
fuente
1

Para abrir el hipervínculo en la misma pestaña, use:

$(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;
});
DHARMENDRA SINGH
fuente