Javascript 在内部元素上触发点击事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7632125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:59:02  来源:igfitidea点击:

Trigger a click event on an inner element

javascriptjqueryevent-handling

提问by Caspar Kleijne

A row in a table where each first cell contains a link needs to be clicked and open a url.

需要单击表中每个第一个单元格包含一个链接的行并打开一个 url。

<table>
  <tr>
    <td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td> 
    <td>more data</td>
  </tr>
  <tr>
    <td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td> 
    <td>more data</td>
  </tr>
  ...
</table>

The complete row should be clickable instead of only the link top open the detail page in a fancybox, ie in the page itself.

完整的行应该是可点击的,而不仅仅是链接顶部在fancybox 中打开详细信息页面,即在页面本身中。

So I triedto do something like this:

所以我尝试做这样的事情:

$("table tr").bind('click',function(e) {
    e.stopPropagation();
    $(this).find("a").trigger('click');
});

But it seems that the event is bubbling recursivly resulting in a:

但似乎该事件正在递归地冒泡,导致:

Uncaught RangeError: Maximum call stack size exceeded

未捕获的 RangeError:超出最大调用堆栈大小

How can I trigger the click on the full row instead of only the link in a proper way avoiding the stackoverflow?

如何以正确的方式触发对整行的点击,而不是仅点击链接,以避免 stackoverflow?

UPDATE: I really appreciate the answers below, but my question is about triggering the event, NOT executing the behaviour inside that event.Workarounds could be nice, but not in this case.

更新:我非常感谢下面的答案,但我的问题是关于触发事件,而不是在该事件中执行行为。解决方法可能很好,但在这种情况下不是。

回答by Lapple

This worked well:

这工作得很好:

$("table tr").click(function(e) {
    var $link = $(this).find("a");

    if (e.target === $link[0]) return false;

    $link.trigger('click');
    return false;
});

EDIT:

编辑:

Why most solutions don't work— they fail, because when the link was clicked, the immediate handler attached runs. The event then bubblesto see if a handler was attached to a table cell, row, etc.

为什么大多数解决方案不起作用——它们失败了,因为当点击链接时,附加的直接处理程序运行。然后该事件冒泡以查看处理程序是否附加到表格单元格、行等。

When you suggest triggering a click you cause the recursion: the link was clicked → fancybox → bubbles → aha! table row → trigger the link click → the link was clicked…

当您建议触发点击时,您会导致递归:链接被点击 → 花式框 → 气泡 → 啊哈!表格行 → 触发链接点击 → 链接被点击...

When you suggest to stop propagation, please note that event stops bubbling to parent elements, so a clickhandler attached to bodywill not be executed.

当您建议停止传播时,请注意事件停止冒泡到父元素,因此不会执行click附加到的处理程序body

Why the code above works— we check if the event bubbled from a link. If true, we simply return and stop furtherpropagation.

为什么上面的代码有效——我们检查事件是否从链接冒泡。如果为真,我们只需返回并停止进一步传播。



See the updated fiddle: http://jsfiddle.net/F5aMb/28/

查看更新的小提琴:http: //jsfiddle.net/F5aMb/28/

回答by Mario Binder

try

尝试

$('table tr').click(function() {
  var href = $(this).find("a").attr("href");
    if(href) {
       window.location = href;
    }
});

回答by Mario Binder

Try this:

尝试这个:

$("table tr a").bind('click', function(e) {
     e.preventDefault();
     window.open($(this).attr('href'));
     return false;
});

$("table tr").bind('click', function(e) {
     $(this).find("a").trigger('click');
 });

I found what went wrong.

In your code,

$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');//This line again triggers a click event binded on the tr ELEMENT which contains the 'a' ELEMENT. So it goes into a infinite loop.
});
$("table tr a").bind('click', function(e) {
     e.preventDefault();
     window.open($(this).attr('href'));
     return false;
});

$("table tr").bind('click', function(e) {
     $(this).find("a").trigger('click');
 });

