Tengo una tabla HTML con un enlace en la primera columna. Quiero permitir que el usuario haga clic en cualquier lugar de la fila para activar ese enlace. Al mismo tiempo, me gustaría preservar la funcionalidad de clic central y Ctrl + clic de abrir una nueva pestaña / ventana. Aquí hay un ejemplo de la tabla:

<table id="row_link"> 
  <tbody> 
    <tr>
      <td><a href="link1.html">link</a></td> 
      <td>info 1</td> 
    </tr>       
    <tr>
      <td><a href="link2.html">link</a></td> 
      <td>info 2</td> 
    </tr>       
  </tbody> 
</table> 

Usando jQuery puedo permitir que el usuario haga clic izquierdo en cualquier lugar de una fila:

$("table#row_link tbody tr").click(function () {
    window.location = $(this).find("a:first").attr("href");
});

Esto, por supuesto, deshabilita la funcionalidad estándar de clic central y Ctrl + clic de abrir una nueva pestaña. ¿Hay una mejor manera de permitir a los usuarios hacer clic en toda la fila mientras se conserva el comportamiento estándar de clic central y ctrl + clcik?

34
Brian Fisher 21 may. 2009 a las 03:32

10 respuestas

La mejor respuesta

Desafortunadamente, no hay forma de simular un enlace y todo el comportamiento asociado en cada navegador. Por lo tanto, la única forma de lograr lo que desea es tener un enlace que siga el cursor alrededor del elemento <tr>; este enlace sería invisible, por lo que, para el usuario, parece que están haciendo clic en <tr> pero en realidad están haciendo clic en un enlace oculto. Con este método, el botón central, ctrl + clic y cualquier otro comportamiento quedan intactos.

Aquí hay una DEMO: http://jsbin.com/ufugo

Y aquí está el código:

$("table tr").each(function(){

    var $link = $('a:first', this).clone(true),
        dim = {
            x: [
                $(this).offset().left,
                $(this).offset().left + $(this).outerWidth()
            ],
            y: [
                $(this).offset().top,
                $(this).offset().top + $(this).outerHeight()
            ]
        }

    $link
        .click(function(){
            $(this).blur();
        })
        .css({
            position: 'absolute',
            display: 'none',
            // Opacity:0  means it's invisible
            opacity: 0
        })
        .appendTo('body');

    $(this).mouseover(function(){
        $link.show();
    });

    $(document).mousemove(function(e){
        var y = e.pageY,
            x = e.pageX;
        // Check to see if cursor is outside of <tr>
        // If it is then hide the cloned link (display:none;)
        if (x < dim.x[0] || x > dim.x[1] || y < dim.y[0] || y > dim.y[1]) {  
            return $link.hide();
        }
        $link.css({
            top: e.pageY - 5,
            left: e.pageX - 5
        })
    });

});

Editar:

Creé un complemento jQuery usando un enfoque ligeramente mejor que el anterior: http://james.padolsey.com/javascript/table-rows-as-clickable-anchors/

35
James 25 may. 2009 a las 18:26

EDITAR

Este es un problema simple que tiene una solución simple. No veo la necesidad de hacks desagradables que puedan romperse en algunos navegadores o tomar tiempo de procesamiento. Especialmente porque hay una solución CSS ordenada y fácil.

Primero, aquí hay una demo

Inspirado por @Nick solution para un problema muy similar, propongo una Solución simple CSS + JQuery.

Primero, aquí está el mini plugin que escribí. El complemento envolverá cada celda con un enlace:

jQuery.fn.linker = function(selector) {
    $(this).each(function() {
        var href = $(selector, this).attr('href');
        if (href) {
            var link = $('<a href="' + $(selector, this).attr('href') + '"></a>').css({
                'text-decoration': 'none',
                'display': 'block',
                'padding': '0px',
                'color': $(this).css('color')
            })
            $(this).children()
                   .css('padding', '0')
                   .wrapInner(link);
        }
    });
};

Y aquí hay un ejemplo de uso:

$('table.collection tr').linker('a:first');

Y toda la CSS que necesitas:

table.collection {
    border-collapse:collapse;
}

Es tan simple como eso.


