bindまたはclickでイベントハンドラーをバインドしていない場合、jquery click()を呼び出して<a>リンクをたどることはできますか?


175

私のJavaScriptにはタイマーがあり、時間が経過すると別のページに移動するためにリンクをクリックすることをエミュレートする必要があります。これを行うには、jQueryのclick()関数を使用しています。私も使用して$().trigger()おりwindow.location、3つすべてで意図したとおりに機能させることができます。

私はいくつかの奇妙な振る舞いを観察しました、click()そして私は何が起こり、なぜ起こるのかを理解しようとしています。

私はこの質問で説明するすべてにFirefoxを使用していますが、他のブラウザがこれで何をするかにも興味があります。

イベントハンドラーを使用していない、$('a').bind('click',fn)または$('a').click(fn)設定していない場合、呼び出し$('a').click()を行っても何も起こらないようです。ブラウザーは新しいページをロードしないため、このイベントのブラウザーのデフォルトハンドラーは呼び出されません。

ただし、最初にイベントハンドラーを設定すると、イベントハンドラーが何もしなくても、期待どおりに機能します。

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

これにより、自分をクリックしたかのように新しいページが読み込まれます。

だから私の質問は2つあります:私がどこかで何か間違ったことをしているのでこれは奇妙な行動ですか?click()独自のハンドラを作成していない場合、なぜ呼び出しはデフォルトの動作では何もしないのですか?

編集:

ホフマンが私の結果を複製しようとしたときに決定したように、私が上で説明した結果は実際には起こりません。昨日観察したイベントの原因はわかりませんが、質問で説明したものではなかったのは今日です。

答えは、ブラウザで「偽の」クリックを行うことはできず、すべてのjQueryがイベントハンドラを呼び出すことです。あなたはまだwindow.locationページを変更するために使用することができ、それは私にとってはうまくいきます。


2
解決策かもしれません: stackoverflow.com/questions/31687759/...
Sukrit Chhabra

回答:


90

興味深いことに、これはおそらくjQueryの「機能リクエスト」(つまりバグ)です。jQueryイベントを要素にバインドした場合、jQueryクリックイベントは要素のクリックアクション(DOMではonClickイベントと呼ばれる)のみをトリガーします。jQueryメーリングリスト(http://forum.jquery.com/)にアクセスして報告してください。これは望ましい動作かもしれませんが、私はそうは思いません。

編集:

私はいくつかのテストを行いましたが、あなたが言ったことは間違っています。たとえ「a」タグに関数をバインドしても、href属性で指定されたWebサイトにはまだアクセスできません。次のコードを試してください:

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

(コメント付きコードの有無にかかわらず)リンクを直接クリックしない限り、google.comにアクセスすることはありません。また、クリックイベントをリンクにバインドした場合でも、ボタンをクリックすると紫色にならないことに注意してください。リンクを直接クリックした場合にのみ、紫色になります。

私はいくつかの調査を行いましたが、ブラウザがJavaScriptで「偽のクリック」をサポートしていないため、.clickは「a」タグで動作するとは思われません。つまり、JavaScriptで要素を「クリック」することはできません。「a」タグを使用すると、onClickイベントをトリガーできますが、リンクの色は変わりません(訪問したリンクの色に対して、ほとんどのブラウザではデフォルトは紫です)。したがって、href属性に移動する動作はonClickイベントの一部ではなく、ブラウザーでハードコード化されているため、$()。clickイベントを 'a'タグで機能させることは意味がありません。


7
私はあなたのコードを試してみましたが、あなたが言ったのとまったく同じですが、私のコードは上で説明したとおりです。さらにいくつかの実験を行い、あなたが試すことができる私の結果の簡単な例をまとめられるかどうかを確認します。
Mnebuerquo 2009年

1
OK。間違いだったに違いない。私が質問を投稿したとき、それが機能していることは間違いありませんでしたが、あなたの例を試したので、私の鉱山はもう機能しません。window.locationを使用してページを変更することに戻り、クリックを偽造しないでください。
Mnebuerquo 2009年

実際、click()は偽のクリックを作成するためのものではありませんが、JavaScriptインジェクションを使用してボタンやフォームをクリックするために、または既存のJavaScript関数の上に一時的なホットキーを作成する際の便宜のために使用できる場合があります。
Aero Wang

241

もちろん、もう1つのオプションは、バニラJavaScriptを使用することです。

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

1
これはSafariでは機能せず、HTML仕様によると、入力のみがこれを実装する必要があります。
ジェレミーカウフマン2013

4
ダン!これは機能します!それは、ソート・オブ・バニラjqueryのジャバスクリプトですので、しかし、私は、それはjqueryの要素を使用していますので、それは非常に「バニラ」javascriptのではないことを言わなければならない....それは、Firefox 24とIE 10で動作します
bgmCoder

@BGM、わかりましたが、click()はjquery要素にありません。getElementById( "..")。click()で置き換えることができます
Peter

すごい負傷者がいっぱい、期待通りに動作します +1が与えられました:) 他のユーザーについては、次のように使用することもできます。var lnk = document.getElementById( "a_link"); if(lnk == null){//いくつかを実行...... else {lnk.click(); }
2014年

さまざまなブラウザでテスト済みで、IE10とJquery 1.6.4はこれを処理できません。
Hannes Schneidermayer

65

$.click関数のコードを見ると、要素にclickイベントのリスナーが登録されているかどうかを確認してから次に進むかどうかを確認する条件ステートメントがあるはずです。hrefリンクから属性を取得して手動でページの場所を変更しないのはなぜですか?

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

編集:triggerバージョン1.3.2のjQueryソースから、関数からクリックスルーしない理由は次のとおりです:

 // 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) {}
    }

