Odd border around html table cell with colspan? - javascript

My question is similar to THIS question, but I'm unable to use divs instead of colspans with a table.
It appears to be an issue that only appears in chrome, but I need to find a workaround.
My use case is very similar to the one below. Notice how the top border for 3.3 spans two columns, which is clearly not right. In my use case, the user is able to change which cells are merged so I can't set the border for a specific cell.
How do you set a cell's border to be confined to its own cell instead of sharing with a common cell whose colspan is greater than 1?
HTML
<div style="padding: 10px">
<table>
<tr>
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
<td colspan="2">2.3</td>
<td>2.5</td>
</tr>
<tr>
<td>3.1</td>
<td>3.2</td>
<td>3.3</td>
<td>3.4</td>
<td>3.5</td>
</tr>
<tr>
<td>4.1</td>
<td>4.2</td>
<td>4.3</td>
<td>4.4</td>
<td>4.5</td>
</tr>
<tr>
<td>5.1</td>
<td>5.2</td>
<td>5.3</td>
<td>5.4</td>
<td>5.5</td>
</tr>
</table>
</div>
CSS
table {
table-layout: fixed;
border-spacing: 0;
border-collapse: collapse;
}
td {
border: 1px solid lightgrey;
height: 60px;
width: 60px;
text-align: center;
vertical-align: middle;
}
td.active {
border: 1px solid blue;
}
td.brdr-b-hide {
border-bottom: none;
}
td.brdr-r-hide {
border-right: none;
}
JavaScript
var fnActivate = function(target) {
target.addClass('active');
if(!target.is(':first-child')) {
target.prev().addClass('brdr-r-hide')
}
var tr = target.closest('tr');
if(!tr.is(':first-child')) {
var prevTr = tr.prev();
$('td', prevTr).eq($('td', tr).index(target)).addClass('brdr-b-hide');
}
};
var fnDeactivate = function(target) {
target.removeClass('active');
if(!target.is(':first-child')) {
target.prev().removeClass('brdr-r-hide')
}
var tr = target.closest('tr');
if(!tr.is(':first-child')) {
var prevTr = tr.prev();
$('td', prevTr).eq($('td', tr).index(target)).removeClass('brdr-b-hide');
}
}
$('table').on('click', 'td', function(e){
var target = $(e.currentTarget);
if(e.ctrlKey && target.hasClass('active')){
fnDeactivate(target);
} else if(e.ctrlKey) {
fnActivate(target);
} else {
fnDeactivate($('table td.active'));
fnActivate(target);
}
});
CODE: Plunkr

Issue was fixed by using:
table {
border-collapse: separate;
}
Code: Plunkr
It's a little different on the front end as each cell now has its own border of 1px, but it's a good workaround for the time being.

I think this usecase is best adressed with the outline css property.
See: http://jsfiddle.net/4zxv4o59/
td.active {
outline: 1px solid blue;
}
Outlines do not take up space, they are drawn above the content.
from https://developer.mozilla.org/en/docs/Web/CSS/outline

Related

make empty table before adding elements

