¿Cómo puedo obtener el encabezado de tabla correspondiente (th) de una celda de tabla (td)?

86

Dada la siguiente tabla, ¿cómo obtendría el encabezado de la tabla correspondiente para cada elemento td?

<table>
    <thead> 
        <tr>
            <th id="name">Name</th>
            <th id="address">Address</th>
        </tr>
    </thead> 
    <tbody>
        <tr>
            <td>Bob</td>
            <td>1 High Street</td>
        </tr>
    </tbody>
</table>

Dado que actualmente tengo alguno de los tdelementos disponibles, ¿cómo puedo encontrar el thelemento correspondiente ?

var $td = IveGotThisCovered();
var $th = GetTableHeader($td);
djdd87
fuente
2
Ninguna de las respuestas tiene en cuenta la posibilidad de que el th pueda tener un colspan mayor que 1, que es mi caso de uso :(
Dexygen
1
@GeorgeJempty Mi respuesta maneja colspans.
doug65536

Respuestas:

137
var $th = $td.closest('tbody').prev('thead').find('> tr > th:eq(' + $td.index() + ')');

O un poco simplificado

var $th = $td.closest('table').find('th').eq($td.index());
usuario113716
fuente
2
si está poniendo más tablas en sus tablas, use en .parent('table')lugar de.closest('table')
Dead.Rabit
14
¿qué pasa con colspans?
bradvido
@bradvido - Mi respuesta tiene eso en cuenta
vsync
10
var $th = $("table thead tr th").eq($td.index())

Sería mejor usar una identificación para hacer referencia a la tabla si hay más de una.

Adán
fuente
Es posible que haya más de una tabla en la página, lo que hace que esta solución no sea confiable
vsync
5

Solución que maneja colspan

Tengo una solución basada en hacer coincidir el borde tdizquierdo del borde izquierdo del correspondiente th. Debe manejar colspans arbitrariamente complejos.

Modifiqué el caso de prueba para mostrar que arbitrario colspanse maneja correctamente.

Demo en vivo

JS

$(function($) {
  "use strict";

  // Only part of the demo, the thFromTd call does the work
  $(document).on('mouseover mouseout', 'td', function(event) {
    var td = $(event.target).closest('td'),
        th = thFromTd(td);
    th.parent().find('.highlight').removeClass('highlight');
    if (event.type === 'mouseover')
      th.addClass('highlight');
  });

  // Returns jquery object
  function thFromTd(td) {
    var ofs = td.offset().left,
        table = td.closest('table'),
        thead = table.children('thead').eq(0),
        positions = cacheThPositions(thead),
        matches = positions.filter(function(eldata) {
          return eldata.left <= ofs;
        }),
        match = matches[matches.length-1],
        matchEl = $(match.el);
    return matchEl;
  }

  // Caches the positions of the headers,
  // so we don't do a lot of expensive `.offset()` calls.
  function cacheThPositions(thead) {
    var data = thead.data('cached-pos'),
        allth;
    if (data)
      return data;
    allth = thead.children('tr').children('th');
    data = allth.map(function() {
      var th = $(this);
      return {
        el: this,
        left: th.offset().left
      };
    }).toArray();
    thead.data('cached-pos', data);
    return data;
  }
});

CSS

.highlight {
  background-color: #EEE;
}

HTML

<table>
    <thead> 
        <tr>
            <th colspan="3">Not header!</th>
            <th id="name" colspan="3">Name</th>
            <th id="address">Address</th>
            <th id="address">Other</th>
        </tr>
    </thead> 
    <tbody>
        <tr>
            <td colspan="2">X</td>
            <td>1</td>
            <td>Bob</td>
            <td>J</td>
            <td>Public</td>
            <td>1 High Street</td>
            <td colspan="2">Postfix</td>
        </tr>
    </tbody>
</table>
doug65536
fuente
Expandí el caso de prueba para usar simultáneamente combinaciones arbitrarias de colspanen los encabezados y las filas, y aún funcionó. Me encantaría saber sobre cualquier caso que pueda encontrar que no funcione con esto.
doug65536
4

Puedes hacerlo usando el índice de td:

var tdIndex = $td.index() + 1;
var $th = $('#table tr').find('th:nth-child(' + tdIndex + ')');
rebelde
fuente
1
Recuerde que .index()está basado en cero y nth-childestá basado en uno. Entonces, el resultado estaría desviado en uno. : o)
user113716
3

Solución de JavaScript puro:

var index = Array.prototype.indexOf.call(your_td.parentNode.children, your_td)
var corresponding_th = document.querySelector('#your_table_id th:nth-child(' + (index+1) + ')')
Jeromej
fuente
1

Busque coincidencias thpara a td, teniendo en cuenta los colspanproblemas de índice.

$('table').on('click', 'td', get_TH_by_TD)

function get_TH_by_TD(e){
   var idx = $(this).index(),
       th, th_colSpan = 0;

   for( var i=0; i < this.offsetParent.tHead.rows[0].cells.length; i++ ){
      th = this.offsetParent.tHead.rows[0].cells[i];
      th_colSpan += th.colSpan;
      if( th_colSpan >= (idx + this.colSpan) )
        break;
   }
   
   console.clear();
   console.log( th );
   return th;
}
table{ width:100%; }
th, td{ border:1px solid silver; padding:5px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>Click a TD:</p>
<table>
    <thead> 
        <tr>
            <th colspan="2"></th>
            <th>Name</th>
            <th colspan="2">Address</th>
            <th colspan="2">Other</th>
        </tr>
    </thead> 
    <tbody>
        <tr>
            <td>X</td>
            <td>1</td>
            <td>Jon Snow</td>
            <td>12</td>
            <td>High Street</td>
            <td>Postfix</td>
            <td>Public</td>
        </tr>
    </tbody>
</table>

vsync
fuente
0

Eso es simple, si hace referencia a ellos por índice. Si desea ocultar la primera columna, debería:

Copiar codigo

$('#thetable tr').find('td:nth-child(1),th:nth-child(1)').toggle();

La razón por la que primero seleccioné todas las filas de la tabla y luego las td y las th que eran el enésimo hijo es para que no tuviéramos que seleccionar la tabla y todas las filas de la tabla dos veces. Esto mejora la velocidad de ejecución del script. Tenga en cuenta que nth-child()se 1basa, no 0.

مهدی عابدی برنامه نویس و مشاور
fuente