Fonts in table get messed up after sorting - javascript

I have a following problem I cant wrap my head around.
I have a report of open fault cases that is generated automatically and then send as HTML file to people that need to know.
Previously it was a simple table without any styles, text only. It wasn't very user friendly.
So I added styles and collapsing of cells if they're too long.
Next I wanted to add sorting to it. I've found simple example in JS from w3schools that works.
And here's the problem, when the report is open on mobile device in Chrome (also on desktop in Responsive mode) and the table is sorted, the font size will get messed up.
It affects only some columns and different ones depending on screen width.
This is how it looks like before sorting:
And this is after:
If you expand the cell, you could see that only text that wasn't hidden got messed up:
I tried enclosing the cells in additional DIVs and SPANs, trying different font-size attributes and adding width constraints. Nothing worked so far.
I'm not that proficient with HTML/CSS/JS to figure out what's wrong with it unfortunately.
I would be very glad for any help.
Here is an example report for you to try out:
window.onload = function() {
c = document.getElementsByClassName('expand');
for (i = 0; i < c.length; i++) {
lc = c[i].lastChild;
lc.style.display = "none";
lc.previousSibling.style.display = "inline";
}
c = document.getElementsByClassName('expand');
for (i = 0; i < c.length; i++) {
c[i].addEventListener("click", function(e) {
if (this.lastChild.style.display == "table") {
this.lastChild.style.display = "none";
this.lastChild.previousSibling.style.display = "initial"
} else {
this.lastChild.style.display = "table";
this.lastChild.previousSibling.style.display = "none"
}
console.log(this.id, this.lastChild);
})
}
h = document.getElementsByTagName("th");
for (i = 0; i < h.length; i++) {
h[i].innerHTML += "<br><span>∨ ∧</span>";
}
}
sort_direction = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
function sortTable(column_id, direction) {
// Method from https://www.w3schools.com/howto/howto_js_sort_table.asp
direction = sort_direction[column_id];
sort_direction[column_id] = sort_direction[column_id] * -1;
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("mainTable");
switching = true;
while (switching) {
switching = false;
rows = table.getElementsByTagName("tbody");
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[column_id];
y = rows[i + 1].getElementsByTagName("td")[column_id];
if (direction == -1) {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (direction == 1) {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}
body {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 13px;
}
th,
td,
.e {
background: #fff;
margin: 0 auto;
text-align: center;
/* border-radius */
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
/* box-shadow */
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 3px;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 3px;
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 3px;
word-wrap: break-word;
}
th:hover {
cursor: pointer;
}
tr {
line-height: 14px;
}
table {
border-style: none;
font-size: 10px;
}
.expand {
border: 1.5px solid DodgerBlue;
}
.expand:hover {
background-color: #eee;
cursor: pointer;
}
.medium_cell {
max-width: 220px;
}
.small_cell {
max-width: 75px;
}
<H1>Report</H1>
<h3>Report generated: 2018-06-05 13:10:07</h3>
<table id="mainTable" border="1" bordercolor="#C0C0C0" cellspasing="0" cellpadding="2">
<tbody><tr id="row0" class="class_row">
<th onclick="sortTable(0)">Case ID</th>
<th onclick="sortTable(1)">Status/Title</th>
<th onclick="sortTable(2)">Reported Date</th>
<th onclick="sortTable(3)">Notes</th>
<th onclick="sortTable(4)">Author</th>
<th onclick="sortTable(5)">Assigned Team</th>
<th onclick="sortTable(6)">Assigned Person</th>
<th onclick="sortTable(7)">Severity</th>
<th onclick="sortTable(8)">Priority</th>
<th onclick="sortTable(9)">Flags</th>
<th onclick="sortTable(10)">Information</th>
</tr></tbody>
<tbody><tr id="row3" class="class_row"> <td><a class="small_cell" href="#">ID654321</a></td>
<td class="medium_cell"><p style="font-weight: bold">Many Many Many Lines Status</p>[TT18][TT00+6*TT18]Title of the reported fault</td>
<td class="small_cell">23 May 2018</td>
<td id="row3c1" class="expand medium_cell" style="font-size: 10px;"><div style="font-weight: bold">2018-05-00 00:00:00</div> xxxx xxxxxxxxx xx xxxxBxxx
x4 - xxxxxRxxx, xx. <p style="font-size: 4px;"/><div style="display:none; font-size: 12px;">⇩ <span style="font-style: oblique; font-size: 10px; font-weight: bold">click to expand</span> ⇩</div><div style="display: table;"><div style="font-weight: bold">2018-05-00 00:00:00</div> xxxx xxxxRxx xx xxxxxxxxx
. xxxxxxx Rxxxxx xxxxxxxx.<BR><div style="font-weight: bold">2018-05-00 00:00:00</div> xxxx xxxxBxxx xx xxxxRxx
xxxxxx xxxxx xxxx xxxx xxx</div></td>
<td class="small_cell">Henry</td>
<td>TEAMBLUE</td>
<td class="small_cell">Maria</td>
<td style="background-color:Orange; color:Black;">B<br>Major</td>
<td style="background-color:Orange; color:Black;">2<br>Critical</td>
<td></td>
<td id="row3c2" class="expand"><span style="font-style: oblique">RC: unknown, LE: yyyy-mm-dd</span><div style="font-weight: bold">2018-05-00</div> xxxx (xxxxxx): xxxxxx xxxxxx xxxxx xx xxxxxxx xxxxxxx xx xxxxxxx; xR xxxx <p style="font-size: 4px;"/><div style="display:none; font-size: 12px;">⇩ <span style="font-style: oblique; font-size: 10px; font-weight: bold">click to expand</span> ⇩</div><div style="display: table; margin: 0 auto;"><div style="font-weight: bold">2018-05-00</div> xxxx (xxxxxx): xxxxxxxxxxxxx</div></td>
</tr></tbody>
<tbody><tr id="row4" class="class_row"> <td><a class="small_cell" href="#">ID345678</a></td>
<td class="medium_cell"><p style="font-weight: bold">Even Longer Status</p>[Title_tag][TT00]Title of the reported fault</td>
<td class="small_cell">24 May 2018</td>
<td class="medium_cell" id="row4c1" style="font-size: 10px;"><div style="font-weight: bold">2018-05-00 00:00:00</div> xxxx xxxxxxxxx xx xxxxBxxx
x4 - xxxxxRxxx, xx.</td>
<td class="small_cell">Doug</td>
<td>TEAMBLUE</td>
<td class="small_cell">Ross</td>
<td style="background-color:Orange; color:Black;">B<br>Major</td>
<td style="background-color:Yellow; color:Black;">3<br>Normal</td>
<td></td>
<td id="row4c2" class="expand"><span style="font-style: oblique">RC: unknown, LE: yyyy-mm-dd</span><div style="font-weight: bold">2018-05-00</div> xxxxxx(xxxxxxxx): xxxxxxx xxx xxxxxxxx xxxxxxx xx xxxxxx. <p style="font-size: 4px;"/><div style="display:none; font-size: 12px;">⇩ <span style="font-style: oblique; font-size: 10px; font-weight: bold">click to expand</span> ⇩</div><div style="display: table; margin: 0 auto;"><div style="font-weight: bold">2018-05-00</div> xxxx (xxxxxx): xxxxxx xxxxxx xxxxx xx xxxxxxx xxxxxxx xx xxxxxxx; xR xxxx
<div style="font-weight: bold">2018-05-00</div> xxxx (xxxxxx): xxxxx xxxxx xx xx xxxxxxx xx xx xx345234</div></td>
</tr></tbody>
</table>
* edit *
If you want a file to download and try out yourself, you can get it here

Related

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>

Drag and drop whole table columns in plain Javascript (VanillaJS)?

I have this fiddle:
https://jsfiddle.net/n9epsy5x/2/
I've got drag and drop working for the column headers, but I'd like a header's whole column to move when dragging and dropping the header. How can I pull this off in plain Javascript (VanillaJS)?
I tried adding classes to the table headers and accompanying column elements to be able to target the column elements to get them to move, but I couldn't get that to work.
Any help would be greatly appreciated. Thanks!
var source;
function isbefore(a, b) {
if (a.parentNode == b.parentNode) {
for (var cur = a; cur; cur = cur.previousSibling) {
if (cur === b) {
return true;
}
}
}
return false;
}
function dragenter(e) {
var targetelem = e.target;
if (targetelem.nodeName == "TD") {
targetelem = targetelem.parentNode;
}
if (isbefore(source, targetelem)) {
targetelem.parentNode.insertBefore(source, targetelem);
} else {
targetelem.parentNode.insertBefore(source, targetelem.nextSibling);
}
}
function dragstart(e) {
source = e.target;
e.dataTransfer.effectAllowed = 'move';
}
[draggable] {
user-select: none;
}
body {
background-color: #fff;
color: #303;
font-family: sans-serif;
text-align: center;
}
li {
border: 2px solid #000;
list-style-type: none;
margin: 2px;
padding: 5px;
}
ul {
margin: auto;
text-align: center;
width: 25%;
}
<table>
<thead>
<tr>
<th ondragstart="dragstart(event)" ondragenter="dragenter(event)" draggable="true">
Column 1
</th>
<th ondragstart="dragstart(event)" ondragenter="dragenter(event)" draggable="true">
Column 2
</th>
<th ondragstart="dragstart(event)" ondragenter="dragenter(event)" draggable="true">
Column 3
</th>
</tr>
</thead>
<tbody>
<tr>
<td>hhgr</td>
<td>ffrr</td>
<td>qedf</td>
</tr>
<tr>
<td>wdfe</td>
<td>cjnb</td>
<td>cdke</td>
</tr>
<tr>
<td>awjb</td>
<td>cdjk</td>
<td>ijfe</td>
</tr>
</tbody>
</table>

Compare items in an array against table items in JavaScript, Beginner

I created a really basic table with 20 numbers inside. I have then bodged together a system which creates an array of 20 numbers and shuffles it, there is then a button which displays one position of the array at a time.
What I want to do, which I haven't been able to figure out yet, is to use the number that has been generated to change to background color of that same number in the table. So if I drew the number 20 it would be marked on the table.
Please could you respond with JavaScript only as jQuery is still a little unknown at the moment.
// This bit shuffles an array
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
// Array input
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]);
//This bit calls the position of the array
var f = 0; // the index of the current item to show
function nextNumber() {
document
.getElementById('test')
.innerHTML = ranNums[f++]; // get the item and increment
if (f == ranNums.length) f = 0; // reset to first element if you've reached the end
}
body {
background-color: white;
color: black;
font-size: 20px;
font-family: "Lucida Grande", Verdana,Arial, Helvetica, sans-serif;
}
h1, th {
font-family: Georgia, "Times New Roman",Times, serif;
}
h1 {
font-size: 28px;
}
table {
border-collapse: separate;
border-spacing: 30px;
float: left;
}
th, td {
padding: 30px;
border: 2px black solid;
text-align: center;
width: 20%;
}
h2 {
}
button {
}
#item20 {
background-color: red;
}
<h1>Bingo!</h1>
<h2 id="test"></h2>
<table>
<tr>
<td id="item1"<h1>1</h1></td>
<td id="item2"<h1>2</h1></td>
<td id="item3"<h1>3</h1></td>
<td id="item4"<h1>4</h1></td>
<td id="item5"<h1>5</h1></td>
</tr>
<tr>
<td id="item6"<h1>6</h1></td>
<td id="item7"<h1>7</h1></td>
<td id="item8"<h1>8</h1></td>
<td id="item9"<h1>9</h1></td>
<td id="item10"<h1>10</h1></td>
</tr>
<tr>
<td id="item11"<h1>11</h1></td>
<td id="item12"<h1>12</h1></td>
<td id="item13"<h1>13</h1></td>
<td id="item14"<h1>14</h1></td>
<td id="item15"<h1>15</h1></td>
</tr>
<tr>
<td id="item16"<h1>16</h1></td>
<td id="item17"<h1>17</h1></td>
<td id="item18"<h1>18</h1></td>
<td id="item19"<h1>19</h1></td>
<td id="item20"<h1>20</h1></td>
</tr>
</table>
<button onclick="nextNumber()">Next Number</button>
Change your nextNumber method to also highlight the new random number selected
function nextNumber() {
var number = ranNums[f];
f++;
document.getElementById('test').innerHTML = number;
document.getElementById("item" + number).style.backgroundColor = "red";
if (f == ranNums.length) f = 0; // reset to first element if you've reached the end
}
Demo
// This bit shuffles an array
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i + 1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
// Array input
var ranNums = shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
//This bit calls the position of the array
var f = 0; // the index of the current item to show
function nextNumber() {
var number = ranNums[f];
f++;
document.getElementById('test').innerHTML = number;
document.getElementById("item" + number).style.backgroundColor = "red";
if (f == ranNums.length) f = 0; // reset to first element if you've reached the end
}
body {
background-color: white;
color: black;
font-size: 20px;
font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
}
h1,
th {
font-family: Georgia, "Times New Roman", Times, serif;
}
h1 {
font-size: 28px;
}
table {
border-collapse: separate;
border-spacing: 30px;
float: left;
}
th,
td {
padding: 30px;
border: 2px black solid;
text-align: center;
width: 20%;
}
h2 {}
button {}
#item20 {
background-color: red;
}
<h1>Bingo!</h1>
<h2 id="test"></h2>
<table>
<tr>
<td id="item1" <h1>1</h1>
</td>
<td id="item2" <h1>2</h1>
</td>
<td id="item3" <h1>3</h1>
</td>
<td id="item4" <h1>4</h1>
</td>
<td id="item5" <h1>5</h1>
</td>
</tr>
<tr>
<td id="item6" <h1>6</h1>
</td>
<td id="item7" <h1>7</h1>
</td>
<td id="item8" <h1>8</h1>
</td>
<td id="item9" <h1>9</h1>
</td>
<td id="item10" <h1>10</h1>
</td>
</tr>
<tr>
<td id="item11" <h1>11</h1>
</td>
<td id="item12" <h1>12</h1>
</td>
<td id="item13" <h1>13</h1>
</td>
<td id="item14" <h1>14</h1>
</td>
<td id="item15" <h1>15</h1>
</td>
</tr>
<tr>
<td id="item16" <h1>16</h1>
</td>
<td id="item17" <h1>17</h1>
</td>
<td id="item18" <h1>18</h1>
</td>
<td id="item19" <h1>19</h1>
</td>
<td id="item20" <h1>20</h1>
</td>
</tr>
</table>
<button onclick="nextNumber()">Next Number</button>
You could clean this up a bit, but this one uses a red class. The key is to target the box using document.getElementById("item" + randNum).className = "red";
I have added a resetNumbers() function and button to reset your classes. This is to display the reason why I chose to use a class. Originally I had it resetting after every button click, but if this is BINGO, that probably is not desired. I commented out where I was doing this, but you can still reset.
I prefer this to setting the background colour, as this is controlled through a css class instead, which is easier to manage.
// This bit shuffles an array
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
// Array input
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]);
//This bit calls the position of the array
var f = 0; // the index of the current item to show
function nextNumber() {
var randNum = ranNums[f++];
document.getElementById('test').innerHTML = randNum; // get the item and increment
if (f == ranNums.length) f = 0; // reset to first element if you've reached the end
//resetNumbers();//uncomment if you do not want to reset - or remove if you never want this here
document.getElementById("item" + randNum).className = "red";
}
function resetNumbers() {
for (var i = 0; i < ranNums.length; i++) {
document.getElementById("item" + ranNums[i]).className = "";
}
}
body {
background-color: white;
color: black;
font-size: 20px;
font-family: "Lucida Grande", Verdana,Arial, Helvetica, sans-serif;
}
h1, th {
font-family: Georgia, "Times New Roman",Times, serif;
}
h1 {
font-size: 28px;
}
table {
border-collapse: separate;
border-spacing: 30px;
float: left;
}
th, td {
padding: 30px;
border: 2px black solid;
text-align: center;
width: 20%;
}
.red {
background-color: red;
}
<h1>Bingo!</h1>
<h2 id="test"></h2>
<table>
<tr>
<td id="item1"<h1>1</h1></td>
<td id="item2"<h1>2</h1></td>
<td id="item3"<h1>3</h1></td>
<td id="item4"<h1>4</h1></td>
<td id="item5"<h1>5</h1></td>
</tr>
<tr>
<td id="item6"<h1>6</h1></td>
<td id="item7"<h1>7</h1></td>
<td id="item8"<h1>8</h1></td>
<td id="item9"<h1>9</h1></td>
<td id="item10"<h1>10</h1></td>
</tr>
<tr>
<td id="item11"<h1>11</h1></td>
<td id="item12"<h1>12</h1></td>
<td id="item13"<h1>13</h1></td>
<td id="item14"<h1>14</h1></td>
<td id="item15"<h1>15</h1></td>
</tr>
<tr>
<td id="item16"<h1>16</h1></td>
<td id="item17"<h1>17</h1></td>
<td id="item18"<h1>18</h1></td>
<td id="item19"<h1>19</h1></td>
<td id="item20"<h1>20</h1></td>
</tr>
</table>
<button onclick="nextNumber()">Next Number</button>
<button onclick="resetNumbers()">Reset Numbers</button>

