function connectThem() {
alert('(' + markedCells[0] +') и (' + markedCells[1] + ')');
if (markedCells.length == 2) {
y_distance = markedCells[0][0] - markedCells[1][0];
y_distance = Math.abs(y_distance) + 1; // vertical distance between dots
x_distance = markedCells[0][1] - markedCells[1][1];
x_distance = Math.abs(x_distance) + 1; // horizontal distance between dots
if (x_distance > y_distance) { // if horizontal distance is bigger than vertical distance
markedCells.sort(function(a,b){return a[1] - b[1];});
totalRows = y_distance;
for (var row = 0 ; row < y_distance; row++) {
thisRowLength = Math.floor(x_distance / totalRows);
for (var c = 0; c < thisRowLength; c++) {
document.getElementById('cell-' + markedCells[0][0] + '-' + markedCells[0][1]).style.backgroundColor = "red";
markedCells[0][1] = parseInt(markedCells[0][1]) + 1;
}
if (markedCells[0][0] < markedCells[1][0]) { // if first marked dot is higher
markedCells[0][0] = parseInt(markedCells[0][0]) + 1;
}
else { // if second one is higher
markedCells[0][0] = parseInt(markedCells[0][0]) - 1;
}
totalRows -= 1; // vertical remaining
x_distance -= thisRowLength; // horizontal remaining
}
}
else {
markedCells.sort(function(a,b){return a[0] - b[0];});
totalCols = x_distance;
for (var col = 0; col < x_distance; col++) {
thisColLength = Math.floor(y_distance/totalCols);
for (var r = 0; r < thisColLength; r++) {
document.getElementById('cell-' + markedCells[0][0] + '-' + markedCells[0][1]).style.backgroundColor = "red";
markedCells[0][0] = parseInt(markedCells[0][0]) + 1;
}
if (markedCells[0][1] < markedCells[1][1]) { // if first marked dot is higher
markedCells[0][1] = parseInt(markedCells[0][1]) + 1;
}
else { // if second one is higher
markedCells[0][1] = parseInt(markedCells[0][1]) - 1;
}
totalCols -= 1;
y_distance -= thisColLength;
}
}
}
else { // if more or less than 2 dots to connect
alert("Can't connect " + markedCells.length + " dots");
}
}
This is my ugly code that does the following thing: I mark 2 cells in a table and the script connects those 2 cells with a line - coloring the path cell by cell. Even if it's a lame solution it still works fine. But! The line is asymmetric.
As you can see the upper part has 2-cell lines but the bottom one has 3-cell lines. And it looks assymetric. I want it to add 3-cell lines in the middle of the connecting line or near the ends of the connecting line. How do I do that? Or maybe what is the better solution for connecting cells?
Cause you also asked for other solutions, this is one (based on my comment, which I wonder if it really would work (dind't manage to do it with only CSS though)) but to give you an idea here's an example using javascript and CSS ...
var rows = document.querySelectorAll('table tr');
var styleElement = document.createElement('style');
var styles = '';
rows.forEach((element, index) => {
var rowNr = (index +1);
var cellNr = (index+index +1);
styles = styles + 'tr:nth-child('+rowNr+') td:nth-child('+cellNr+'),tr:nth-child('+rowNr+') td:nth-child('+(cellNr+1)+') { background: red;}'
});
styleElement.innerHTML = styles;
document.body.appendChild(styleElement);
table {
border-collapse: collapse;
}
td {
border: solid 1px gray;
width: 20px;
height: 20px;
}
/* unfortunately this didn't work but shows the logic needed */
/*
tr:nth-child(1) td:nth-child(1),
tr:nth-child(1) td:nth-child(2) {
background: red;
}
tr:nth-child(2) td:nth-child(3),
tr:nth-child(2) td:nth-child(4) {
background: blue;
}
*/
<table>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
</table>
If you want to play with it here is a fiddle
Related
This is my pagination
pagination.js
$(document).ready(function() {
var totalRows = $('#myTable').find('tbody tr:has(td)').length;
var recordPerPage = 10;
var totalPages = Math.ceil(totalRows / recordPerPage);
var $pages = $('<div id="pages"></div>');
for (i = 0; i < totalPages; i++) {
$('<span class="pageNumber"> ' + (i + 1) + '</span>').appendTo($pages);
}
$pages.appendTo('#myTable');
$('.pageNumber').hover(
function() {
$(this).addClass('focus');
},
function() {
$(this).removeClass('focus');
}
);
$('table').find('tbody tr:has(td)').hide();
var tr = $('table tbody tr:has(td)');
for (var i = 0; i <= recordPerPage - 1; i++) {
$(tr[i]).show();
}
$('span').click(function(event) {
$('#myTable').find('tbody tr:has(td)').hide();
var nBegin = ($(this).text() - 1) * recordPerPage;
var nEnd = $(this).text() * recordPerPage - 1;
for (var i = nBegin; i <= nEnd; i++) {
$(tr[i]).show();
}
});
});
Table.php
<table id="myTable" class="table table-bordered " width="100%" cellspacing="0">
</table>
Hello Guys, Can anyone help with this problem. I'm doing pagination in may patient table but my pagination is in my picture above. I want my pagination to start to "Previous 1 2 3 Next" but in my pagination is only " 1 2 3". I want to add Previous and Next. Sorry Guys, I'm just a beginner.
In my example I'm using a table with just 10 entries and recordPerPage is set to 2 for convenience. If there is no previous or next page, previous and next simply don't work. It could be adjusted to not show previous or next instead but maybe this isn't necessary and you're already content with this solution.
$(document).ready(function() {
var totalRows = $('#myTable').find('tbody tr:has(td)').length;
var recordPerPage = 2;
var totalPages = Math.ceil(totalRows / recordPerPage);
var $pages = $('<div id="pages"></div>');
for (i = 0; i < totalPages; i++) {
$('<span class="pageNumber"> ' + (i + 1) + '</span>').appendTo($pages);
}
var next = $('<span class="next" data-target="2">Next</span>');
next.appendTo($pages);
var prev = $('<span class="prev" data-target="0">Previous</span>');
prev.prependTo($pages);
$pages.appendTo('#myTable');
$('.pageNumber').hover(
function() {
$(this).addClass('focus');
},
function() {
$(this).removeClass('focus');
}
);
$('table').find('tbody tr:has(td)').hide();
var tr = $('table tbody tr:has(td)');
for (var i = 0; i <= recordPerPage - 1; i++) {
$(tr[i]).show();
}
$('span.pageNumber').click(function(event) {
$('#myTable').find('tbody tr:has(td)').hide();
var nBegin = ($(this).text() - 1) * recordPerPage;
var nEnd = $(this).text() * recordPerPage - 1;
for (var i = nBegin; i <= nEnd; i++) {
$(tr[i]).show();
}
$(".next").data("target", parseInt($(this).text()) + 1);
$(".prev").data("target", parseInt($(this).text()) - 1);
});
$('span.next').click(function(event) {
if ($(this).data("target") <= $(".pageNumber:last").text()) {
$('#myTable').find('tbody tr:has(td)').hide();
var nBegin = ($(this).data("target") - 1) * recordPerPage;
var nEnd = $(this).data("target") * recordPerPage - 1;
for (var i = nBegin; i <= nEnd; i++) {
$(tr[i]).show();
}
$(this).data("target", $(this).data("target") + 1);
$(".prev").data("target", $(".prev").data("target") + 1);
}
});
$('span.prev').click(function(event) {
if ($(this).data("target") >= $(".pageNumber:first").text()) {
$('#myTable').find('tbody tr:has(td)').hide();
var nBegin = ($(this).data("target") - 1) * recordPerPage;
var nEnd = $(this).data("target") * recordPerPage - 1;
for (var i = nBegin; i <= nEnd; i++) {
$(tr[i]).show();
}
$(this).data("target", $(this).data("target") - 1);
$(".next").data("target", $(".next").data("target") - 1);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>5</td>
</tr>
<tr>
<td>6</td>
</tr>
<tr>
<td>7</td>
</tr>
<tr>
<td>8</td>
</tr>
<tr>
<td>9</td>
</tr>
<tr>
<td>10</td>
</tr>
</table>
This may not answer your question directly but as your question says you are a beginner with JavaScript. As a beginner I'd always try to use existing plugins / librarys which solve my problems before I attempt solving them by myself.
The easiest solution for your problem would be to use something like Datatables. It offers great support for customizing and also comes with your desired pagination out-of-the-box.
If you need help converting your code to datatables ask a new question.
Right now I have this:
<style>
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th, td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
</style>
<table id="schInfoTable">
<thead>
<th onclick="sortTable(0)">Date</th>
<th>Amount</th>
<th>Count</th>
</thead>
<tbody>
<tr>
<td><a onclick="openView('2018-11-14')">2018-11-14</a></td>
<td>$23,000.00</td>
<td>12</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Mandy</td>
<td>Designer</td>
<td>View</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Robert</td>
<td>Cook</td>
<td>View</td>
</tr>
<tr>
<td><a onclick="openView('2018-11-13')">2018-11-13</a></td>
<td>$13,000.00</td>
<td>8</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-13 branches">
<td>James</td>
<td>Driver</td>
<td>View</td>
</tr>
</tbody>
</table>
<script>
function openView(showID){
$("."+showID).toggle();
}
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("schInfoTable");
switching = true;
//Set the sorting direction to ascending:
dir = "asc";
/*Make a loop that will continue until
no switching has been done:*/
while (switching) {
//start by saying: no switching is done:
switching = false;
rows = table.rows;
/*Loop through all table rows (except the
first, which contains table headers):*/
for (i = 1; i < (rows.length - 1); i++) {
//start by saying there should be no switching:
shouldSwitch = false;
/*Get the two elements you want to compare,
one from current row and one from the next:*/
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
/*check if the two rows should switch place,
based on the direction, asc or desc:*/
if (dir == "asc") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
//if so, mark as a switch and break the loop:
shouldSwitch= true;
break;
}
} else if (dir == "desc") {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
//if so, mark as a switch and break the loop:
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
/*If a switch has been marked, make the switch
and mark that a switch has been done:*/
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
//Each time a switch is done, increase this count by 1:
switchcount ++;
} else {
/*If no switching has been done AND the direction is "asc",
set the direction to "desc" and run the while loop again.*/
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
</script>
jsfiddle code here: jsfiddle
When you click on dates it will expand and show additional table row with its data:
But when you click on Date header in order sort by date it all goes wrong:
As you can see, green highlighted table data goes all together to the bottom but they should be like this:
How do I achieve this?
UPDATE: Thanks to David784's code I was able to get desired result, had to do a little tweek though but all credit to David. Here is what I have now:
function openView(showID) {
$("." + showID).toggle();
}
function sortTable(n) {
var table, rows, i, x, y = 0;
var compare1, compare2;
table = document.getElementById("schInfoTable");
switching = true;
rows = table.querySelectorAll('tr.sort');
var sortArr = [];
for (i = 0; i < rows.length; i++) {
x = rows[i];
if (i + 1 in rows) y = rows[i + 1].previousElementSibling;
else y = x.parentElement.lastChild;
var obj = {
sort: x.getElementsByTagName("TD")[n].textContent.toLowerCase(),
range: document.createRange()
};
obj.range.setStartBefore(x);
obj.range.setEndAfter(y);
sortArr.push(obj);
}
function fnSortArrAsc(a, b) {
if (a.sort > b.sort) return 1;
else if (a.sort < b.sort) return -1;
else return 0;
}
function fnSortArrDesc(a, b) {
if (a.sort < b.sort) return 1;
else if (a.sort > b.sort) return -1;
else return 0;
}
compare1 = rows[0].getElementsByTagName("TD")[0].textContent.toLowerCase();
compare2 = rows[rows.length-1].getElementsByTagName("TD")[0].textContent.toLowerCase();
if(compare1 < compare2){
sortArr = sortArr.sort(fnSortArrDesc);
}else{
sortArr = sortArr.sort(fnSortArrAsc);
}
frag = document.createDocumentFragment();
for (i = 0; i < sortArr.length; i++) {
x = sortArr[i];
frag.appendChild(x.range.extractContents());
}
table.appendChild(frag);
}
Full working code is here: jsfiddle
This would be one way of accomplishing what you're trying to do, assuming you want to keep your table structure pretty much the same.
Brief description of the javascript:
assumptions:
add class on each "top level" TR. These are the rows that get sorted
any non-top-level TR is assumed to be a sub-row of the top-level TR above it, and will be moved with that row.
methodology
use that new class added to top-level TRs in a querySelectorAll to get a list of everything we want to sort.
loop: create an array of objects, consisting of
sort value (lower case string contents of correct TD)
DOM range of row and all sub-rows under it
then use built-in javascript Array.sort with simple custom sorting function.
loop: extract all range contents in order into a documentFragment
append documentFragment back to the table
The reason why I'm using the documentFragment is that it saves on DOM reflow and rendering, as described here on MDN, compared with appending each range directly back to the table element one at a time.
Note: if you have a table footer, you would probably want to make use of the tbody element instead of just dealing directly with the table.
function openView(showID) {
$("." + showID).toggle();
}
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("schInfoTable");
switching = true;
//Set the sorting direction
dir = 1;
var thEl = table.querySelectorAll('th')[n];
if (thEl.classList.contains('asc')) dir = -1;
thEl.classList.toggle('asc');
rows = table.querySelectorAll('tr.sort');
var sortArr = [];
for (i = 0; i < rows.length; i++) {
x = rows[i];
if (i + 1 in rows) y = rows[i + 1].previousElementSibling;
else y = x.parentElement.lastChild;
var obj = {
sort: x.getElementsByTagName("TD")[n].textContent.toLowerCase(),
range: document.createRange()
};
obj.range.setStartBefore(x);
obj.range.setEndAfter(y);
sortArr.push(obj);
}
function fnSortArr(a, b) {
if (a.sort > b.sort) return 1 * dir;
else if (a.sort < b.sort) return -1 * dir;
else return 0;
}
sortArr = sortArr.sort(fnSortArr);
console.log(JSON.stringify(sortArr, null, 2));
frag = document.createDocumentFragment();
for (i = 0; i < sortArr.length; i++) {
x = sortArr[i];
frag.appendChild(x.range.extractContents());
}
table.appendChild(frag);
}
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th,
td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="schInfoTable">
<thead>
<th onclick="sortTable(0)">Date</th>
<th>Amount</th>
<th>Count</th>
</thead>
<tbody>
<tr class='sort'>
<td><a onclick="openView('2018-11-14')">2018-11-14</a></td>
<td>$23,000.00</td>
<td>12</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Mandy</td>
<td>Designer</td>
<td>View</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Robert</td>
<td>Cook</td>
<td>View</td>
</tr>
<tr class='sort'>
<td><a onclick="openView('2018-11-13')">2018-11-13</a></td>
<td>$13,000.00</td>
<td>8</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-13 branches">
<td>James</td>
<td>Driver</td>
<td>View</td>
</tr>
</tbody>
</table>
*EDIT: add sort order toggle
An alternative method commonly used would be to put your sub-rows into a child table. For example, your child data would look something like this:
<tr><td colspan='3'> <table>...</table> </td></tr>.
Then every top-level row has a single child-table row beneath it, and you always sort/move the rows in pairs, instead of dealing with any number of child-rows from zero to infinity.
I was very intrueged by your question and I programmed out the idea I had for it.
I hope this aproach will help you.
let testData = [{
date: "2018-11-14",
amount: 23000,
count: 12,
people: [{
name: "Mandy",
designation: "Designer",
detail: "View",
},
{
name: "Robert",
designation: "Cook",
detail: "View",
}
]
},
{
date: "2018-11-13",
amount: 13000,
count: 8,
people: [{
name: "James",
designation: "Driver",
detail: "View",
}]
}
]
let testDiv = document.querySelector('#test');
let main = function() {
let mainTable = document.createElement('table');
mainTable.classList.add('table-style');
let mainTbody = document.createElement('tbody');
let mainTheader = document.createElement('tr');
mainTheader.onclick = sort;
let dateHeader = document.createElement('th');
dateHeader.textContent = 'Date';
mainTheader.appendChild(dateHeader);
let amountHeader = document.createElement('th');
mainTheader.appendChild(amountHeader);
amountHeader.textContent = 'Amount';
let countHeader = document.createElement('th');
countHeader.textContent = 'Count';
mainTheader.appendChild(countHeader);
mainTable.appendChild(mainTheader);
let counter = 0;
testData.forEach(object => {
console.log('MAIN', object);
counter++;
let rowEl = document.createElement('tr');
if (counter % 2 === 0) {
rowEl.classList.add('uneven-row');
}
rowEl.onclick = toggle;
rowEl.id = object.date;
let keys = Object.keys(object);
keys.forEach(key => {
console.log(key, ": ", object[key]);
if (key !== 'people') {
let colEl = document.createElement('td');
colEl.textContent = object[key];
rowEl.appendChild(colEl);
} else {
mainTbody.appendChild(rowEl);
let subTableRow = document.createElement('tr');
subTableRow.id = 'detail-' + object.date;
subTableRow.classList.add('hidden');
let subTable = document.createElement('table');
subTable.classList.add('sub-table-style');
subTableRow.appendChild(subTable);
let subTbody = document.createElement('tbody');
object[key].forEach(detail => {
console.log('DETAIL', detail);
let subRowEl = document.createElement('tr');
let detailKeys = Object.keys(detail);
detailKeys.forEach(detailKey => {
console.log(detailKey, ": ", detail[detailKey]);
let subColEl = document.createElement('td');
subColEl.textContent = detail[detailKey];
subRowEl.appendChild(subColEl);
});
subTbody.appendChild(subRowEl);
});
subTable.appendChild(subTbody);
mainTbody.appendChild(subTableRow);
}
});
});
mainTable.appendChild(mainTbody);
testDiv.appendChild(mainTable);
}
let toggle = function() {
let detailEl = document.querySelector('#detail-' + this.id);
console.log('TOGGLE', detailEl);
if (detailEl.classList.contains('hidden')) {
detailEl.classList.toggle('hidden');
console.log('SHOW', detailEl.id);
} else {
detailEl.classList.toggle('hidden');
console.log('HIDE', detailEl);
}
}
let compareAsc = function(a, b) {
console.log('A', a);
console.log('B', b);
if (a.date > b.date) {
return 1;
}
if (a.date < b.date) {
return -1;
}
if (a.date === b.date) {
return 0;
}
}
let compareDesc = function(a, b) {
console.log('A', a);
console.log('B', b);
if (a.date < b.date) {
return 1;
}
if (a.date > b.date) {
return -1;
}
if (a.date === b.date) {
return 0;
}
}
let redraw = function() {
while (testDiv.firstChild) {
testDiv.removeChild(testDiv.firstChild);
}
main();
}
let sort = function() {
console.log('SORT', this.classList)
if (!window.sorted) {
console.log('SORT ASC', this);
testData.sort(compareAsc);
window.sorted = true;
redraw();
} else {
console.log('SORT DESC', this);
testData.sort(compareDesc);
window.sorted = false;
redraw();
}
}
main();
body {
font-family: 'Courier New', Courier, monospace;
}
table {
border: 1px solid #ccc;
border-collapse: collapse;
table-layout: fixed;
width: 600px;
}
.sub-table-style {
border: 0px;
background: lawngreen;
}
td {
width: 150px;
padding: 10px;
margin: 0;
border: 0px;
}
.uneven-row {
background: #ddd;
}
.hidden {
visibility: hidden;
display: none;
height: 0px;
overflow: hidden;
}
<div id="test">
</div>
I have so many HTML tables in my application, each table has different no of columns. I wrote the same script code for all pages so I need to set cell size on the basis of table id. I can get table Id how any but cant looping column wise..
reached till here :
$.each(table1, function (i, row) {
rowCount++;
$.each(row, function (j, cellContent) {
if (rowCount == 1) {
doc.margins = 1;
doc.setFont("helvetica");
doc.setFontType("bold");
doc.setFontSize(11);
//trying by this but cant get each cell wise.
for (var k = 0; k <= row[j].length; k++) {
if (TblId == 'Tbl_AddUser' && k==0) {
cellWidth = 20;
}
else if (TblId == 'Tbl_AddUser' && k == 3) {
cellWidth = 40;
}
doc.cell(leftMargin, topMargin, cellWidth, headerRowHeight, cellContent, i);
}
}
})
})
just write the below code inside of first each loop.
if (table.replace('#', '') == 'sample_2') {
for (var k = 0; k < ActualTbl.rows[rowCount].cells.length; k++) {
cellWidth = 30;
}
}
Welcome to StackOverflow.
The correct way to add table-specific settings would be to use css classes.
In your case, you can have css rules based on table IDs.
table#table1 tr td {
width: 200px;
border: 1px solid black;
}
table#table2 tr td {
width: 100px;
border: 1px solid black;
}
<table id='table1'>
<tr>
<td>Cell in table-1</td>
</tr>
</table>
<table id='table2'>
<tr>
<td>Cell in table-2</td>
</tr>
</table>
I'm trying to add rows and columns to a table using user input values to determine the number of rows and columns dynamically using jQuery. Below is my code which actually adds rows and columns but not according to the user's inputs
function makeGrid() {
let numOfRow = 0; let numOfCol = 0;
$('#submit').on('click', function() {
numOfRow = $('#height').val();
numOfCol = $('#width').val();
for (var i = 1; i <= numOfRow; i++) {
let row = $('.grid-canvas').append('<tr>');
for (col = 1; col <= numOfCol; col++) {
$('tr').append('<td></td>');
}
}
});
}
makeGrid();
Assuming a user inputs numOfRow = 2 and numOfCol = 2, I should have a table like this
<tbody class="grid-canvas">
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
Problem is my code seems to be adding extra but I haven't been able to figure it out. This is the result of my code
<tbody class="grid-canvas">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
How do I fix my code?
try changing your code from:
$('#submit').on('click', function() {
numOfRow = $('#height').val();
numOfCol = $('#width').val();
for (var i = 1; i <= numOfRow; i++) {
let row = $('.grid-canvas').append('<tr>');
for (col = 1; col <= numOfCol; col++) {
$('tr').append('<td></td>');
}
}
});
into this
$('#submit').on('click', function() {
numOfRow = $('#height').val();
numOfCol = $('#width').val();
var body = $('.grid-canvas');
for (var i = 1; i <= numOfRow; i++) {
let row = $('<tr></tr>');
for (col = 1; col <= numOfCol; col++) {
row.append('<td></td>');
}
body.append(row);
}
});
what i have done in the above code is created a separate object for the table's body and then once my rows are created with the columns, I append them back to the table object.
Pure javascript code is here
function f(x, y) {
var rows = x,
rowButtonNumber = y;
var table = document.getElementById("myTable");
table.innerHTML = "";
for (var i = 0; i < rows; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < rowButtonNumber; j++) {
var td = document.createElement("td");
var btn = document.createElement("button");
btn.innerHTML = "btn " + (i + 1);
btn.id = "btn-" + i;
btn.onclick = function() {
alert(this.innerHTML);
};
td.appendChild(btn);
tr.appendChild(td);
}
}
}
function go() {
var row = document.getElementById("row").value;
var col = document.getElementById("col").value;
f(row, col);
}
<html>
<head>
<style>
td {
width: 200px;
height: 200px;
}
button {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
Rows
<input id="row" type="number" placeholder="Rows" />
<br> Columns
<input id="col" type="number" placeholder="Columns" />
<button onclick="go()">Go</button>
<table id="myTable" cellspacing="50">
</table>
</body>
It does not seem you are using the row variable. I would suggest appending newly created td to row instead of $('tr').
I want to cut table after tr to insert a div and re-open the table :
Before :
<table>
<tr onClick="cutAfter(this);">
<td>bla</td><td> 123 </td><td>Yes </td>
</tr>
<tr onClick="cutAfter(this);">
<td>bli</td><td> 456 </td><td>no</td>
</tr>
<tr onClick="cutAfter(this);">
<td>blu</td><td> 789 </td><td>hum</td>
</tr>
</table>
After :
<table>
<tr onClick="cutAfter(this);">
<td>bla</td><td> 123 </td><td>Yes </td>
</tr>
<tr onClick="cutAfter(this);">
<td>bli</td><td> 456 </td><td>no</td>
</tr>
</table>
<div onClick="fuse(this)">It works</div>
<table>
<tr onClick="cutAfter(this);">
<td>blu</td><td> 789 </td><td>hum</td>
</tr>
</table>
And return to first state on click.
Any idea (no jQuery).
A simple whay to do it is to use combination of DOM manipulation methods like insertAdjacentHTML to create new table and appendChild to move rows into new table:
function cutAfter(row) {
var table = row.parentNode.parentNode;
if (row.nextElementSibling) {
table.insertAdjacentHTML('afterend', '<table><tbody></tbody></table>');
var newTable = table.nextElementSibling.tBodies[0];
while (row.nextElementSibling) {
newTable.appendChild(row.nextElementSibling);
}
}
}
table {
margin-bottom: 10px;
}
table td {
border: 1px #AAA solid;
}
<table>
<tr onClick="cutAfter(this);">
<td>bla</td><td> 123 </td><td>Yes </td>
</tr>
<tr onClick="cutAfter(this);">
<td>bli</td><td> 456 </td><td>no</td>
</tr>
<tr onClick="cutAfter(this);">
<td>blu</td><td> 789 </td><td>hum</td>
</tr>
</table>
Here's a simple example, made of an HTML file (the structure) and a Javascript file (the behavior). The script uses node manipulation, so as to preserve existing handlers (e.g. added by other scripts). It also attaches event handlers directly, using element.onxxx, to keep things simple, but you should replace that by your favorite event manager.
var makeSplittable = function(table, joinText) {
init();
function init() {
var tBodies = table.tBodies;
for (var ii = 0; ii < tBodies.length; ii++) {
var rows = tBodies[ii].rows;
for (var j = 0; j < rows.length; j++) {
rows[j].onclick = split; // Replace with your favorite event manager
}
}
}
function split(evt) {
var rowIndex = this.rowIndex;
var tbody = findParent(this, "tbody");
var numRows = tbody.rows.length;
if (rowIndex < numRows - 1) {
var rows = [];
for (var ii = rowIndex + 1; ii < numRows; ii++) {
rows.push(tbody.rows[ii]);
}
var existingTable = findParent(this, "table");
var newTable = createTable(rows);
var joiner = createJoiner();
existingTable.parentNode.insertBefore(newTable, existingTable.nextSibling);
existingTable.parentNode.insertBefore(joiner, existingTable.nextSibling);
}
}
function createTable(rows) {
var table = document.createElement("table");
var tbody = document.createElement("tbody");
for (var ii = 0; ii < rows.length; ii++) {
tbody.appendChild(rows[ii]);
}
table.appendChild(tbody);
return table;
}
function createJoiner() {
var div = document.createElement("div");
var content = document.createTextNode(joinText);
div.appendChild(content);
div.onclick = join; // same
return div;
}
function join(evt) {
var previousTable = this.previousSibling;
var nextTable = this.nextSibling;
var tbody = previousTable.tBodies[previousTable.tBodies.length - 1];
var rows = nextTable.rows;
while (rows.length) {
tbody.appendChild(rows[0]);
}
nextTable.parentNode.removeChild(nextTable);
this.parentNode.removeChild(this);
}
function findParent(element, type) {
if (!element || !type) {
return null;
}
if (element.nodeName.toLowerCase() == type.toLowerCase()) {
return element;
}
return findParent(element.parentNode, type);
}
};
makeSplittable(document.getElementById("target"), "Merge adjacent tables");
table,
div {
margin: 5px 0;
}
tr:hover td {
background-color: orange;
}
td {
background-color: yellow;
cursor: pointer;
padding: 10px;
}
div {
color: #0c0;
cursor: pointer;
}
<table id="target">
<tr>
<td>bla</td>
<td>123</td>
<td>Yes</td>
</tr>
<tr>
<td>bli</td>
<td>456</td>
<td>no</td>
</tr>
<tr>
<td>blu</td>
<td>789</td>
<td>hum</td>
</tr>
</table>
A possibility, assuming that a DIV should not be inserted after the last TR if there has not been a cut, but it would have been nice to see your effort. Also assuming no <thead> or <tfoot>.
function isTagName(element, tagName) {
return element.tagName.toUpperCase() === tagName.toUpperCase();
}
function getClosest(element, tagName) {
var closest = null;
while (element !== document && !isTagName(element, tagName)) {
element = element.parentNode;
}
if (element !== document && isTagName(element, tagName)) {
closest = element;
}
return closest;
}
function insertAfter(newNode, referenceNode) {
return referenceNode.parentNode
.insertBefore(newNode, referenceNode.nextSibling);
}
function moveAppend(list, dest, from) {
var index = list.length - 1,
last;
for (last = from || 0; index >= last; index -= 1) {
dest.appendChild(list[index]);
}
return dest;
}
document.body.addEventListener('click', function(e) {
var target = e.target,
tr = getClosest(target, 'tr'),
newDiv,
newTable,
newBody,
next,
parent;
if (tr) {
if (tr.rowIndex < tr.parentNode.rows.length - 1) {
newDiv = document.createElement('div');
newDiv.appendChild(document.createTextNode('It works!'));
insertAfter(newDiv, getClosest(tr, 'table'));
newTable = document.createElement('table');
newBody = document.createElement('tbody');
moveAppend(tr.parentNode.rows, newBody, tr.rowIndex + 1);
newTable.appendChild(newBody);
insertAfter(newTable, newDiv);
}
} else if (isTagName(target, 'div') &&
isTagName(target.previousElementSibling, 'table') &&
isTagName(target.nextElementSibling, 'table')) {
next = target.nextElementSibling;
moveAppend(next.tBodies[0].rows, target.previousElementSibling.tBodies[0]);
parent = target.parentNode;
parent.removeChild(next);
parent.removeChild(target);
}
}, false);
table,
td {
border-style: solid;
border-width: 1px;
}
div {
background-color: yellow;
}
<table>
<tr>
<td>bla</td>
<td>123</td>
<td>Yes</td>
</tr>
<tr>
<td>bli</td>
<td>456</td>
<td>no</td>
</tr>
<tr>
<td>blu</td>
<td>789</td>
<td>hum</td>
</tr>
</table>