Can't find the selectors of a fixed header table - javascript

Original Table Example
Example with Fixed Table Header
The first example shows a comparison table that displays data dynamically in a column on click. When the table is full, it'll remove .addinfo class and go back to the second column to replace old data. The problem comes in when I try to use a fixed header plugin from this page. It creates a second thead to allow th to be fixed at the top, like this:
<table id="toptable" style="padding: 0px;">
<thead class="Original">
<tr>
<th style="visibility:hidden">-</th>
<th class="image addinfo">Fdw</th>
</tr>
</thead>
<thead class="Floating" style="display: none;"> //Second Thead//
<tr>
<th style="visibility:hidden">-</th>
<th class="image addinfo">Fdw</th>
</tr>
</thead>
<tbody>
<tr>
<td class="description">Name</td>
<td class="description addinfo">Fdw</td>
</tr>
<tr>
<td class="title">Age</td>
<td class="title addinfo">Fdw</td>
</tr>
<tr>
<td class="title">Age</td>
<td class="title addinfo">Fdw</td>
</tr>
<tbody>
</table>
As you see in the second example, it can't remove the class .addinfo when the table is full. I guess I need to change the table selectors in the script to get it to work. Can someone tell me which table selectors I should change?
This code only works for the first example:
$(function () {
function filltable(buttontext) {
var i = $('th.addinfo').length !== 0 ? $('th.addinfo:last').index() : 0;
i + 2 > $('th').length || $('th,td').filter(':nth-child(' + (i + 2) + ')')
.addClass('addinfo').html(buttontext);
}
$('.area').each(function () {
var area = $(this),
button = $(this).find('button'),
buttontext = button.text();
button.on("click", function () {
var allCells = $('table').find('th').length-1;
var fullCells = $('table th.addinfo').length;
console.log(allCells, fullCells);
if (allCells === fullCells) { // If table is full
$('table .addinfo').removeClass('addinfo');
filltable(buttontext);
} else { // If table isn't full
filltable(buttontext);
}
});
});
});
First Example Markup
<div class="area">
<button>Gah</button>
</div>
<div class="area">
<button>Kaj</button>
</div>
<div class="area">
<button>Fdw</button>
</div>
<div class="area">
<button>ffdf</button>
</div>
<table>
<thead>
<tr>
<th>Placeholder</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Age</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Nationality</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Education</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Background</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Language</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

Change
var allCells = $('#toptable').find('th').length - 1;
To
var allCells = $('#toptable').find('th').length - 2;
JS FIDDLE DEMO

Related

How to add a class if the number of rows in a table is some number with Javascript/jQuery