How do I split a table column into new columns from the nth delimiter onwards

I managed to create some code that splits, at the slash delimiter, the third column into new columns.
What I did not manage to do is make it split from the nth (i.e. 2nd) occurrence onwards.
I could not find a similar question on the internet, that's why I post i here.
The desired outcome should be as follows:
function split() {
var delimiter = "/";
var arr = [];
var highest = 0;
var columnIndex = "";
$('#tbl td:nth-child(3)').each(function() {
ColumnIndex = $(this).index();
var string = $(this).text();
var array = string.split(delimiter);
var nbrCharacter = (string.split(delimiter).length - 1) //COUNT OCCURENCES OF CHARACTER
var temp = (nbrCharacter > highest) ? highest++ : highest = highest;
arr.push(string.split(delimiter));
});
for (i = 0; i < highest; i++) { //ADD EMPTY COLUMNS
$('#tbl').find('tr').each(function() {
$(this).find('td').eq(ColumnIndex).after('<td></td>');
});
}
for (i = 0; i < arr.length; i++) { //POPULATE CELLS FROM ARRAY
var columnTracker = ColumnIndex
for (j = 0; j < arr[i].length; j++) {
$('#tbl').find('tr:eq(' + (i + 1) + ')').find('td:eq(' + columnTracker + ')').html(arr[i][j]);
columnTracker++
}
}
}
th {
height: 15px;
min-width: 30px;
border: 1px solid black;
font-size: 12px;
font-family: Courier, monospace;
padding: 2px 5px 2px 5px;
}
td {
height: 15px;
min-width: 30px;
border: 1px solid black;
font-size: 12px;
font-family: Courier, monospace;
padding: 2px 5px 2px 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" onclick="split()">Split</button>
<br>
<br>
<table id="tbl">
<thead>
<tr class="tbl-header">
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<td>A/B/C</td>
<td>B/C</td>
<td>C</td>
<td></td>
</tr>
<tr>
<td>A/B</td>
<td>B/C</td>
<td></td>
<td>D/E</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>A/B/C/D</td>
<td></td>
<td>C/D/E</td>
<td>D/E/F</td>
</tr>
<tr>
<td></td>
<td>B/C/D</td>
<td>C/D</td>
<td>D/E/F/G</td>
</tr>
<tr>
<td>A/B/C</td>
<td>B/C/D/E</td>
<td>C/D/E/F</td>
<td></td>
</tr>
</tbody>
</table>

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