Jak mogę uzyskać odpowiedni nagłówek tabeli (th) z komórki tabeli (td)?

86

Biorąc pod uwagę poniższą tabelę, jak uzyskać odpowiedni nagłówek tabeli dla każdego elementu 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>

Biorąc pod uwagę, że obecnie mam już dostępny któryś z tdelementów, jak mogę znaleźć odpowiedni thelement?

var $td = IveGotThisCovered();
var $th = GetTableHeader($td);
djdd87
źródło
2
Żadna z odpowiedzi nie bierze pod uwagę możliwości, że th może mieć colspan większy niż 1, co jest moim przypadkiem użycia :(
Dexygen
1
@GeorgeJempty Moja odpowiedź obsługuje colspans.
doug65536

Odpowiedzi:

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

Lub trochę uproszczone

var $th = $td.closest('table').find('th').eq($td.index());
user113716
źródło
2
jeśli umieszczasz więcej tabel w swoich tabelach, użyj .parent('table')zamiast.closest('table')
Dead.Rabit
14
a co z colspansami?
bradvido
@bradvido - Moja odpowiedź bierze to pod uwagę
vsync
10
var $th = $("table thead tr th").eq($td.index())

Najlepiej byłoby użyć identyfikatora do odniesienia się do tabeli, jeśli jest więcej niż jedna.

Adam
źródło
Na stronie może znajdować się więcej niż jedna tabela, przez co to rozwiązanie jest niewiarygodne
vsync
5

Rozwiązanie, które radzi sobie colspan

Mam rozwiązanie polegające na dopasowaniu lewej krawędzi tddo lewej krawędzi odpowiedniego th. Powinien obsługiwać dowolnie złożone kolumny.

Zmodyfikowałem przypadek testowy, aby pokazać, że arbitralny colspanjest obsługiwany poprawnie.

Live Demo

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
źródło
Rozszerzyłem przypadek testowy, aby jednocześnie używać dowolnych kombinacji colspanw nagłówkach i wierszach, i nadal działał. Z przyjemnością usłyszę o wszelkich przypadkach, które mogą nie zadziałać.
doug65536
4

Możesz to zrobić za pomocą indeksu td:

var tdIndex = $td.index() + 1;
var $th = $('#table tr').find('th:nth-child(' + tdIndex + ')');
buntownik
źródło
1
Pamiętaj, że .index()jest liczony od zera i od nth-childjedynki. Więc wynik byłby różny o jeden. : o)
user113716
3

Czyste rozwiązanie JavaScript:

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
źródło
1

Znajdź dopasowanie thdla a td, biorąc pod uwagę colspankwestie indeksowe.

$('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
źródło
0

To proste, jeśli odwołujesz się do nich według indeksu. Jeśli chcesz ukryć pierwszą kolumnę, wykonaj następujące czynności:

Skopiuj kod

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

Powodem, dla którego najpierw wybrałem wszystkie wiersze tabeli, a następnie zarówno td, jak i th, które były n-tym dzieckiem, jest to, że nie musielibyśmy dwukrotnie wybierać tabeli i wszystkich wierszy tabeli. Poprawia to szybkość wykonywania skryptów. Pamiętaj, że nth-child()jest 1oparty, a nie 0.

مهدی عابدی برنامه نویس و مشاور
źródło