im trying to make a table that fills some space before adding rows...
i tried making an empty row with a height of like 500px but this dosnt seems to work as intended.
<table>
<thead>
<tr>
<th>ID ARTICULO</th>
<th>NOMBRE</th>
<th>FORMATO</th>
<th>CANTIDAD</th>
<th>POR</th>
<th>TOTAL</th>
<th>LOTE</th>
<th>FECHA VENC</th>
<th>Valor Tot</th>
<th>Valor Unit</th>
</tr>
</thead>
<tbody>
<tr style="height:500px ;"></tr>
</tbody>
</table>
I want to make it look like there are 10 empty rows and when adding elements with JS they appear occuping those spaces in order
This is the expected result, but its made with flash
You could use a row of empty td that has your height set to 500px and uses a repeating background linear gradient. Below the nth-child code is for when you have actual rows of data and the :first-child:last-child is for when you don't have any data as the row will be the only child:
table {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
border: 1px solid black;
}
tbody tr:nth-child(odd) td {
background: #cccccc;
}
tbody tr:nth-child(even) td {
background: #ffffff;
}
tbody tr:first-child:last-child td {
/* the 50px increments here is the height of the td divided by 10 to make it look like you have ten rows) */
background: repeating-linear-gradient(#cccccc, #cccccc 50px, #ffffff 50px, #ffffff 100px);
);
}
<table>
<thead>
<tr>
<th>ID ARTICULO</th>
<th>NOMBRE</th>
<th>FORMATO</th>
<th>CANTIDAD</th>
<th>POR</th>
<th>TOTAL</th>
<th>LOTE</th>
<th>FECHA VENC</th>
<th>Valor Tot</th>
<th>Valor Unit</th>
</tr>
</thead>
<tbody>
<tr style="height:500px;">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
This is one of the many ways to achieve the result of having an empty table with a function that will populate the next available empty row (if any).
initTable(5);
const fixedRow = [1,2,3,4,5,6,7,8,9,10] ;
function initTable(nRows){
const nCols = document.querySelectorAll('#mytable thead tr th').length;
const tbody = document.querySelector('#mytable tbody');
for(let j=0; j<nRows; j++){
const tr = document.createElement('tr');
tr.setAttribute('data-empty', 'true');
for(let k=0; k<nCols; k++){
const td = document.createElement('td');
tr.appendChild(td);
}
tbody.appendChild(tr);
}
}
function populateNextEmptyRow(datarow){
const table = document.querySelector('#mytable');
const firstEmptyRow = document.querySelector('#mytable tbody tr[data-empty=true]');
if (firstEmptyRow == null){
console.log('no more available empty rows');
return;
}
let i=0;
for(cellvalue of datarow){
firstEmptyRow.children[i].innerText = cellvalue;
i++;
}
firstEmptyRow.setAttribute('data-empty', 'false');
}
#mytable td{
border: solid 1px lightgray;
height: 2rem;
text-align: center;
}
button {
cursor: pointer;
margin-top: 5px;
}
<table id="mytable">
<thead>
<tr>
<th>ID ARTICULO</th>
<th>NOMBRE</th>
<th>FORMATO</th>
<th>CANTIDAD</th>
<th>POR</th>
<th>TOTAL</th>
<th>LOTE</th>
<th>FECHA VENC</th>
<th>Valor Tot</th>
<th>Valor Unit</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<button onclick="populateNextEmptyRow(fixedRow);">populateNextRow</button>
You probably can't make the width of the row/table 500px because the actual width of the table is around 700px given the current font size of the headings. So you may want to reduce those down to about 0.7em.
But you can also build the rows/cells using a helper function so you don't have to hardcode them in the HTML, and then you can style the table/cells using CSS.
// Take in a number, a type, and a value,
// create a new array of template strings
// and then join that array up into an HTML string
function builder(n, type, value) {
return new Array(n)
.fill('')
.map(el=> `<${type}>${value}</${type}>`)
.join('');
}
// Create some HTML: a set of 10 rows that have 10 cells
const html = builder(10, 'tr', builder(10, 'td', ' '));
// Attach that HTML to the table body
const tbody = document.querySelector('tbody');
tbody.innerHTML = html;
table { border-collapse: collapse; border: 1px solid #565656; width:500px; table-layout: fixed; }
th { font-size: 0.7em; background-color: white; text-transform: lowercase; }
th:first-letter { text-transform: capitalize; }
th, td { border: 1px solid #dfdfdf; padding: 0 0.3em;}
tr:nth-child(odd) {background-color: #efefef;}
td { width: 10%; }
<table>
<thead>
<tr>
<th>ID ARTICULO</th>
<th>NOMBRE</th>
<th>FORMATO</th>
<th>CANTIDAD</th>
<th>POR</th>
<th>TOTAL</th>
<th>LOTE</th>
<th>FECHA VENC</th>
<th>Valor Tot</th>
<th>Valor Unit</th>
</tr>
</thead>
<tbody>
</tbody>
</table>

How to create a lot of custom JavaScript "alert" boxes in the same file?

I tried to google this question, and the answer to custom alert boxes in javascript is usually jquery dialog. And this works great with one query, but I have a huge table where 90% of the cells is supposed to be clickable to open up a small alert window with information.
I tried one Stack question (link under). But the same answer made a fault in the code.
So here is my sample code that "works" right now:
<table>
<tr>
<td>Manufacturer</td>
<td>Product</td>
<td>Price range 1</td>
<td>Price range 1</td>
<td>Price range 1</td>
</tr>
<tr>
<td>Umbrella Company</td>
<td>Vaccine</td>
<td><div onclick="alert('1399')">1399</div></td>
<td><div onclick="alert('4299')">4299</div></td>
<td><div onclick="alert('5999')">5999</div></td>
</tr>
</table>
This option works, and but is not working as custom.
This other option, with custom code with jQuery works with one cell, and all the other cells just cries out the same statement.
Test the jsfiddle source under with both tables, one with alert() and one with jquery box.
Is it not possible to do it this way?
Source one: How to change the style of alert box?
Source two: https://jsfiddle.net/olelasse/e6hk9340/
You could avoid more duplication by using child functions or passing the element reference but this is the general idea. I'm not a huge fan of DOM refs because it's fragile. Move one element and everything goes to Hades in a handbasket.
function functionAlert(msg) {
var confirmBox = $("#confirm");
confirmBox.find(".message").text(msg);
var myYes = confirmBox.find(".yes");
myYes.on('click', function() {
confirmBox.hide();
});
//myYes.click(myYes);
confirmBox.show();
}
#confirm {
display: none;
background-color: #F3F5F6;
color: #000000;
border: 1px solid #aaa;
position: fixed;
width: 300px;
height: 400px;
left: 40%;
top: 40%;
box-sizing: border-box;
text-align: center;
}
#confirm button {
background-color: #FFFFFF;
display: inline-block;
border-radius: 12px;
border: 4px solid #aaa;
padding: 5px;
text-align: center;
width: 60px;
cursor: pointer;
bottom: 5px;
}
#confirm .message {
padding: 5px;
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<title>JS Alert Box</title>
</head>
<body>
<h2>
Table 1
</h2>
<h3>
Alert()
</h3>
<table border="1">
<tr>
<td>Manufacturer</td>
<td>Product</td>
<td>Price range 1</td>
<td>Price range 2</td>
<td>Price range 3</td>
</tr>
<tr>
<td>Umbrella Company</td>
<td>Vaccine</td>
<td><div onclick="functionAlert('1399')">1399</div></td>
<td><div onclick="functionAlert('4299')">4299</div></td>
<td><div onclick="functionAlert('5999')">5999</div></td>
</tr>
<tr>
<td>Umbrella Company</td>
<td>Vaccine 2</td>
<td><div onclick="functionAlert('1299')">1299</div></td>
<td><div onclick="functionAlert('4199')">4199</div></td>
<td><div onclick="functionAlert('5899')">5899</div></td>
</tr>
<tr>
<td>Microhard</td>
<td>PDA</td>
<td><div onclick="functionAlert('999')">999</div></td>
<td><div onclick="functionAlert('3599')">3599</div></td>
<td><div onclick="functionAlert('6299')">6299</div></td>
</tr>
</table>
<div id="confirm">
<div class="message">
</div>
<button class="yes">Close</button>
</div>
</body>
</html>
Don't write the HTML by hand. Generate it dynamically based on your data. You could use a library like React, or just use the DOM as I've demonstrated below.
This way, no matter how large your table is, you need only write the event handler logic once. There are additional ways you could simplify this code, but which you choose will depend on your experience and goals.
// All your data are belong to this array
const data = [
["Umbrella Company", "Vaccine", 1399, 4299, 5999],
["Soylent Corporation", "Soylent Green", 299, 399, 599],
["Omni Consumer Products", "ED-209", 19990, 39990, 78990],
["Tyrell Corporation", "Nexus-6", 27990, 31990, 59990],
];
const table = document.getElementById("products");
for (const row of data) {
const tr = document.createElement("tr");
const manTD = document.createElement("td");
manTD.innerText = row[0];
tr.appendChild(manTD);
const prodTD = document.createElement("td");
prodTD.innerText = row[1];
tr.appendChild(prodTD);
const range1TD = document.createElement("td");
range1TD.innerText = row[2];
range1TD.addEventListener("click", function() {
alert(row[2]);
});
tr.appendChild(range1TD);
const range2TD = document.createElement("td");
range2TD.innerText = row[3];
range2TD.addEventListener("click", function() {
alert(row[3]);
});
tr.appendChild(range2TD);
const range3TD = document.createElement("td");
range3TD.innerText = row[4];
range3TD.addEventListener("click", function() {
alert(row[4]);
});
tr.appendChild(range3TD);
table.appendChild(tr)
}
<table id="products">
<tr>
<th>Manufacturer</th>
<th>Product</th>
<th>Price range 1</th>
<th>Price range 1</th>
<th>Price range 1</th>
</tr>
</table>
Whenever possible try and keep your code DRY, below I've modified your code to do the following->
Used a delegated event handler on the table. This means you only need one event to handle all the TD's, and better still if a TD was added dynamically later it would work with the added lines.
Used an array to store the data, we can then use this to render the table lines.
Used the .dataset property to store the type of data stored in the TD, I'm only using this to prevent the dialog showing if you don't click a TD with numbers in, but I could have used a class, or even parsed the .innerText
const data = [
["Umbrella Company", "Vaccine", 1399, 4299, 5999],
["Umbrella Company", "Vaccine2", 1299, 4199, 5899],
["Microhard", "PDA", 999, 3599, 6299]
];
const table =
document.querySelector('table');
const confirmBox =
document.querySelector('#confirm');
const confirmBoxMsg =
confirmBox.querySelector('.message');
const confirmBoxYes =
confirmBox.querySelector('.yes');
function fillTable() {
for (const d of data) {
const tr = document.createElement('tr');
for (const v of d) {
const td = document.createElement('td');
td.dataset.type = typeof v;
td.innerText = v;
tr.appendChild(td);
}
table.appendChild(tr);
}
}
table.addEventListener('click', ev => {
const td = ev.target.closest('td');
if (!td) return; //did with click a TD?
if (td.dataset.type !== 'number') return;
confirmBoxMsg.innerText = td.innerText;
confirmBox.style.display = 'block';
});
confirmBoxYes.addEventListener('click', ev => {
confirmBox.style.display = 'none';
});
fillTable();
#confirm {
display: none;
background-color: #F3F5F6;
color: #000000;
border: 1px solid #aaa;
position: fixed;
width: 300px;
height: 400px;
left: 40%;
top: 40%;
box-sizing: border-box;
text-align: center;
}
#confirm button {
background-color: #FFFFFF;
display: inline-block;
border-radius: 12px;
border: 4px solid #aaa;
padding: 5px;
text-align: center;
width: 60px;
cursor: pointer;
bottom: 5px;
}
#confirm .message {
padding: 5px;
text-align: left;
}
<html>
<head>
<title>JS Alert Box</title>
</head>
<body>
<h2>
Table 1
</h2>
<h3>
Alert()
</h3>
<table border="1">
<tr>
<td>Manufacturer</td>
<td>Product</td>
<td>Price range 1</td>
<td>Price range 2</td>
<td>Price range 3</td>
</tr>
</table>
<div id="confirm">
<div class="message">
</div>
<button class="yes">Close</button>
</div>
</body>
</html>

