Czy mogę wywołać jquery click (), aby podążać za linkiem <a>, jeśli nie powiązałem z nim obsługi zdarzeń za pomocą bind lub click?


175

Mam zegar w moim JavaScript, który musi emulować kliknięcie linku, aby przejść do innej strony po upływie czasu. Aby to zrobić, używam funkcji jQuery click(). Użyłem $().trigger()i window.locationrównież i mogę sprawić, że będzie działać zgodnie z przeznaczeniem ze wszystkimi trzema.

Zauważyłem dziwne zachowanie click()i próbuję zrozumieć, co się dzieje i dlaczego.

Używam Firefoksa do wszystkiego, co opisuję w tym pytaniu, ale interesuje mnie również, co inne przeglądarki będą z tym robić.

Jeśli nie użyłem $('a').bind('click',fn)ani $('a').click(fn)nie ustawiłem programu obsługi zdarzeń, wywołanie $('a').click()wydaje się nic nie robić. Nie wywołuje domyślnej procedury obsługi przeglądarki dla tego zdarzenia, ponieważ przeglądarka nie ładuje nowej strony.

Jeśli jednak najpierw ustawię procedurę obsługi zdarzeń, będzie działać zgodnie z oczekiwaniami, nawet jeśli program obsługi zdarzeń nic nie robi.

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

Spowoduje to załadowanie nowej strony, tak jakbym sam kliknął przycisk a.

Moje pytanie jest więc dwojakie: czy to dziwne zachowanie, ponieważ gdzieś robię coś złego? i dlaczego wywołanie click()nic nie robi z zachowaniem domyślnym, jeśli nie utworzyłem własnego modułu obsługi?

EDYTOWAĆ:

Jak ustalił Hoffman, próbując powielić moje wyniki, wynik, który opisałem powyżej, w rzeczywistości nie ma miejsca. Nie jestem pewien, co spowodowało wydarzenia, które wczoraj obserwowałem, ale dziś jestem pewien, że nie to opisałem w pytaniu.

Odpowiedź jest taka, że ​​nie można „udawać” kliknięć w przeglądarce i że wszystko, co robi jQuery, to wywoływanie modułu obsługi zdarzeń. Nadal możesz window.locationzmienić stronę, a dla mnie to działa dobrze.


Odpowiedzi:


90

