触发内部元素上的单击事件

时间:2011-10-03 07:25:41

标签: javascript jquery event-handling

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

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

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

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

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

但似乎事件正在冒泡,导致:

  

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

如何以正确的方式触发完整行而不是链接的点击,以避免堆栈溢出?

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

14 个答案:

答案 0 :(得分:18)

这很有效:

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

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

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

修改

为什么大多数解决方案无法正常工作 - 它们会失败,因为单击链接后,附加的直接处理程序会运行。然后事件起泡以查看处理程序是否附加到表格单元格,行等。

当你建议触发点击时会导致递归:点击了链接→fancybox→bubbles→aha!表格行→触发链接点击→点击链接...

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

为什么上面的代码可行 - 我们会检查事件是否来自链接。如果为true,我们只需返回并停止进一步传播。


请参阅更新的小提琴:http://jsfiddle.net/F5aMb/28/

答案 1 :(得分:9)

尝试

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

答案 2 :(得分:4)

试试这个:

$("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.
});

更新

This will do.

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

$(this).find("a").trigger('click');实际上并未触发默认值     锚标记行为。它只是尝试在单击事件时触发单击事件     已明确绑定到该元素。

答案 3 :(得分:3)

可能是我误解了你的问题,但这不符合你的需要:

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

答案 4 :(得分:3)

对于本练习的有趣目的,这里是一个纯粹的js解决方案,即没有使用jQ lib。

此处可用于测试: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);
        }
    }

答案 5 :(得分:2)

尝试

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

答案 6 :(得分:2)

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

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

在这里摆弄:http://jsfiddle.net/3VMGn/2/

答案 7 :(得分:2)

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

您可以尝试: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()
   }
}

答案 8 :(得分:1)

我能够通过为每个链接提供一个唯一ID然后使用jQuery设置该唯一ID的click事件来将窗口重定向到适当的页面来实现。

以下是我的工作示例:http://jsfiddle.net/MarkKramer/F5aMb/2/

以下是代码:

$('#link1').click(function(){
    // do whatever I want here, then redirect
    window.location.href = "detail.aspx?CID=67525";
});
$('#link2').click(function(){
    // do whatever I want here, then redirect
    window.location.href = "detail.aspx?CID=17522";
});

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

答案 9 :(得分:1)

您可以使用以下代码执行所需操作。我测试了你jsfiddle似乎工作。

$("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();
  }
});

让我知道,如果你想要实现别的目的。

答案 10 :(得分:1)

我认为.click().trigger("click")只会触发onclick的事件处理程序。

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

您也可以参考以下链接:re-firing a click event on a link with jQuery

<强>解决方案

如果您只想打开fancybox,请尝试:

$("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');
    });

其中click.fb是fancybox与锚元素绑定的事件。

答案 11 :(得分:0)

$('a.fancybox').click(function(evt){evt.stopPropagation())});

$('table tr:has[.fancybox]').click(function(evt){
$(this).find('.fancybox').trigger('click')
})

答案 12 :(得分:0)

我想我有你想要的东西。您需要做的是在处理程序中的锚标记上调用click(),并确保忽略锚本身的事件。此外,WebKit不支持click(),因此您必须自己实现它。

请注意下面的小提琴,它正确地跟随链接目标,即打开一个新窗口,或加载到同一个窗口。 http://jsfiddle.net/mendesjuan/5pv5A/3/

// Some browsers (WebKit) don't support the click method on links
if (!HTMLAnchorElement.prototype.click) {
    HTMLAnchorElement.prototype.click = function() {
      var target = this.getAttribute('target');
      var href = this.getAttribute('href');
      if (!target) {
          window.location = href;
      } else {
          window.open(href, target);
      }          
    }
}

$("table tr").bind('click',function(e) {
    // This prevents the stack overflow
    if (e.target.tagName == 'A') {
        return;
    }
    // This triggers the default behavior of the anchor
    // unlike calling jQuery trigger('click')
    $(this).find("a").get(0).click();
});

答案 13 :(得分:0)

我的用例是在单击-element时触发单击。检查目标元素的类型可以解决递归调用问题。

$('#table tbody td').click(function(e){
    if ($(e.target).is('td')) {
        $(this).find('input').trigger('click');
    }
});