Refactoring tables

Viewed 77

I am using a great little block of jQuery with CSS to enable some tables of data to re-flow on small screens. The jQuery works pefectly IF there is just one table on the page... however if there is more than one table - it gets muddled and adds the TH contents of both tables - is there a way to adapt this code to make it run once per each table so as to not mix up the TH names for the columns?

Approach is based on this solution > Is there a way to make Chris Coyier's responsive "list" table with dynamic content?

$(function() {

//Assign class to each header
$('th').each(function() {
$(this).addClass('header-' + $(this).index());
});

//Assign a data-header attribute with the text from the corresponding header
$('td').each(function() {
$(this).attr('data-header', $('.header-' + $(this).index()).text());
});


});

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
</head>

<body>

<style>

table {
width: 100%;
}

th , td {
border: 1px solid black;
border-collapse: collapse;
}



table.data,
table.data thead,
table.data tbody,
table.data th,
table.data td,
table.data tr {
  display: block;
}

table.data thead tr {
  position: absolute;
  top: -9999px;
  left: -9999px;
}
table.data tr {
  /*border: 1px solid #ccc;*/
  margin-bottom: 10px !important;
    border-top: 1px solid #eee !important;
}
table.data tr td {
  /* Behave  like a "row" */
  border-top: none !important;
  border-left: 1px solid #eee !important;
  border-right: 1px solid #eee !important;
  border-bottom: 1px solid #eee !important;
  position: relative;
  padding-left: 50% !important;
}
table.data td:before {
  /* Now like a table header */
  position: absolute;
  left: 6px;
  width: 42%;
  padding-right: 10px;
  white-space: nowrap;
  content: attr(data-header);
  font-weight: 600;
  /*border-right: 1px solid #ccc;*/
}
    
.homeContainer {
width: 88% !important;
margin: 0 6% !important;
}    
    


</style>

<h1>Table 1</h1>

<table class="data">
<thead>
<tr>
<th>TH 1</th>
<th>TH 2</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Example</code></td>
<td>Content here</td>
</tr>
<tr>
<td><code>ANother</code></td>
<td>More data</td>
</tr>
</tbody>
</table>

<h1>2nd table</h1>

<table class="data">
<thead>
<tr>
<th>2nd Table Header 1</th>
<th>2nd Table Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>More</code></td>
<td>Blah blah blah here</td>
</tr>
<tr>
<td><code>Chickens</code></td>
<td>Like Monkeys</td>
</tr>
</tbody>
</table>


 <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
   

<script>

$(function() {

//Assign class to each header
$('th').each(function() {
  $(this).addClass('header-' + $(this).index());
});
//Assign a data-header attribute with the text from the corresponding header
$('td').each(function() {
  $(this).attr('data-header', $('.header-' + $(this).index()).text());
});

});



</script>

</body>
</html>

1 Answers

You are looping through all td and assigning its value but you have not differentiate them i.e : from where to take th values because there are 2 class with same name .Instead , you can iterate through table then inside this iterate through td and then find th from table which is been iterated currently and assign value.

Demo Code :

$(function() {
  $('th').each(function() {
    $(this).addClass('header-' + $(this).index());
  });
  //loop through table
  $("table").each(function() {
    //find thead
    var th = $(this).find('thead')
    //loop through tds
    $(this).find("tbody td").each(function() {
      //find th only from table which is loop currently
      $(this).attr('data-header', $(th).find('.header-' + $(this).index()).text());
    });
  })
});
table {
  width: 100%;
}

th,
td {
  border: 1px solid black;
  border-collapse: collapse;
}

table.data,
table.data thead,
table.data tbody,
table.data th,
table.data td,
table.data tr {
  display: block;
}

table.data thead tr {
  position: absolute;
  top: -9999px;
  left: -9999px;
}

table.data tr {
  /*border: 1px solid #ccc;*/
  margin-bottom: 10px !important;
  border-top: 1px solid #eee !important;
}

table.data tr td {
  /* Behave  like a "row" */
  border-top: none !important;
  border-left: 1px solid #eee !important;
  border-right: 1px solid #eee !important;
  border-bottom: 1px solid #eee !important;
  position: relative;
  padding-left: 50% !important;
}

table.data td:before {
  /* Now like a table header */
  position: absolute;
  left: 6px;
  width: 42%;
  padding-right: 10px;
  white-space: nowrap;
  content: attr(data-header);
  font-weight: 600;
  /*border-right: 1px solid #ccc;*/
}

.homeContainer {
  width: 88% !important;
  margin: 0 6% !important;
}
<h1>Table 1</h1>

<table class="data">
  <thead>
    <tr>
      <th>TH 1</th>
      <th>TH 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>Example</code></td>
      <td>Content here</td>
    </tr>
    <tr>
      <td><code>ANother</code></td>
      <td>More data</td>
    </tr>
  </tbody>
</table>

<h1>2nd table</h1>

<table class="data">
  <thead>
    <tr>
      <th>2nd Table Header 1</th>
      <th>2nd Table Header 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>More</code></td>
      <td>Blah blah blah here</td>
    </tr>
    <tr>
      <td><code>Chickens</code></td>
      <td>Like Monkeys</td>
    </tr>
  </tbody>
</table>


<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>

Related