Puede usar el objeto de evento para verificar el tipo de clic del mouse. Este artículo está discutiendo un tema similar.

De todos modos, aquí está cómo hacerlo:

$("table#row_link tbody tr").click(function () {

    if((!$.browser.msie && e.button == 0) || ($.browser.msie && e.button == 1)){
        if (!e.ctrlKey) {
            // Left mouse button was clicked without ctrl
            window.location = $(this).find("a:first").attr("href");
        }
    }
});
12
Community 23 may. 2017 a las 12:26

Puedes tomar el evento y ver su código de evento. Pero no hay una forma real de saber cuál es el comportamiento de un navegador para esos eventos.

1
psayre23 21 may. 2009 a las 00:36

Puede hacer un enlace y dejarlo flotando en su tr, enlazar con el mouse sobre el evento, actualizar href y posición

Crear un enlace de píxel

<table id="row_link">....</table>
<a id="onepixel" style="position:absolute;z-index:1000;width:1px;height:1px;"></a>

Actualizar href y colocar el mouse sobre

$("#row_link tr").mouseover(
   function(event){
      //update href
      $("#onepixel").attr("href",$(this).find("a:first").attr("href"));
      //update position, just move to current mouse position
      $("#onepixel").css("top",event.pageY).css("left",event.pageX);
   }
);
1
AnhTu 25 may. 2009 a las 10:27

Tu quieres esto:

$('table#row_link tbody tr').mousedown( function(e){
    if(e.ctrlKey || (!$.browser.msie && e.button == 1) || ($.browser.msie && e.button == 4)){
        //middle mouse button or ctrl+click
    } else {
        //normal left click
    }
});

Esto se prueba en FF3.0.10, Chrome 1.0 e IE6. Uso el evento mousedown porque ni firefox ni IE pasan el clic del botón central del mouse a un evento .click (fn).

6
Pim Jager 25 may. 2009 a las 07:40

Aquí hay algo que debería funcionar: en lugar de usar window.location, us .click () para emular un clic en el primero dentro del elemento. Además, use un condicional para verificar CTRL + Click.

Debería verse así:

$("table#row_link tbody tr").click(function (e) {
    if(e.ctrlKey) { 
        // Run Ctl+Click Code Here
    } else { 
        $(this).children('a').eq(0).click(); 
    }
}

¡Espero que esto ayude!

Dave Romero

1
Mwiza 29 oct. 2017 a las 21:31

Creo que el un complemento más grande hará lo que usted pida. Aquí esta la

-1
Eystein 24 may. 2009 a las 10:05

Intente colocar la a alrededor del td y luego aplique una pantalla: bloquee el elemento CSS al td.

Eso debería hacer que se pueda hacer clic en toda el área del td con todos los botones como un enlace "normal".

Un ejemplo es probablemente mejor:

<table id="row_link"> 
  <tbody> 
    <tr>
      <a href="link1.html"><td style="display: block;">link</td></a> 
      <td>info 1</td> 
    </tr>       
    <tr>
      <a href="link2.html"><td style="display: block;">link</td></a>
      <td>info 2</td> 
    </tr>       
  </tbody> 
</table>

Un enfoque similar me funcionó en el pasado, aunque no fue exactamente para los elementos de la tabla. No probado con mesas, así que pruébalo.

-1
mr-euro 23 may. 2009 a las 22:23

Atacaría esto desde el lado HTML / css. Esto solía ser un problema común cuando la mayoría de los sitios realizaban todo el diseño en tablas.

Primero convierta el contenido de todas las celdas de la tabla en enlaces. Si no desea que se vean como enlaces, puede usar CSS para eliminar el subrayado de las celdas 'sin enlace'. Pero serán enlaces, que es semánticamente lo que quieres de todos modos.

A continuación, desea que el enlace se expanda para llenar toda la celda. StackOverflow ya conoce la respuesta a esto:

td a { display: block; width: 100%; height: 100%; line-height: 100%; }

Con una tabla típica sin espacios entre las celdas, se podrá hacer clic en toda la fila. Y dado que esto no se basa en trucos o hacks específicos del navegador, debería funcionar en todas partes.

8
Community 23 may. 2017 a las 10:29