Co ciekawe, jest to prawdopodobnie „prośba o funkcję” (tj. Błąd) dla jQuery. Zdarzenie jQuery click wyzwala akcję click (nazywaną zdarzeniem onClick w DOM) na elemencie tylko wtedy, gdy powiążesz zdarzenie jQuery z elementem. Powinieneś przejść do list mailingowych jQuery ( http://forum.jquery.com/ ) i zgłosić to. To może być pożądane zachowanie, ale nie sądzę.

EDYTOWAĆ:

Przeprowadziłem kilka testów i to, co powiedziałeś, jest błędne, nawet jeśli powiążesz funkcję ze znacznikiem „a”, nadal nie przeniesie Cię to do witryny określonej przez atrybut href. Wypróbuj następujący kod:

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

Nigdy nie trafia do google.com, chyba że klikniesz bezpośrednio link (z komentowanym kodem lub bez niego). Zauważ również, że nawet jeśli powiążesz zdarzenie kliknięcia z linkiem, nadal nie zmieni się ono na fioletowe po kliknięciu przycisku. Kolor zmienia się na fioletowy tylko po bezpośrednim kliknięciu linku.

Zrobiłem kilka badań i wydaje się, że .click nie powinien działać z tagami „a”, ponieważ przeglądarka nie obsługuje „fałszywego klikania” w języku JavaScript. Chodzi mi o to, że nie można „kliknąć” elementu za pomocą javascript. Za pomocą tagów „a” możesz wywołać zdarzenie onClick, ale link nie zmieni kolorów (w przypadku odwiedzanego koloru linku domyślnie w większości przeglądarek jest fioletowy). Dlatego nie miałoby sensu, aby zdarzenie $ (). Click działało z tagami „a”, ponieważ czynność przechodzenia do atrybutu href nie jest częścią zdarzenia onClick, ale jest zakodowana na stałe w przeglądarce.


7
Wypróbowałem Twój kod i działa dokładnie tak, jak powiedziałeś, ale mój kod działa tak, jak opisałem powyżej. Zrobię więcej eksperymentów i zobaczę, czy uda mi się zebrać prosty przykład moich wyników, który możesz wypróbować.
Mnebuerquo

1
Dobrze. To musiało być coś, co zrobiłem źle. W momencie, gdy zamieściłem moje pytanie, byłem absolutnie pewien, że działa, ale odkąd wypróbowałem twój przykład, mój już nie działa. Po prostu wrócę do używania window.location do zmiany strony i nie będę próbował udawać kliknięcia.
Mnebuerquo

Rzeczywiście, click () nie ma na celu tworzenia fałszywych kliknięć, ale czasami możemy go użyć do klikania przycisków lub formularzy z zastrzykami javascript lub po prostu dla wygody podczas tworzenia tymczasowego skrótu do istniejących funkcji javascript.
Aero Wang

241

Inną opcją jest oczywiście użycie zwykłego javascript:

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

1
To nie działa w Safari i zgodnie ze specyfikacją HTML tylko wejścia wymagają implementacji.
Jeremy Kauffman

4
Cholera! To działa! Ale muszę powiedzieć, że nie jest całkiem „wanilia” javascript, ponieważ jest za pomocą elementu jQuery, więc to sort-of-waniliowy jquery javascript .... To działa w Firefoksie i IE 10. 24
bgmCoder

@BGM, ok, ale click () nie znajduje się w elemencie jquery. Możesz go zamienić na getElementById (".."). Click ()
Piotr,

wow rana pełna, działa zgodnie z oczekiwaniami. +1 podane :). W przypadku innych użytkowników możesz również użyć: var lnk = document.getElementById ("a_link"); if (lnk == null) {// zrób coś ....} else {lnk.click (); }
Iqbal

IE10 i Jquery 1.6.4 przetestowane w różnych przeglądarkach nie radzą sobie z tym.
Hannes Schneidermayer,

65

Jeśli spojrzysz na kod $.clickfunkcji, założę się, że istnieje instrukcja warunkowa, która sprawdza, czy element ma zarejestrowanych detektorów clickzdarzenia przed jego kontynuacją. Dlaczego nie pobrać hrefatrybutu z linku i ręcznie zmienić lokalizację strony?

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

EDYCJA: Oto dlaczego nie przechodzi, z triggerfunkcji, źródła jQuery dla wersji 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) {}
    }

Po wywołaniu programów obsługi (jeśli istnieją) jQuery wyzwala zdarzenie na obiekcie. Jednak wywołuje natywne programy obsługi dla zdarzeń kliknięcia tylko wtedy, gdy element nie jest łączem. Myślę, że z jakiegoś powodu zostało to zrobione celowo. Powinno to być prawdą, niezależnie od tego, czy program obsługi zdarzeń jest zdefiniowany, czy nie, więc nie jestem pewien, dlaczego w twoim przypadku dołączenie programu obsługi zdarzeń spowodowało onClickwywołanie natywnego programu obsługi. Będziesz musiał zrobić to, co ja, i przejść przez egzekucję, aby zobaczyć, gdzie się ona nazywa.


Z pewnością mogę użyć window.location i href, jak wspomniałem w pytaniu. Próbuję zrozumieć, co dzieje się w jquery click () i co powoduje zaobserwowane przeze mnie wyniki.
Mnebuerquo

Zredagowałem moją odpowiedź, aby pokazać, gdzie w źródle jQuery zajmuje się wywołaniami $ .click () na linkach.
Ryan Lynch

2
window.location działa, ale nie wysyła strony odsyłającej HTTP i przerywa działanie przycisku Wstecz.
Chase Seibert,