How to make a partially un-editable table cell compatible with inline JavaScript functions?

So, a few days ago, I posted this question (nearly identical) and received a very helpful response.
However, in order to make a table calculator, I already have a id set to every table row of a certain column to turn the table into a calculator, which kind of messes up the answer for the original question when I try to apply it for myself (the JavaScript parses the unit "kg" in with the number and displays a sum as "NaN").
As well, there is a visible text box displayed inside of every cell with the answer above, which looks kind of ugly. My current code has cells that don't appear as text boxes but are still editable, which makes for a much sleeker experience in my opinion (I know it makes no functional difference, but the appearance is something that bugs me a lot!)
Below is a mock-up of what I'd like the code to look like. I'm trying to make the numbers/input appear on the right side of the text box, but still on the left side of the unit ("kg").
Below is a mock-up of what I am trying to create (except the numbers would be on the right).
Here is the code I have:
<head>
<style>
table {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
width: 100%;
}
th, td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
padding: 5px;
}
</style>
</head>
<body>
<table>
<tr>
<th>header1</th>
<th>header2</th>
</tr>
<tr>
<td>entry1</td>
<td id="entry1" oninput="myFunction()">4000</td>
</tr>
<tr>
<td>entry2</td>
<td id="entry2" oninput="myFunction()">200</td>
</tr>
<tr>
<td>Total</td>
<td id="total"></td>
</tr>
</table>
<script type="text/javascript">
document.getElementById("entry1").contentEditable = true;
document.getElementById("entry2").contentEditable = true;
function myFunction() {
var entry1 = document.getElementById("entry1").innerText;
var entry2 = document.getElementById("entry2").innerText;
var total2 = parseInt(entry1) + parseInt(entry2);
document.getElementById("total").innerHTML = total2;
}
myFunction();
</script>
</body>
As you can see, it adds up the numbers in the right column and displays a sum in the final row. However, I would like units to display here (e.g. "kg") on the side, that aren't editable and, more importantly, don't get parsed as a number in the JavaScript function. Would be great if the ugly textbox outline doesn't appear inside the cell, too.
Is this possible? Any answers appreciated!
You get NaN when you call parseInt on an empty string. To fix this, change following statement from
var total = parseInt(jack2) + parseInt(john2) + parseInt (joe2);
to
var total = (parseInt(jack2) || 0) + (parseInt(john2) || 0) + (parseInt (joe2) || 0);
and to display the unit alongside the number in the right column, add 2 span elements inside the td element and use flexbox to align them properly.
To make the number editable, add contentEditable attribute on the span element containing the number. span element containing the unit will be non-editable by default.
function myFunction() {
var jack2 = document.getElementById("jack").innerText;
var john2 = document.getElementById("john").innerText;
var joe2 = document.getElementById("joe").innerText;
var total = (parseInt(jack2) || 0) + (parseInt(john2) || 0) + (parseInt(joe2) || 0);
document.getElementById("total").innerHTML = total;
}
myFunction();
table {
width: 100%;
}
table,
tr,
th,
td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
}
th,
td {
padding: 5px;
}
td:last-child {
display: flex;
justify-content: space-between;
border: none;
}
td:last-child span:first-child {
flex-grow: 1;
margin-right: 10px;
outline: none;
text-align: right;
}
#total {
display: flex;
justify-content: flex-end;
}
<table>
<thead>
<tr>
<th>Person</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jack</td>
<td id="jack" oninput="myFunction()">
<span contentEditable="true">4</span>
<span>Kg</span>
</td>
</tr>
<tr>
<td>John</td>
<td id="john" oninput="myFunction()">
<span contentEditable="true">2</span>
<span>Kg</span>
</td>
</tr>
<tr>
<td>Joe</td>
<td id="joe" oninput="myFunction()">
<span contentEditable="true">3</span>
<span>Kg</span>
</td>
</tr>
<tr>
<td>Total</td>
<td id="total"></td>
</tr>
</tbody>
</table>
To avoid the result being "NAN", an if is added and we check the one of the seals is empty '' and replace it with a 0.
In the edit cell two divs are added one to edit the value and the other to add the text "kg".
<style>
table {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
width: 100%;
}
th, td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
padding: 5px;
}
.input_{
width: 90%;
float: left;
}
.peso{
width: 10%;
float: right;
}
</style>
<table>
<tr>
<th>Person</th>
<th>Weight</th>
</tr>
<tr>
<td>Jack</td>
<td>
<div class="input_" id="jack" oninput="myFunction()">1</div>
<div class="peso">kg</div>
</td>
</tr>
<tr>
<td>John</td>
<td>
<div class="input_" id="john" oninput="myFunction()">2</div>
<div class="peso">kg</div>
</td>
</tr>
<tr>
<td>Joe</td>
<td>
<div class="input_" id="joe" oninput="myFunction()">3</div>
<div class="peso">kg</div>
</td>
</tr>
<tr>
<td>Total</td>
<td id="total"></td>
</tr>
</table>
<script type="text/javascript">
document.getElementById("jack").contentEditable = true;
document.getElementById("john").contentEditable = true;
document.getElementById("joe").contentEditable = true;
function myFunction() {
var jack2 = document.getElementById("jack").innerText;
var john2 = document.getElementById("john").innerText;
var joe2 = document.getElementById("joe").innerText;
if(jack2==""){
jack2=0;
}
if(john2==""){
john2=0;
}
if(joe2==""){
joe2=0;
}
var total2 = parseInt(jack2) + parseInt(john2) + parseInt (joe2);
document.getElementById("total").innerHTML = total2+" kg";
}
myFunction();
</script>

