Dapatkah saya memanggil klik jquery () untuk mengikuti tautan <a> jika saya belum mengikat event handler dengan bind atau klik?


175

Saya memiliki timer di JavaScript saya yang perlu meniru mengklik tautan untuk pergi ke halaman lain begitu waktu berlalu. Untuk melakukan ini saya menggunakan click()fungsi jQuery . Saya telah menggunakan $().trigger()dan window.locationjuga, dan saya bisa membuatnya berfungsi sebagaimana dimaksud dengan ketiganya.

Saya telah mengamati beberapa perilaku aneh click()dan saya mencoba memahami apa yang terjadi dan mengapa.

Saya menggunakan Firefox untuk semua yang saya jelaskan dalam pertanyaan ini, tetapi saya juga tertarik pada apa yang akan dilakukan browser lain dengan ini.

Jika saya belum pernah menggunakan $('a').bind('click',fn)atau $('a').click(fn)mengatur pengendali acara, maka menelepon $('a').click()sepertinya tidak melakukan apa-apa sama sekali. Itu tidak memanggil penangan default browser untuk acara ini, karena browser tidak memuat halaman baru.

Namun, jika saya menetapkan event handler terlebih dahulu, maka itu berfungsi seperti yang diharapkan, bahkan jika event handler tidak melakukan apa-apa.

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

Ini memuat halaman baru seolah-olah saya telah mengklik a sendiri.

Jadi pertanyaan saya ada dua: Apakah ini perilaku aneh karena saya melakukan sesuatu yang salah di suatu tempat? dan mengapa menelepon tidak click()melakukan apa-apa dengan perilaku default jika saya belum membuat handler sendiri?

EDIT:

Seperti yang ditentukan Hoffman ketika dia mencoba menduplikasi hasil saya, hasil yang saya jelaskan di atas tidak benar-benar terjadi. Saya tidak yakin apa yang menyebabkan peristiwa yang saya amati kemarin, tetapi saya yakin hari ini bukan itu yang saya jelaskan dalam pertanyaan.

Jadi jawabannya adalah Anda tidak bisa "memalsukan" klik di peramban dan yang dilakukan semua jQuery adalah memanggil pengendali acara Anda. Anda masih dapat menggunakan window.locationuntuk mengubah halaman, dan itu berfungsi dengan baik untuk saya.


Jawaban:


90