ハンドラー(存在する場合)を呼び出した後、jQueryはオブジェクトのイベントをトリガーします。ただし、要素がリンクでない場合、クリックイベントのネイティブハンドラーのみを呼び出します。これは何らかの理由で意図的に行われたと思います。イベントハンドラーが定義されているかどうかにかかわらず、これは当てはまるはずです。そのため、イベントハンドラーをアタッチすると、ネイティブonClickハンドラーが呼び出された理由がわかりません。あなたは私がしたことを実行し、それが呼び出されている場所を確認するために実行をステップスルーする必要があります。


質問で述べたように、window.locationとhrefは確かに使用できます。私はjquery click()で何が起こるか、そして私が観察した結果の原因を理解しようとしています。
Mnebuerquo 2009年

回答を編集して、jQueryソースのどこでリンクの$ .click()呼び出しを処理するかを示しました。
ライアンリンチ

2
window.locationは機能しますが、HTTPリファラーをポストしません。また、戻るボタンを壊します。
Chase Seibert、2010

5

アンカータグのクリックハンドラーはjQueryの特殊なケースです。

アンカーのonclickイベント(ブラウザーに知られている)と、DOMのアンカータグの概念をラップするjQueryオブジェクトのclickイベントが混同されていると思います。

ここからjQuery 1.3.2ソースをダウンロードできます。

ソースの関連セクションは、2643-2645行目です(これを複数の行に分割して、理解しやすくしました)。

// 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は、プログラムで「クリックされた」リンクのデフォルトの動作をサポートしていません。

できることは、フォームを作成して送信することです。この方法では、window.locationまたはを使用する必要window.openはありません。これらは、ブラウザによって不要なポップアップとしてブロックされることがよくあります。

このスクリプトには2つの異なる方法があります。1つは3つの新しいタブ/ウィンドウを開こうとする方法(IEとChromeでは1つだけ開く、詳細は以下)、もう1つはリンクのクリック時にカスタムイベントを発生させる方法です。

方法は次のとおりです。

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

});

これは、各リンク要素に対して行われます。

  1. フォームを作成する
  2. 属性を与える
  3. DOMに追加して送信できるようにする
  4. 提出する
  5. フォームをDOMから削除し、すべての痕跡を削除します*邪悪な笑いを挿入します*

これで、新しいタブ/ウィンドウがロードされました"https://google.nl"(または必要なURLがあれば、それを置き換えてください)。残念ながら、この方法で複数のウィンドウPopup blockedを開こうとすると、2番目のウィンドウを開こうとするとメッセージバーが表示されます(最初のウィンドウはまだ開いています)。


私がこの方法にたどり着いた方法についての詳細はここにあります:

window.openまたはを使用せずに新しいウィンドウ/タブを開くwindow.location.href


3

jquery .click()をフックする要素内にあるハイパーリンク要素をトリガーします。

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

スクリプトでは、クリックイベントを発生させたいメインコンテナーに接続します。次に、標準のjquery手法を使用して要素(type、class、id)を見つけ、クリックを発生させます。何が起こるかは、jqueryが再帰関数に入り、クリックを起動し、イベント 'e'およびstopPropagation()関数を取得して再帰関数を中断し、jqueryが他に何も実行しないようにしてリンクを起動するためにfalseを返すことです。

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

別の解決策は、コンテナを要素でラップし、をの代わりにのコンテナとして配置することです。w3c標準に準拠するようにスパンを表示ブロックに設定します。


3

jQueryを使用して、その要素のjQueryオブジェクトを選択できます。次に、基になるDOM要素を取得し、そのclick()メソッドを呼び出します。

ID別

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

またはjQueryを使用して、CSSクラスでリンクの束をクリックします

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

2

イベントにバインドされているイベントがないため、何も実行されません。私が正しく思い出せば、jQueryはパフォーマンスやその他の目的でNodeListsにバインドされたイベントハンドラーの独自のリストを維持します。


2

1つのケースまたはごく少数のケースでこの機能が必要な場合。(アプリ全体でこの機能は必要ありません)私はjQueryをそのままにしておき(多くの理由で、新しいバージョンやCDNに更新できるなど)、次の回避策を講じます。

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

同じタブでハイパーリンクを開くには、次を使用します。

$(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;
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.