我发现出了什么问题。

在您的代码中,

$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');//This line again triggers a click event binded on the tr ELEMENT which contains the 'a' ELEMENT. So it goes into a infinite loop.
});

Update:

更新:

This will do.

这会做。

$("table tr").bind('click', function(e) {
   window.location.href = $(this).find("a.fancybox").attr('href');
});

$(this).find("a").trigger('click');is actually not triggering the default anchor tag behavior. It just tries to trigger a click event if a click event is already bound to that element explicitly.

$(this).find("a").trigger('click');实际上不会触发默认的锚标记行为。如果点击事件已经明确绑定到该元素,它只会尝试触发点击事件。

回答by deviousdodo

It may be that I misunderstood your question, but doesn't this do what you need:

可能是我误解了您的问题,但这不是您所需要的:

$("table tr").click(function(e) {
    e.stopImmediatePropagation();
    if (! $(e.target).is('a')) {
        $(this).find("a").trigger('click');
    }
});

回答by hornetbzz

For the funny purpose of this exercise, here is a pure js solution, i.e., w/o using jQ lib).

为了这个练习的有趣目的,这里是一个纯 js 解决方案,即不使用 jQ lib)。

Available here for testing: http://jsfiddle.net/Sr5Vy/3/

可在此处进行测试:http: //jsfiddle.net/Sr5Vy/3/

<table>
  <tr id="node_1">
    <td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td>
    <td>more data</td>
  </tr>
  <tr id="node_2">
    <td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td>
    <td>more data</td>
  </tr>
</table>


function AddEvent(id, evt_type, ma_fonction, phase) {
  var oElt = document.getElementById(id);
  if( oElt.addEventListener ) {
      oElt.addEventListener(evt_type, ma_fonction, phase);
  } else if( oElt.attachEvent ) {
      oElt.attachEvent('on'+evt_type, ma_fonction);
  }

    // Debug
    // alert('a \'' + evt_type + '\' event has been attached on ' + id );

    return false;
}

function getElementsByRegExpOnId(search_reg, search_element, search_tagName) {
    search_element = (search_element === undefined) ? document : search_element;
    search_tagName= (search_tagName === undefined) ? '*' : search_tagName;
    var id_return = new Array;
    for(var i = 0, i_length = search_element.getElementsByTagName(search_tagName).length; i < i_length; i++) {
        if (search_element.getElementsByTagName(search_tagName).item(i).id &&
        search_element.getElementsByTagName(search_tagName).item(i).id.match(search_reg)) {
            id_return.push(search_element.getElementsByTagName(search_tagName).item(i).id) ;
        }
    }
    return id_return; // array
}

function FollowSpecialLinks(event) {

    // Debug
    // alert('event was successfully attached');

    // Prevent propagation
    event.preventDefault();

    // Identify targetted node (eg one of the children of <tr>)
    var targetted_elt = ShowEventSource(event);
    //alert('Event\'s target : ' + targetted_elt);

    // Extract the targetted url
    if (targetted_elt == "A") {
        var current_link = GetEventSource(event).href;

    } else {
        var current_tr = GetEventSource(event).parentNode;
        var child_links = current_tr.getElementsByTagName('a');
        var current_link = child_links[0].href;
    }



   // Now open the link
    if(current_link) {
        // Debug  
        alert('will now open href : ' + current_link);
       window.location = current_link;
    }


}

function GetEventSource(event) {
    var e = event || window.event;
    var myelt = e.target || e.srcElement;
    return myelt;
}

function ShowEventSource(event) {
    var elmt;
    var event = event || window.event;            // W3C ou MS
    var la_cible = event.target || event.srcElement;
    if (la_cible.nodeType == 3)            // Vs bug Safari
        elmt = la_cible.parentNode;                        
    else
        elmt = la_cible.tagName;
   return elmt;
}

