1

I've the following table with a link in the last cell. The table is populated with data via ajax, depending on the users input.

<table class="table-list">
<tbody>
<tr>
 <td>...</td>
 <td><a href="/link">Link</a></td>
</tr>
</tbody>
</table>

Because I like to have the whole row clickable, I use the following script to catch the onClick event. But the link is also in the table row and the onClick-Event gets fired infinity times until the script aborts with an "stackoverflow" error.

<script>
$(function() {
 $('.table-list tr').live('click', function() {
  $('a:last', this).click();
 });
});
</script>

I tried to disable the event temporarily like below but it's not working.

<script>
$(function() {
 $('.table-list tr').live('click', function() {
  $(this).off('click');
  $('a:last', this).click();
  $(this).on('click');
 });
});
</script>

I also tried some variations like addind and removing a class isClicked to the row etc. but nothing worked.

Any suggestions on this?

3 Answers 3

3

It is important to prevent event propagation, e.g. bubbling.

I posted some example code here: http://pastebin.com/d25QeVkK

This is the JS/jQuery part:

(function($){
    $(document).delegate('table tr', 'click', function(e){
        $('a', this).trigger('click');
    });
    $(document).delegate('tr a', 'click', function(e){
        console.log("it works!");
        // use either of these to prevent stackoverflow
        //e.stopPropagation(); // use this if you want normal click behaviour without bubbling
        return false; // use this if you don't want normal click behaviour and no propagation
    });                            
})(jQuery);

So this wasn't the smartest solution, because it actually won't work because of the way delegate works. The click has to bubble to the body element for it to work if you use delegate - and stopPropagate prevents that. This should do the trick:

$('body').delegate('.table-list tr', 'click', function(e){
        $('a', this).trigger('click');
});
$('body').delegate('.table-list tr a', 'click', function(e){
        e.stopPropagation();
        window.location.href = $(this).attr('href');   
});

e.stopPropagation(); has to stay in the click handler, because else you would still get a frozen UI and recursion warning after a while, before getting redirected to the target url.

http://pastebin.com/PrH96GX8

So this is even shorter and should work too:

$('body').delegate('.table-list tr', 'click', function(e){
    window.location.href = $(this).find('a').attr('href');  
});

Use this to open in new tab:

$('body').delegate('.table-list tr', 'click', function(e){
    window.open($(this).find('a').attr('href'),'_newtab');
    return false;
});

Please keep in mind to use the right selectors, this is really generic code.

Sign up to request clarification or add additional context in comments.

Comments

0

Try this one:

$(function() {  
  $('.table-list').on('click', 'tr', function(){
    $(this).find('a:last').trigger('click'); 
  });

  $('.table-list').on('click','a',function(e){ 
   e.stopImmediatePropagation(); 
  }); 
});

3 Comments

That triggers just the same error Uncaught RangeError: Maximum call stack size exceeded.
I've just edited my answer.. you can try this one.. let me know if this is ok now
That just fires nothing. I came up with a hidden form as solution. Working but not very elegant. $('.table-list tr').live('click', function() { $('#go').attr('action', $('a:last', this).attr('href')).submit(); });
0

Instead of trying to click the link, try this:

<table class="table-list">
<tbody>
<tr style='border: 1px solid black;'>
 <td>.1.</td><td>.2.</td><td>.3.</td><td>.4.</td><td>.5.</td>
 <td class='link'><a href="/link" target="_blank">Link</a></td>
</tr>
<tr style='border: 1px solid black;'>
 <td>.1.</td><td>.2.</td><td>.3.</td><td>.4.</td><td>.5.</td>
 <td class='link'><a href="/link">Link2</a></td>
</tr>
</tbody>
</table>​

Script:

  $('.table-list td').each(function(){
        if ($(this).find('a').length === 0){
            $(this).on('click', function(){
                var link = $(this).siblings('.link').find('a');
                if (link.attr('target') === '_blank'){
                    window.open(link.attr('href'));
                }
                else {
                    window.location = link.attr('href')            
                }
            });
        }
    }); 

It's ugly, and could be shortened, but it's better than the form submit IMHO.
If you want to make the other tds clickable consider just wrapping the entire row with the link.

1 Comment

Thank you for your suggestion - but I'll stay with the form. Wrapping a row or a table into a link can lead to serious problems with Internet Explorer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.