I am trying to add class to div if the number of rows in the table is larger than 3.
This is my code.
$('.box').each(function () {
var $this=$(this);
if ($this.find('tbody > tr').length > 3) {
$this.find('.box').addClass('newclass');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box">
<table>
<thead>
<tr>
<th >1</th>
<th >2</th>
</tr>
</thead>
<tbody>
<tr>
<td>lorem1</td>
<td>ipsum1</td>
</tr>
<tr>
<td>lorem2</td>
<td>ipsum2</td>
</tr>
<tr>
<td>lorem3</td>
<td>ipsum3</td>
</tr>
<tr>
<td>lorem4</td>
<td>ipsum4</td>
</tr>
</tbody>
</table>
</div>
I don't see why this code not working, can somebody try to help me with this?
What I try to achieve is this:
<div class="box newclass">
Your code isn't working because this is a reference to the .box element itself. When you do a find() from there you're looking for child elements, so nothing it returned. To fix the issue just remove the find() call.
However you can make the jQuery more succinct by simply using the :has() selector to retrieve .box elements which have more than 3 tr within them:
$('.box:has(tbody > tr:eq(3))').addClass('newclass');
.newclass { color: #C00; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box">
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
</tr>
</thead>
<tbody>
<tr>
<td>lorem1</td>
<td>ipsum1</td>
</tr>
<tr>
<td>lorem2</td>
<td>ipsum2</td>
</tr>
<tr>
<td>lorem3</td>
<td>ipsum3</td>
</tr>
<tr>
<td>lorem4</td>
<td>ipsum4</td>
</tr>
</tbody>
</table>
</div>
<div class="box">
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
</tr>
</thead>
<tbody>
<tr>
<td>lorem1</td>
<td>ipsum1</td>
</tr>
</tbody>
</table>
</div>
you already set the $this to the selector. and by now using $this.find will try to find inside the element itself, so u can use $this directly or search the document itself $(document).find instead of $this.find >>> try the button to show classes list
$('.box').each(function () {
var $this=$(this);
if ($this.find('tbody > tr').length > 3) {
$(document).find('.box').addClass('newclass');
}
});
$('button').on('click', function() {
console.log($(document).find('.box').attr('class'));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box">
<table>
<thead>
<tr>
<th >1</th>
<th >2</th>
</tr>
</thead>
<tbody>
<tr>
<td>lorem1</td>
<td>ipsum1</td>
</tr>
<tr>
<td>lorem2</td>
<td>ipsum2</td>
</tr>
<tr>
<td>lorem3</td>
<td>ipsum3</td>
</tr>
<tr>
<td>lorem4</td>
<td>ipsum4</td>
</tr>
</tbody>
</table>
</div>
<button> show classes list </button>

Make first two columns sticky in a table

I need to make the first two columns sticky in a table having n number of columns each of dynamic width.
I had tried the below CSS
td:nth-child(1), td:nth-child(2){
position:sticky;
left:0px;
}
And then I had set the left position of second column in JS by calculating the width of first column
var width = $("table tr > td:nth-child(1)").outerWidth();
$("table.matrix_class tr > td:nth-child(2)").css('left', width);
Now I need to do all the stuff in CSS not in JS. How do I do that in pure CSS?
Additionally, how do you do this when the first column width is dynamic?
You can do sticky header with using this css.
live working demo
<div class="zui-wrapper">
<div class="zui-scroller">
<table class="zui-table">
<thead>
<tr>
<th class="zui-sticky-col">Name</th>
<th class="zui-sticky-col2">Number</th>
<th>Position</th>
<th>Height</th>
<th>Born</th>
<th>Salary</th>
<th>Prior to NBA/Country</th>
</tr>
</thead>
<tbody>
<tr>
<td class="zui-sticky-col">DeMarcus Cousins</td>
<td class="zui-sticky-col2">15</td>
<td>C</td>
<td>6'11"</td>
<td>08-13-1990</td>
<td>$4,917,000</td>
<td>Kentucky/USA</td>
</tr>
<tr>
<td class="zui-sticky-col">Isaiah Thomas</td>
<td class="zui-sticky-col2">22</td>
<td>PG</td>
<td>5'9"</td>
<td>02-07-1989</td>
<td>$473,604</td>
<td>Washington/USA</td>
</tr>
<tr>
<td class="zui-sticky-col">Ben McLemore</td>
<td class="zui-sticky-col2">16</td>
<td>SG</td>
<td>6'5"</td>
<td>02-11-1993</td>
<td>$2,895,960</td>
<td>Kansas/USA</td>
</tr>
<tr>
<td class="zui-sticky-col">Marcus Thornton</td>
<td class="zui-sticky-col2">23</td>
<td>SG</td>
<td>6'4"</td>
<td>05-05-1987</td>
<td>$7,000,000</td>
<td>Louisiana State/USA</td>
</tr>
<tr>
<td class="zui-sticky-col">Jason Thompson</td>
<td class="zui-sticky-col2">34</td>
<td>PF</td>
<td>6'11"</td>
<td>06-21-1986</td>
<td>$3,001,000</td>
<td>Rider/USA</td>
</tr>
</tbody>
</table>
</div>

jQuery search toggled table rows

I've a table with rows that I can toggle. Now I wanna search in the table. My search function work's but does not display the hidden rows. How can I do this? Here my search function.
$(document).ready(function(){
$("#search").keyup(function(){
var search = $(this).val();
$("table tbody tr").hide();
$(".header-1").show();
$(".header-2").show();
$("table tbody tr td:contains("+search+")").each(function(){
$(this).closest("tr").show();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="skills" id="skills" width="100%" cellspacing="0">
<tr class="header-1">
<th>Skill</th>
<th colspan="2">Theoretische Kenntnisse</th>
<th>Praktische Kenntnisse</th>
<th class="skills_pfl">Zuletzt gepfelgt</th>
</tr>
<tr class="header-2">
<th></th>
<th class="skills_ausb">Ausgebildet</th>
<th class="skills_ausb_jhr">Ausbildungsjahr</th>
<th></th>
<th></th>
</tr>
<tr id="74" class="skills_kat">
<td style="text-align: left;" class="show"
onclick="$('#body-74').toggle(300); $('#fa-74').toggleClass('fa-caret-right').toggleClass('fa-caret-down');">
<i class="fa fa-caret-right" id="fa-74"></i> Anwendungsgebiete
</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tbody id="body-74" class="table-body"></tbody>
<tr id="116" class="skills_kat">
<td style="text-align: left;" class="show"
onclick="$('#body-116').toggle(300); $('#fa-116').toggleClass('fa-caret-right').toggleClass('fa-caret-down');">
<i class="fa fa-caret-right" id="fa-116"></i> Application Server
</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
Some peoples don't understandt me. The search logic works fine, but I've rows that I can toggle with a click. And these rows won't be display if i search the table. Here a screenshot.
Why don't you turn your logic around and hide only the ones you don't want to see? Like so:
$(document).ready(function() {
var consolidatedArray = $("table tbody tr td").slice();
$("#search").keyup(function() {
var search = $(this).val();
$("table tbody tr").show()
$(".header-1").show();
$(".header-2").show();
$("table tbody tr td:not(:contains(" + search + "))").each(function() {
$(this).closest("tr").hide();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>abc</td>
</tr>
<tr>
<td>efg</td>
</tr>
<tr>
<td>xsd</td>
</tr>
<tr>
<td>sdf</td>
</tr>
<tr>
<td>ffs</td>
</tr>
<tr>
<td>abc</td>
</tr>
</tbody>
</table>
<input id="search" type="text"/>

Jquery copying the attribute of the the thead tr td to the tbody tr td

Can we copy the data from thead to tbody? I only wanted to get the data-date
<table>
<thead>
<tr>
<td data-date="2017-10-08"></td>
<td data-date="2017-10-09"></td>
<td data-date="2017-10-10"></td>
<td data-date="2017-10-11"></td>
<td data-date="2017-10-12"></td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
Can i copy the attribute of the thead tr td? to the tbody tr td? so it will also become
<table>
<thead>
<tr>
<td data-date="2017-10-08"></td>
<td data-date="2017-10-09"></td>
<td data-date="2017-10-10"></td>
<td data-date="2017-10-11"></td>
<td data-date="2017-10-12"></td>
</tr>
</thead>
<tbody>
<tr>
<td data-date="2017-10-08"></td>
<td data-date="2017-10-09"></td>
<td data-date="2017-10-10"></td>
<td data-date="2017-10-11"></td>
<td data-date="2017-10-12"></td>
</tr>
</tbody>
Note that I cant manully put the attribute coz this is coming from a plugin
You can set header td value in an array then set it using that arraywith jQuery each() function. check updated snippet below..
var xyz = [];
$('table thead td').each(function(){
xyz.push($(this).data('date'));
})
$('table tbody td').each(function(i,el){
$(this).data('date', xyz[i]).html(xyz[i]);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border='1' celpadding="2">
<thead>
<tr>
<td data-date="2017-10-08"></td>
<td data-date="2017-10-09"></td>
<td data-date="2017-10-10"></td>
<td data-date="2017-10-11"></td>
<td data-date="2017-10-12"></td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Try this solution. Get both tds and iterate over one, use that index and copy the data-date into the tbody tds.
const theadTds = $('thead tr td');
const tbodyTds = $('tbody tr td');
theadTds.each((index, td) => {
const tbodyTd = tbodyTds.eq(index); // Get current tbody td
tbodyTd.data('date', $(td).data('date')); // Set the `data-date` to the `thead td` `data-date`
console.log(tbodyTd.data('date'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td data-date="2017-10-08"></td>
<td data-date="2017-10-09"></td>
<td data-date="2017-10-10"></td>
<td data-date="2017-10-11"></td>
<td data-date="2017-10-12"></td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
No need for any interim variables etc. Just iterate over the columns, this does ALL rows in body, if you just want first one you can do that also.
$('thead').find('tr').find('td').each(function(index){
$('tbody').find('tr').find('td').eq(index).data('date',$(this).data('date')):
});
Only first row in body
$('thead').find('tr').find('td').each(function(index){
$('tbody').find('tr').eq(0).find('td').eq(index).data('date',$(this).data('date')):
});
Alternate syntax if that is more clear to you
$('thead').find('tr').find('td').each(function(index,element){
$('tbody').find('tr').eq(0).find('td').eq(index).data('date',$(element).data('date')):
});

Displaying Width of Tables on Page with jQuery

Sometimes I let the easiest 101 type questions get me! Well, time for the latest chapter.
Lets say I have a html page with one or more tables. Using jQuery I want to display the width of each table found.
Here's the my simple / basic table html -
<table border="1" cellpadding="1" cellspacing="1" style="width: 500px;">
<thead>
<tr>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>
</p>
<table border="1" cellpadding="1" cellspacing="1" style="width: 250px;">
<tbody>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>
</p>
<table border="1" cellpadding="1" cellspacing="1" style="width: 500px;">
<tbody>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Here's the jQuery I'm using -
<script>
$(document).on("pageshow", function () {
$("table:visible").each(function () {
alert($(this).width);
});
});
</script>
I'm using pageshow being this will be part of a jquery mobile site but it easily could be the standard jquery document.ready.
I do indeed get the alert prompt three times but I am not getting width of the current table (this). I'm getting some long message like this -
function (i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}
So what obvious thing am I misunderstanding?
try below code
$(document).on("pageshow", function () {
$("table:visible").each(function () {
alert($(this).width());
});
});
Adding the brackets after width() gave me the functionality I was looking for.

Categories

Resources