Menarik, ini mungkin "permintaan fitur" (yaitu bug) untuk jQuery. Acara klik jQuery hanya memicu tindakan klik (disebut peristiwa onClick pada DOM) pada elemen jika Anda mengikat acara jQuery ke elemen. Anda harus pergi ke milis jQuery ( http://forum.jquery.com/ ) dan melaporkan ini. Ini mungkin perilaku yang diinginkan, tapi saya rasa tidak.

EDIT:

Saya melakukan beberapa pengujian dan apa yang Anda katakan salah, bahkan jika Anda mengikat fungsi ke tag 'a' itu masih tidak membawa Anda ke situs web yang ditentukan oleh atribut href. Coba kode berikut:

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

Tidak pernah masuk ke google.com kecuali Anda mengklik langsung tautannya (dengan atau tanpa kode yang dikomentari). Perhatikan juga bahwa bahkan jika Anda mengikat acara klik ke tautan itu tetap tidak menjadi ungu setelah Anda mengklik tombol. Hanya ungu jika Anda mengklik tautan secara langsung.

Saya melakukan penelitian dan tampaknya .click tidak seharusnya bekerja dengan tag 'a' karena browser tidak mendukung "mengklik palsu" dengan javascript. Maksud saya, Anda tidak bisa "mengklik" elemen dengan javascript. Dengan tag 'a' Anda dapat memicu event onClick-nya tetapi tautannya tidak akan berubah warna (ke warna tautan yang dikunjungi, defaultnya adalah ungu di sebagian besar browser). Jadi tidak masuk akal untuk membuat $ () .klik acara bekerja dengan tag 'a' karena tindakan pergi ke atribut href bukan bagian dari acara onClick, tetapi hardcoded di browser.


7
Saya mencoba kode Anda, dan itu persis seperti yang Anda katakan, tetapi kode saya melakukan seperti yang saya jelaskan di atas. Saya akan melakukan beberapa eksperimen lagi dan melihat apakah saya dapat memberikan contoh sederhana hasil saya yang dapat Anda coba.
Mnebuerquo

1
Baik. Pasti sesuatu yang saya lakukan salah. Saya benar-benar yakin pada saat saya memposting pertanyaan saya bahwa itu berfungsi, tetapi karena saya mencoba contoh Anda milik saya tidak lagi berfungsi. Saya hanya akan kembali menggunakan window.location untuk mengubah halaman dan tidak mencoba memalsukan klik.
Mnebuerquo

Memang, klik () tidak dimaksudkan untuk membuat klik palsu tetapi kadang-kadang kita dapat menggunakannya untuk mengklik tombol atau formulir dengan suntikan javascript atau hanya untuk kenyamanan saat membuat hotkey sementara di atas fungsi javascript yang ada.
Aero Wang

241

Pilihan lain tentu saja hanya menggunakan vanilla javascript:

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

1
Ini tidak berfungsi di Safari, dan menurut spesifikasi HTML hanya input yang perlu menerapkan ini.
Jeremy Kauffman

4
Dang! Ini berhasil! Tapi saya harus mengatakan bahwa itu bukan javascript "vanilla" karena menggunakan elemen jquery, jadi javascript semacam
javery

@ BGM, ok, tapi klik () tidak pada elemen jquery. Anda bisa menggantinya dengan getElementById (".."). Click ()
Peter

wow terluka penuh, bekerja seperti yang saya harapkan. +1 diberikan :). Untuk pengguna lain, Anda juga dapat menggunakan seperti: var lnk = document.getElementById ("a_link"); if (lnk == null) {// do some ....} else {lnk.click (); }
Iqbal

Diuji di berbagai browser, IE10 & Jquery 1.6.4 tidak dapat menangani ini.
Hannes Schneidermayer

65

Jika Anda melihat kode untuk $.clickfungsi saya akan bertaruh ada pernyataan kondisional yang memeriksa untuk melihat apakah elemen memiliki pendengar terdaftar untuk clickacara tersebut sebelum mulai. Mengapa tidak mendapatkan hrefatribut dari tautan dan secara manual mengubah lokasi halaman?

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

EDIT: Inilah mengapa ia tidak mengklik, dari triggerfungsi, sumber jQuery untuk versi 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) {}
    }

Setelah itu memanggil penangan (jika ada) jQuery memicu suatu peristiwa pada objek. Namun itu hanya memanggil penangan asli untuk acara klik jika elemen tersebut bukan tautan. Saya kira ini dilakukan dengan sengaja untuk beberapa alasan. Ini harus benar meskipun apakah event handler didefinisikan atau tidak, jadi saya tidak yakin mengapa dalam kasus Anda melampirkan event handler menyebabkan onClickpenangan asli dipanggil. Anda harus melakukan apa yang saya lakukan dan melangkah melalui eksekusi untuk melihat di mana ia dipanggil.


Saya pasti bisa menggunakan window.location dan href seperti yang saya sebutkan dalam pertanyaan. Saya mencoba memahami apa yang terjadi di jquery click (), dan apa yang menyebabkan hasil yang saya amati.
Mnebuerquo

Saya mengedit jawaban saya untuk menunjukkan di mana dalam sumber jQuery yang berhubungan dengan $ .click () panggilan pada tautan.
Ryan Lynch

2
window.location berfungsi, tetapi tidak memposting HTTP Referrer, dan memecah tombol kembali.
Chase Seibert

5

