开发者

Trigger a click event on an inner element

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

<table>
  <tr>
    开发者_Python百科<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.

So I tried to 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

How can I trigger the click on the full row instead of only the link in a proper way avoiding the 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.


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 bubbles to 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 click handler attached to body will not be executed.

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


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


try

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


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

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.


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


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

Available here for testing: 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);
        }
    }


Try

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


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/


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.

you can try it out at: 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()
   }
}


I was able to do it by giving each link a unique ID and then using jQuery to set the click event of that unique ID to redirect the window to the appropriate page.

Here is my working example: http://jsfiddle.net/MarkKramer/F5aMb/2/

And here is the code:

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


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

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


I think .click() or .trigger("click") only fires the event handlers for 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.

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

Solution

If you are just looking to open a fancybox try 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.fb is the event that fancybox binds with the anchor element.


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

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


I think I have what you're looking for. What you need to do is to call click() on the anchor tag in the handler, and make sure you ignore events from the anchor itself. Also, WebKit doesn't support click(), so you have to implement it yourself.

Notice from the fiddle below that it properly follows the link target, that is, opens a new window, or loads into the same window. 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();
});


My usecase was to trigger a click when a -element was clicked. Checking the type of the target element solves the recursive call problem.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