Comment puis-je obtenir l'en-tête de tableau correspondant (th) à partir d'une cellule de tableau (td)?


86

Compte tenu du tableau suivant, comment puis-je obtenir l'en-tête de tableau correspondant pour chaque élément 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>

Étant donné que j'ai actuellement l'un des tdéléments à ma disposition, comment puis-je trouver l' thélément correspondant ?

var $td = IveGotThisCovered();
var $th = GetTableHeader($td);

2
Aucune des réponses ne prend en compte la possibilité que le th puisse avoir un colspan supérieur à 1, ce qui est mon cas d'utilisation :(
Dexygen

1
@GeorgeJempty Ma réponse gère les colspans.
doug65536

Réponses:


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

Ou un peu simplifié

var $th = $td.closest('table').find('th').eq($td.index());

2
si vous mettez plus de tables dans vos tables, utilisez à la .parent('table')place de.closest('table')
Dead.Rabit

14
qu'en est-il des colspans?
bradvido

@bradvido - Ma réponse tient compte de cela
vsync

10
var $th = $("table thead tr th").eq($td.index())

Il serait préférable d'utiliser un identifiant pour référencer la table s'il y en a plus d'un.


Plus d'un tableau peut être dans la page, ce qui rend cette solution peu fiable
vsync

5

Solution qui gère colspan

J'ai une solution basée sur la correspondance du bord tdgauche du bord gauche du correspondant th. Il doit gérer des colspans arbitrairement complexes.

J'ai modifié le cas de test pour montrer que l'arbitraire colspanest géré correctement.

Démo en direct

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>

J'ai développé le cas de test pour utiliser simultanément des combinaisons arbitraires colspandans les en-têtes et les lignes, et cela fonctionnait toujours. Je serais heureux d'entendre tous les cas que vous pouvez trouver qui ne fonctionneront pas.
doug65536

4

Vous pouvez le faire en utilisant l'index de td:

var tdIndex = $td.index() + 1;
var $th = $('#table tr').find('th:nth-child(' + tdIndex + ')');

1
N'oubliez pas que .index()c'est une base zéro et nth-childune base unique. Donc, le résultat serait de un. : o)
user113716

3

La solution purement 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) + ')')

1

Trouvez la correspondance thpour a td, en tenant compte colspandes problèmes d'index.

$('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>


0

C'est simple, si vous les référencez par index. Si vous souhaitez masquer la première colonne, vous devez:

Copier le code

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

La raison pour laquelle j'ai d'abord sélectionné toutes les lignes de la table, puis les td et les th qui étaient le nième enfant est pour que nous n'ayons pas à sélectionner la table et toutes les lignes de la table deux fois. Cela améliore la vitesse d'exécution du script. Gardez à l'esprit, nth-child()est 1basé, non 0.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.