How do I only select the "tr" element that was clicked?

I have an HTML table with different rows (TR) and when I click on one row the background color changes (if it blank it becomes blu and if it blue it becomes white).
How can I exclude from this onclick event the TR that have the TD with the class EXPANDREDUCE?
My code is the following but it doesn't work because in this way it works on each TR i click but I need to check if in the TR that I clicked there is one or more TD with the CLASS EXPANDREDUCE and if yes i don't need to do anything:
function rowHighlight() {
$("TR").click(function() {
try {
$(this).parent().prev()[0].tagName;
HighLightTR(this);
} catch (err) {}
});
}
By using the event.target property, like this:
$("tr").on("click", function(event) {
var tr = $(event.target);
});
NOTE: To check to see if it has the class EXPANDREDUCE, change your selector to "tr.EXPANDREDUCE".
Good luck.
Here's an example:
$(function() {
$("thead tr").addClass("background");
$("tbody tr:even").addClass("even");
$("tbody tr:odd").addClass("odd");
$("tbody input:checkbox:checked").parent().parent().addClass("sel");
$("tbody tr").click(function(e) {
var flag = $(this).hasClass("sel");
if (flag) {
$(this).removeClass("sel");
} else {
$(this).addClass("sel");
}
});
});
table {
width: 400px;
border: 2px solid #999;
text-align: center;
border-collapse: collapse;
}
table td, table th {
border: 2px solid #999;
height: 25px;
}
.background {
background-color: #CCC;
}
.even {
background-color: #FFE7BA;
}
.odd {
background-color: #FFF0F5;
}
.sel {
background-color: #FFFF00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<table>
<thead>
<tr>
<th>title</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
</tbody>
</table>
</div>

How to move a column in a table by its header value

I want the 'adult' column moved to the last position (on the right) in the table, but the table is interactive, the number of columns is not fixed, and sometimes, there will be no 'adult' column.
Please help
Here's the table:
table.tableizer-table {
font-size: 12px;
border: 1px solid #CCC;
font-family: Arial, Helvetica, sans-serif;
}
.tableizer-table td {
padding: 4px;
margin: 3px;
border: 1px solid #CCC;
}
.tableizer-table th {
background-color: #104E8B;
color: #FFF;
font-weight: bold;
}
<table class="tableizer-table">
<thead><tr class="tableizer-firstrow"><th></th><th>adult</th><th>embryo</th><th>lava</th><th>pupa</th></tr></thead>
<tbody>
<tr><td>AAEL006466-RA</td><td>ns</td><td>ns</td><td>**</td><td>ns</td></tr>
<tr><td>AAEL006466-S2</td><td>***</td><td>ns</td><td>ns</td><td>ns</td></tr>
<tr><td>AAEL006466-S4</td><td>***</td><td>ns</td><td>*</td><td>ns</td></tr>
</tbody>
</table>
This function will reorder the columns so that the 'adult' column is put last (if it is present in any position in the table).
It does presume that there is AT MOST only one column headed 'adult' (having no 'adult' column is fine though):
$(function() {
function reorderTable() {
var adultCol;
var $headerCells = $(".tableizer-firstrow").children();
$headerCells.each(function(idx, el) {
var title = (el.textContent || el.innerText || "").toLowerCase();
if (title === 'adult') adultCol = idx;
});
if (adultCol) { // adult column is present
$(".tableizer-table tr").each(function(idx, el) {
$(this).append($(this).children().eq(adultCol));
});
}
};
reorderTable();
});
table.tableizer-table {
font-size: 12px;
border: 1px solid #CCC;
font-family: Arial, Helvetica, sans-serif;
}
.tableizer-table td {
padding: 4px;
margin: 3px;
border: 1px solid #CCC;
}
.tableizer-table th {
background-color: #104E8B;
color: #FFF;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="tableizer-table">
<thead>
<tr class="tableizer-firstrow">
<th></th>
<th>adult</th>
<th>embryo</th>
<th>lava</th>
<th>pupa</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAEL006466-RA</td>
<td>ns</td>
<td>ns</td>
<td>**</td>
<td>ns</td>
</tr>
<tr>
<td>AAEL006466-S2</td>
<td>***</td>
<td>ns</td>
<td>ns</td>
<td>ns</td>
</tr>
<tr>
<td>AAEL006466-S4</td>
<td>***</td>
<td>ns</td>
<td>*</td>
<td>ns</td>
</tr>
</tbody>
</table>
EDIT Here's an explanation of how it works...
$(function() { // this waits for DOM to load fully before executing
function reorderTable() {
var adultCol; // this will be the column number that has the 'adult' header
var $headerCells = $(".tableizer-firstrow").children(); // gets the collection of <th> cells
$headerCells.each(function(idx, el) { // runs a function on each <th> cell
// The following is equivalent to writing $(el).text().toLowerCase() -
// to get the inner text so that we can compare it to our search phrase.
// But it is more entertaining to write and will run faster than jQuery's fn.
// It's job is to handle differences between browsers, and to ignore case for the comparison later
var title = (el.textContent || el.innerText || "").toLowerCase();
if (title === 'adult') adultCol = idx; // if we have a match, remember the column #
});
if (adultCol) { // run only if we found the `adult` column index (i.e. it is not null or undefined)
$(".tableizer-table tr").each(function() { // loop over EVERY table row (so both header and body)
// `this` is the current row, and $(this).append(...) will move an element (cell)
// to the last position in that row.
// the inner part says give me the nth cell to move.
// The nth cell being the 'adult' column.
$(this).append($(this).children().eq(adultCol));
});
}
};
reorderTable(); // execute the above function
});
Try the following code:
$(function() {
let firstColumnHeader;
let findPosToMove = $("table").find('tr')[0].cells.length - 2;
jQuery.each($("table tr"), function(index, value) {
if(index === 0){
firstColumnHeader = ($(this).children(":eq(1)")[index].innerText);
}
if(firstColumnHeader == 'adult'){
for(var i = 0; i < findPosToMove; i++){
$(this).children(":eq(1)").before($(this).children(":eq("+(findPosToMove+1)+")"));
}
}
});
});
table.tableizer-table {
font-size: 12px;
border: 1px solid #CCC;
font-family: Arial, Helvetica, sans-serif;
}
.tableizer-table td {
padding: 4px;
margin: 3px;
border: 1px solid #CCC;
}
.tableizer-table th {
background-color: #104E8B;
color: #FFF;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="tableizer-table">
<thead><tr class="tableizer-firstrow"><th></th><th>adult</th><th>embryo</th><th>lava</th><th>pupa</th></tr></thead>
<tbody>
<tr><td>AAEL006466-RA</td><td>ns</td><td>ns</td><td>**</td><td>ns</td></tr>
<tr><td>AAEL006466-S2</td><td>***</td><td>ns</td><td>ns</td><td>ns</td></tr>
<tr><td>AAEL006466-S4</td><td>***</td><td>ns</td><td>*</td><td>ns</td></tr>
</tbody>
</table>

Categories

Resources