// Get all document <tr> id's and attach the "click" events to them
  my_rows = new Array();
  my_rows = getElementsByRegExpOnId(/^node_.+/, document , 'tr') ;
    if (my_rows) {
        for (i=0; i< my_rows.length; i++ ) {
            var every_row = document.getElementById( my_rows[i] ) ;
            AddEvent(every_row.id, 'click', FollowSpecialLinks, false);
        }
    }

回答by jSource

In order to compensate for the bubbling, you need to detect the target of the event and not click on the link more than once. Also, jQuery's "trigger" function won't work for plain links, so you need a specialized click function.

为了补偿冒泡,您需要检测事件的目标并且不要多次单击链接。此外,jQuery 的“触发器”功能不适用于普通链接,因此您需要一个专门的点击功能。

you can try it out at: http://jsfiddle.net/F5aMb/27/

你可以试试:http: //jsfiddle.net/F5aMb/27/

$("table tr").each(function(i, tr){
    $(tr).bind('click',function(e) {
        var target = $(e.target);
        if( !target.is("a") ) {
            clickLink($(this).find("a")[0]);
        }
    })
});


function clickLink(element) {
   if (document.createEvent) {
       // dispatch for firefox + others
       var evt = document.createEvent("MouseEvents");
       evt.initEvent("click", true, true ); // event type,bubbling,cancelable
       return !element.dispatchEvent(evt);
   } else {
       //IE
       element.click()
   }
}

回答by Merianos Nikos

Try

尝试

$(".fancybox").parent('td').parent('tr').bind('click',function(e) {
    e.stopPropagation();
    $(this).find("a").trigger('click');
});

回答by Nicola Peluchetti

Have you tried stopping immediate propagation when you click the link?This way you should stop the recursion

您是否尝试在单击链接时停止立即传播?这样您就应该停止递归

$('a').click(function(e){
    e.stopImmediatePropagation();
    alert('hi');
});

fiddle here: http://jsfiddle.net/3VMGn/2/

在这里小提琴:http: //jsfiddle.net/3VMGn/2/

回答by Amit

I think .click()or .trigger("click")only fires the event handlers for onclick.

我认为.click().trigger("click")只触发onclick.

See a sample here http://jsfiddle.net/sethi/bEDPp/4/. Manually clicking on the link shows 2 alerts while firing the event through jQuery shows only 1 alert.

在此处查看示例http://jsfiddle.net/sethi/bEDPp/4/。手动单击链接会显示 2 个警报,而通过 jQuery 触发事件仅显示 1 个警报。

You can also refer to this link : re-firing a click event on a link with jQuery

你也可以参考这个链接:re-firing a click event on a link with jQuery

Solution

解决方案

If you are just looking to open a fancyboxtry this:

如果你只是想打开一个花哨的盒子试试这个:

$("table tr").bind('click',function(e) {
        var elem = $(e.target);
        if(elem.is('a')){
            return;    
        }
        e.stopImmediatePropagation();
        var parent= elem.is('tr') ? elem:elem.parents("tr").eq(0);
        parent.find("a").trigger('click.fb');
    });

where click.fbis the event that fancybox binds with the anchor element.

哪里click.fb是fancybox与锚元素绑定的事件。

回答by rtdp

You can do what you want with following code. I tested it on you jsfilddle seems working.

您可以使用以下代码执行您想要的操作。我在你身上测试过 jsfilddle 似乎有效。

$("table tr").click(function(e) {

   // check if click event is on link or not.
   // if it's link, don't stop further propagation
   // so, link href will be followed.

  if($(e.target).attr('class')=='fancybox'){
    alert('you clicked link, so what next ?.');

  // else if click is happened somewhere else than link, 
  // stop the propagation, so that it won't go in recursion.

  }else{
    alert('no link clicked, :( ');
    alert('now clicking link prgrammatically');
    $(this).find('a').click(); 
    e.preventDefault();
  }
});

Let me know, if you want to achieve something else than this.

如果您想实现其他目标,请告诉我。