5

Mechanizmy obsługi kliknięć na tagach kotwicy są szczególnym przypadkiem w jQuery.

Myślę, że możesz być zdezorientowany między zdarzeniem onclick kotwicy (znanym przez przeglądarkę) a zdarzeniem click obiektu jQuery, który zawija pojęcie DOM o tagu kotwicy.

Możesz pobrać źródło jQuery 1.3.2 tutaj .

Odpowiednie sekcje źródła to wiersze 2643-2645 (podzieliłem to na wiele wierszy, aby ułatwić zrozumienie):

// 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 nie obsługuje programowo domyślnego zachowania linków „klikniętych”.

Możesz tylko utworzyć formularz i przesłać go. W ten sposób nie musisz używać window.locationlub window.open, które są często blokowane przez przeglądarki jako niechciane wyskakujące okienka.

Ten skrypt ma 2 różne metody: jedną, która próbuje otworzyć 3 nowe karty / okna (otwiera tylko 1 w IE i Chrome, więcej informacji poniżej) i drugą, która uruchamia niestandardowe zdarzenie po kliknięciu linku.

Oto jak:

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

});

To, co robi, dotyczy każdego elementu łącza:

  1. Utwórz formularz
  2. Nadaj mu atrybuty
  3. Dołącz go do DOM, aby można go było przesłać
  4. Prześlij to
  5. Usuń formularz z DOM, usuwając wszystkie ślady * Wstaw zły śmiech *

Teraz ładujesz nową kartę / okno "https://google.nl"(lub dowolny adres URL, po prostu go zastąp). Niestety, gdy próbujesz otworzyć w ten sposób więcej niż jedno okno, Popup blockedpojawia się pasek komunikatów podczas próby otwarcia drugiego (pierwsze jest nadal otwarte).


Więcej informacji o tym, jak doszedłem do tej metody, znajdziesz tutaj:

Otwieranie nowego okna / karty bez użycia window.openlubwindow.location.href


3

Uruchom element Hyperlink znajdujący się wewnątrz elementu, do którego chcesz podłączyć jquery .click ()

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

W swoim skrypcie łączysz się z głównym kontenerem, na którym chcesz zdarzenie kliknięcia. Następnie używasz standardowej metodologii jquery, aby znaleźć element (typ, klasę, identyfikator) i uruchomić kliknięcie. Dzieje się tak, gdy jquery wchodzi do funkcji rekurencyjnej, aby uruchomić kliknięcie, a ty przerywasz funkcję rekurencyjną, przyjmując zdarzenie „e” i funkcję stopPropagation () i zwracając false, ponieważ nie chcesz, aby jquery robił cokolwiek innego poza uruchomieniem łącza.

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

Alternatywnym rozwiązaniem jest zawinięcie pojemników w element i umieszczenie w nim pojemników zamiast pojemników. Ustaw rozpiętości tak, aby blok wyświetlania był zgodny ze standardami w3c.


3

Możesz użyć jQuery, aby wybrać obiekt jQuery dla tego elementu. Następnie pobierz podstawowy element DOM i wywołaj jego click()metodę.

według identyfikatora

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

lub użyj jQuery, aby kliknąć kilka linków według klasy CSS

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

2

Nie robi nic, ponieważ żadne wydarzenia nie zostały powiązane z wydarzeniem. Jeśli dobrze pamiętam, jQuery utrzymuje własną listę programów obsługi zdarzeń, które są powiązane z NodeLists dla wydajności i innych celów.


2

Jeśli potrzebujesz tej funkcji dla jednego przypadku lub bardzo niewielu kaset. (cała aplikacja nie wymaga tej funkcji) Wolałbym zostawić jQuery bez zmian (z wielu powodów, w tym możliwość aktualizacji do nowszych wersji, CDN itp.) i zastosować następujące obejście:

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

Aby otworzyć hiperłącze w tej samej karcie, użyj:

$(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;
});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.