Penangan klik pada tag jangkar adalah kasus khusus di jQuery.

Saya pikir Anda mungkin menjadi bingung antara peristiwa onclick jangkar (dikenal oleh browser) dan acara klik objek jQuery yang membungkus gagasan DOM tentang tag jangkar.

Anda dapat mengunduh sumber jQuery 1.3.2 di sini .

Bagian yang relevan dari sumber adalah baris 2643-2645 (Saya telah membagi ini menjadi beberapa baris untuk membuatnya lebih mudah dipahami):

// 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 tidak mendukung perilaku tautan yang "diklik" secara terprogram.

Yang dapat Anda lakukan adalah membuat formulir dan mengirimkannya. Dengan cara ini Anda tidak perlu menggunakan window.locationatau window.open, yang sering diblokir sebagai munculan yang tidak diinginkan oleh browser.

Skrip ini memiliki 2 metode berbeda: satu yang mencoba membuka 3 tab / jendela baru (hanya membuka 1 di IE dan Chrome, info lebih lanjut di bawah ini) dan satu yang menjalankan acara khusus pada klik tautan.

Begini caranya:

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

});

Apa yang dilakukannya adalah untuk setiap elemen tautan:

  1. Buat formulir
  2. Berikan atributnya
  3. Tambahkan ke DOM sehingga bisa dikirimkan
  4. Kirimkan itu
  5. Hapus formulir dari DOM, hapus semua jejak * Masukkan tawa jahat *

Sekarang Anda memiliki pemuatan tab / jendela baru "https://google.nl"(atau URL apa pun yang Anda inginkan, ganti saja). Sayangnya ketika Anda mencoba untuk membuka lebih dari satu jendela dengan cara ini, Anda mendapatkan kotak Popup blockedpesan ketika mencoba untuk membuka yang kedua (yang pertama masih dibuka).


Info lebih lanjut tentang cara saya menggunakan metode ini dapat ditemukan di sini:

Membuka jendela / tab baru tanpa menggunakan window.openatauwindow.location.href


3

Memicu elemen Hyperlink yang ada di dalam elemen yang ingin Anda kaitkan dengan jquery .klik ()

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

Dalam skrip Anda, Anda terhubung ke wadah utama Anda ingin acara klik aktif. Kemudian Anda menggunakan metodologi jquery standar untuk menemukan elemen (tipe, kelas, id) dan jalankan klik. Apa yang terjadi adalah jquery memasuki fungsi rekursif untuk menyalakan klik dan Anda merusak fungsi rekursif dengan mengambil fungsi 'e' dan stopPropagation () berfungsi dan mengembalikan false karena Anda tidak ingin jquery melakukan hal lain selain menyalakan tautan.

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

Solusi alternatif adalah dengan membungkus wadah di dalam elemen dan menempatkannya sebagai wadah di dalamnya. Atur bentang untuk menampilkan blok agar sesuai dengan standar w3c.


3

Anda bisa menggunakan jQuery untuk memilih objek jQuery untuk elemen itu. Kemudian, dapatkan elemen DOM yang mendasarinya dan panggilclick() metodenya.

oleh id

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

atau gunakan jQuery untuk mengklik banyak tautan oleh kelas CSS

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

2

Itu tidak melakukan apa-apa karena tidak ada peristiwa yang terikat pada peristiwa itu. Jika saya ingat dengan benar, jQuery menyimpan daftar event handler yang terikat dengan NodeLists untuk kinerja dan keperluan lainnya.


2

Jika Anda memerlukan fitur ini untuk satu kasing atau sangat sedikit kaset. (Anda seluruh aplikasi tidak memerlukan fitur ini) Saya lebih suka meninggalkan jQuery apa adanya (karena berbagai alasan, termasuk dapat memperbarui ke versi yang lebih baru, CDN dll.) dan memiliki solusi berikut:

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

Untuk membuka hyperlink di tab yang sama, gunakan:

$(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;
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.