I am trying to make a grid with javascript.
The table is being created but there is a space in between the cell borders.
function create_grid(x, y) {
let output = '<table style="width: 50%; height: 50%;">';
output += '<tbody>'
for (i = 0; i < x; i++) {
output += '<tr>';
for (j = 0; j < y; j++) {
output += '<td id="' + String(j) + " " + String(i) + '">' + i + '</td>';
}
output += '</td>';
}
output += "</tbody></table>";
document.write(output);
return true;
}
create_grid(20, 20)
th, td {
border: 1px solid black;
border-style: solid;
border-collapse: collapse;
border-spacing: 0px;
}
table {
border: 10px;
border-color: #000000;
border-style: solid;
}
when i run this the cellborders have a gap in between the cells.
I don't know why this is happening can some one help me?
I've built this table with a sort function and now I'm also trying to set a class for the selected th so I can put some arrows with CSS, as sort indicators.
I need a way to set dynamic .asc and .desc classes to my selected th with JS somewhere on my sortTable() ..
It also needs to be Pure JS.
var myData, asc = {'userId':true, 'id':true, 'title':true, 'completed':true};
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://jsonplaceholder.typicode.com/todos');
myRequest.onload = function () {
myData = JSON.parse(myRequest.responseText);
dataTable(myData);
};
myRequest.send();
function dataTable(data) {
if (data.length > 0) {
var temp = '';
data.forEach((u) => {
temp += '<tr>';
temp += "<td style='text-align: center'>" + u.userId + '</td>';
temp += "<td style='text-align: center'>" + u.id + '</td>';
temp += '<td>' + u.title + '</td>';
temp += "<td style='text-align: center'>" + u.completed + '</td>';
temp += "<td>" + '<input type="button" value="Delete" onclick="deleteRow(this)"> <input type="button" value="Edit" onclick="insertToForm(this)">' + '</td></tr>';
document.getElementById('data').innerHTML = temp;
});
}
}
function sortTable(col){
myData.sort(function(a, b) {
if(asc[col]){
return a[col] > b[col]? 1:-1;
}
else{
return a[col] > b[col]? -1:1;;
}
});
asc[col] = !asc[col];
document.getElementById('data').innerHTML = '';
dataTable(myData);
}
.container{
display: flex;
margin: 25px 10px;
}
.my-table {
border-collapse: collapse;
font-size: 0.9em;
font-family: sans-serif;
min-width: 400px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
margin-right: 15px;
}
.my-table td, th {
padding: 12px 15px;
}
.my-table thead {
background-color: #009879;
color: #ffffff;
text-align: left;
}
.my-table th {
background-color: #009879;
color: #ffffff;
text-align: left;
cursor: pointer;
}
.my-table tbody tr {
border-bottom: 1px solid #dddddd;
}
tbody tr input {
width: 50px;
}
.my-table tbody tr:nth-of-type(even) {
background-color: #f3f3f3;
}
.my-table tbody tr:last-of-type {
border-bottom: 2px solid #009879;
}
<table id="table" class="my-table">
<thead>
<tr>
<th id="tbl-head-userid" onclick="sortTable('userId');">UserID</th>
<th id="tbl-head-id" onclick="sortTable('id');">ID</th>
<th id="tbl-head-title" onclick="sortTable('title');">Title</th>
<th id="tbl-head-completed" onclick="sortTable('completed');">Completion</th>
<th>Action</th>
</tr>
</thead>
<tbody id="data">
</tbody>
</table>
I have edited the snipped. arrow buttons will be shown when the <th> is clicked and the icons on the other headers will be removed
var myData, asc = {'userId':true, 'id':true, 'title':true, 'completed':true};
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://jsonplaceholder.typicode.com/todos');
myRequest.onload = function () {
myData = JSON.parse(myRequest.responseText);
dataTable(myData);
};
myRequest.send();
function dataTable(data) {
if (data.length > 0) {
var temp = '';
data.forEach((u) => {
temp += '<tr>';
temp += "<td style='text-align: center'>" + u.userId + '</td>';
temp += "<td style='text-align: center'>" + u.id + '</td>';
temp += '<td>' + u.title + '</td>';
temp += "<td style='text-align: center'>" + u.completed + '</td>';
temp += "<td>" + '<input type="button" value="Delete" onclick="deleteRow(this)"> <input type="button" value="Edit" onclick="insertToForm(this)">' + '</td></tr>';
document.getElementById('data').innerHTML = temp;
});
}
}
function sortTable(col, e){
myData.sort(function(a, b) {
if(asc[col]){
return a[col] > b[col]? 1:-1;
}
else{
return a[col] > b[col]? -1:1;;
}
});
asc[col] = !asc[col];
document.getElementById('data').innerHTML = '';
dataTable(myData);
var currentTarget = e.currentTarget;
Array.from(currentTarget.parentElement.children).forEach(function(ele) {
ele.classList.remove('asc', 'des');
})
if(!asc[col]) {
currentTarget.classList.add('asc');
} else {
currentTarget.classList.add('des');
}
}
.container{
display: flex;
margin: 25px 10px;
}
.my-table {
border-collapse: collapse;
font-size: 0.9em;
font-family: sans-serif;
min-width: 400px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
margin-right: 15px;
}
.my-table td, th {
padding: 12px 15px;
}
.my-table thead {
background-color: #009879;
color: #ffffff;
text-align: left;
}
.my-table th {
background-color: #009879;
color: #ffffff;
text-align: left;
cursor: pointer;
}
.my-table tbody tr {
border-bottom: 1px solid #dddddd;
}
tbody tr input {
width: 50px;
}
.my-table tbody tr:nth-of-type(even) {
background-color: #f3f3f3;
}
.my-table tbody tr:last-of-type {
border-bottom: 2px solid #009879;
}
th {
position: relative;
}
th.asc:before,
th.des:after {
border: 4px solid transparent;
content: "";
display: block;
height: 0;
right: 5px;
top: 50%;
position: absolute;
width: 0;
}
th.asc:before {
border-bottom-color: #fff;
margin-top: -5px;
}
th.des:after {
border-top-color: #ffff;
}
<table id="table" class="my-table">
<thead>
<tr>
<th id="tbl-head-userid" onclick="sortTable('userId', event);">UserID</th>
<th id="tbl-head-id" onclick="sortTable('id', event);">ID</th>
<th id="tbl-head-title" onclick="sortTable('title', event);">Title</th>
<th id="tbl-head-completed" onclick="sortTable('completed', event);">Completion</th>
<th>Action</th>
</tr>
</thead>
<tbody id="data">
</tbody>
</table>
I have a JSON message that needs to be displayed in a table format as follows. I am trying to display MARKS, PERCENATGE, RESULT columns in different colors based on values. Anything below 40% is Fail and so marks, percentage and result values for Rick will be displayed in Red color where as for rest of students those three columns should be in green color.
Required table:
NAME SEX MARKS PERCENTAGE RESULT
Rick M 32/100 32 F
Rose F 43/45 95.96 P
Alex M 54/75 72 P
Adam M 88/96 91.67 P
JSON message:
[{"NAME":"Rick","SEX":"M","MARKS":"32/100","PERCENTAGE":"32%","RESULT":"F"},{"NAME":"Rose","SEX":"F","MARKS":"43/45","PERCENTAGE":"95.56%","RESULT":"P"},{"NAME":"Alex","SEX":"M","MARKS":"54/75","PERCENTAGE":"72%","RESULT":"P"},{"NAME":"Adam","SEX":"M","MARKS":"88/96","PERCENTAGE":"91.67%","RESULT":"P"}]
I have already written the following code which displays the data in a table format.
<!DOCTYPE html>
<html>
<head>
<title>Spring Session Report</title>
<style>
table, th, td
{
margin:10px 0;
border:solid 1px #333;
padding:2px 4px;
font:15px Verdana;
text-align: center;
}
th {
font-weight:bold;
background-color:#b1babf;
color: black;
font-size: 15px;
text-align: center;
margin: auto;
padding: 8px;
height: 5px;
width: 20%;
}
</style>
</head>
<body>
<input type="button" onclick="CreateTableFromJSON()" value="Generate Semester Report" />
<div id="showData"></div>
</body>
<script>
function CreateTableFromJSON() {
var myBooks = [{"NAME":"Rick","SEX":"M","MARKS":"32/100","PERCENTAGE":"32%","RESULT":"F"},{"NAME":"Rose","SEX":"F","MARKS":"43/45","PERCENTAGE":"95.56%","RESULT":"P"},{"NAME":"Alex","SEX":"M","MARKS":"54/75","PERCENTAGE":"72%","RESULT":"P"},{"NAME":"Adam","SEX":"M","MARKS":"88/96","PERCENTAGE":"91.67%","RESULT":"P"}]
var col = [];
for (var i = 0; i < myReport.length; i++) {
for (var key in myReport[i]) {
if (col.indexOf(key) === -1) {
col.push(key);
}
}
}
var table = document.createElement("table");
var tr = table.insertRow(-1);
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th");
th.innerHTML = col[i];
tr.appendChild(th);
}
for (var i = 0; i < myReport.length; i++) {
tr = table.insertRow(-1);
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = myReport[i][col[j]];
}
}
var divContainer = document.getElementById("showData");
divContainer.innerHTML = "";
divContainer.appendChild(table);
}
</script>
</html>
I know that the color of the MARKS, PERCENTAGE, RESULT columns needs to be done with CSS but I am not sure how to achieve it. Or is there a better way to do it? Can anyone help in this regard?
Check the percentage on each iteration, and give each tr a pass or fail class depending on whether the percentage. Then you can style the last few TDs with nth-child.
You can also significantly clean up your Javascript by using array methods:
function CreateTableFromJSON() {
var myBooks=[{"NAME":"Rick","SEX":"M","MARKS":"32/100","PERCENTAGE":"32%","RESULT":"F"},{"NAME":"Rose","SEX":"F","MARKS":"43/45","PERCENTAGE":"95.56%","RESULT":"P"},{"NAME":"Alex","SEX":"M","MARKS":"54/75","PERCENTAGE":"72%","RESULT":"P"},{"NAME":"Adam","SEX":"M","MARKS":"88/96","PERCENTAGE":"91.67%","RESULT":"P"}]
const divContainer = document.getElementById("showData");
divContainer.textContent = '';
const table = divContainer.appendChild(document.createElement("table"));
const trHead = table.appendChild(document.createElement('tr'));
Object.keys(myBooks[0]).forEach(key => {
trHead.appendChild(document.createElement('th'))
.textContent = key;
});
myBooks.forEach((personData) => {
const tr = table.appendChild(document.createElement('tr'));
const percentStr = personData.PERCENTAGE;
const percent = Number(percentStr.slice(0, percentStr.length - 1));
if (percent < 40) tr.className = 'fail';
else tr.className = 'pass';
Object.values(personData).forEach(tableValue => {
tr.appendChild(document.createElement('td'))
.textContent = tableValue;
});
});
}
table,
th,
td {
margin: 10px 0;
border: solid 1px #333;
padding: 2px 4px;
font: 15px Verdana;
text-align: center;
}
th {
font-weight: bold;
background-color: #b1babf;
color: black;
font-size: 15px;
text-align: center;
margin: auto;
padding: 8px;
height: 5px;
width: 20%;
}
tr.pass > td:nth-child(n + 3) {
color: green;
}
tr.fail > td:nth-child(n + 3) {
color: red;
}
<input type="button" onclick="CreateTableFromJSON()" value="Generate Semester Report" />
<div id="showData"></div>
You can have two classes, one for each possible color:
.red {
background: red;
}
.green {
background: green;
}
Then, depending on whether the percentage is below 40%, you apply one or the other:
const percentage = parseFloat(student.PERCENTAGE); // No need to remove the % at the end.
tableCell.classList.add(percentage < 40 ? 'red' : 'green')
Full example:
// Data:
const students = [{
"NAME":"Rick",
"SEX":"M",
"MARKS":"32/100",
"PERCENTAGE":"32%",
"RESULT":"F"
}, {
"NAME":"Rose",
"SEX":"F",
"MARKS":"43/45",
"PERCENTAGE":"95.56%",
"RESULT":"P"
}, {
"NAME":"Alex",
"SEX":"M",
"MARKS":"54/75",
"PERCENTAGE":"72%",
"RESULT":"P"
}, {
"NAME":"Adam",
"SEX":"M",
"MARKS":"88/96",
"PERCENTAGE":"91.67%",
"RESULT":"P"
}];
// Get a list with all column names:
const columnNames = Object.keys(students[0]);
// And create another one with the ones we want to add a background based
// on the value of the percentage:
const columnNamesWithBackground = ["MARKS", "PERCENTAGE", "RESULT"];
// Create the table:
const table = document.createElement("table");
// Create the header of the table:
const header = table.insertRow();
for (const columnName of columnNames) {
const th = document.createElement("th");
th.innerText = columnName;
header.appendChild(th);
}
// Create the content of the table:
for (const student of students) {
// Add a new row at the end:
tr = table.insertRow(-1);
// Get the percentage and parse it as a number:
const percentage = parseFloat(student.PERCENTAGE);
// Add all the columns and values to this row:
for (const columnName of columnNames) {
const td = tr.insertCell(-1);
if (columnName === 'SEX') {
td.classList.add('borderRight');
} else if (columnNamesWithBackground.includes(columnName)) {
td.classList.add(percentage < 40 ? 'red' : 'green');
}
td.innerText = student[columnName];
}
}
// Add the table to the page:
document.body.appendChild(table);
body {
font-family: monospace;
font-size: 16px;
}
table {
border: 2px solid #000;
border-collapse: collapse;
table-layout: fixed;
text-align: center;
width: 100%;
}
th,
td {
border-bottom: 2px solid #000;
padding: 4px;
}
th {
padding: 8px;
background: #000;
color: #FFF;
font-weight: bold;
width: 20%;
}
.green {
background: #0A2;
color: #FFF;
}
.red {
background: #F00;
color: #FFF;
}
.borderRight {
border-right: 2px solid #000;
}
In the above image the delete button need to align properly. in my code it get align based on file name length.
<script>
var filelist = new Array();
updateList = function () {
var input = document.getElementById('fileUploader');
var output = document.getElementById('divFiles');
var HTML = "<table>";
for (var i = 0; i < input.files.length; ++i) {
filelist[i]=input.files.item(i).name;
HTML += "<tr><td>" + filelist[i] + "</td><td> <button ></button></td></tr>";
}
HTML += "</table>";
output.innerHTML += HTML;
}
</script>
Please try this.
table {
border-collapse: separate;
border-spacing: 0 3px;
width: 600px;
}
Try this
table
{
table-layout: fixed;
width: 300px;
}
td
{
border: 1px solid green;
word-wrap:break-word;
}
try jsfiddle
<style>
table {
border-collapse: separate;
border-spacing: 0 2px;
width: 600px;
table-layout: fixed;
}
tr:nth-child(1n) {
border: 2px solid;
background-color: #eceff1;
color: Black;
}
tr:nth-child(2n) {
border: 2px solid;
color: Black;
}
td {
padding-top: .5em;
padding-left: .5em;
padding-right: .5em;
padding-bottom: .5em;
}
input[type="file"] {
display: none;
}
.label1 {
padding: 3px;
background: #fff;
display: table;
color:black;
}
button {
background-image: url('../../Images/delete.ico');
background-size: cover;
padding-right:0px;
background-color: Transparent;
cursor: pointer;
border: none;
width: 30px;
height: 30px;
}
</style>
<script>
$(document).ready(function () {
$(document).on('click', "button", function (e) {
$(this).closest('tr').remove();
});
});
</script>
<script>
var filelist = new Array();
updateList = function () {
var input = document.getElementById('fileUploader');
var output = document.getElementById('divFiles');
var HTML = "<table>";
for (var i = 0; i < input.files.length; ++i) {
filelist[i]=input.files.item(i).name;
HTML += "<tr><td>" + filelist[i] + "</td><td><button ></button></td></tr>";
}
HTML += "</table>";
output.innerHTML += HTML;
}
</script>
In the above script the delete button is showing in fixed order but i want the file name to be aligned at left and delete button need to at right side corner.
My goal is to get my table columns aligned. My table is currently set up this way because I wanted to have a table with a scroll bar and give each row it's own border and margin. When the mouse overs over a row that row changes color. I have these features but now I am having trouble aligning my table columns.
This is what my table looks like currently.
The tbody has a scroll bar and the each tbody tr has a margin. The tbody has a fixed height of 25vh. The table, thead, th, tbody elements are hardcoded into the html. The tbody rows are written by jquery after the page loads. I have given the td and th elements a 1px solid black border to show you there margins and padding. I plan on removing them once I have aligned them.
Below is my static html code.
<h3 id = "UpdateEmpyeeCaption">Update Employee Table</h3>
<table id = "UpdateEmployeeTable" >
<thead id ="UpdateTableHeadders" >
<tr>
<th class = "UpHeaderCell">EmployeeID </th>
<th class = "UpHeaderCell">Firstname </th>
<th class = "UpHeaderCell">Lastname </th>
<th class = "UpHeaderCell">Username </th>
<th class = "UpHeaderCell">Password </th>
<th class = "UpHeaderCell">Lifeguard </th>
<th class = "UpHeaderCell">Instructor </th>
<th class = "UpHeaderCell">Headguard </th>
<th class = "UpHeaderCell">Supervisor </th>
</tr>
</thead>
<tbody id = "UpdateEmployeeTableinner">
</tbody>
</table>
Next is the function I use to append the table rows into the tbody.
function loadTable( employeelist )
{
var MSG = "";
EmployeeList = employeelist;
for( var emp in employeelist )
{
var id = employeelist[emp]["employeeID"];
var firstname = employeelist[emp]["Firstname"];
var lastname = employeelist[emp]["Lastname"];
var username = employeelist[emp]["Username"];
var Password = employeelist[emp]["Password"];
var lifeguard = "";
if ( employeelist[emp]["Lifeguard"] == true ){ lifeguard = "Yes"; }else{ lifeguard = "no"; }
var instructor = "";
if ( employeelist[emp]["Instructor"] == true ){ instructor = "Yes"; }else{ instructor = "no"; }
var headguard = "";
if ( employeelist[emp]["Headguard"] == true ){ headguard = "Yes"; }else{ headguard = "no"; }
var supervisor = "";
if ( employeelist[emp]["Supervisor"] == true ){ supervisor = "Yes"; }else{ supervisor = "no"; }
MSG += "<tr class = \"UpdateEmployeeCell notHoverTable\">";
MSG += "<td class =\"upEmCell\"> "+id+" </td>";
MSG += "<td class =\"upEmCell\"> "+firstname+" </td>";
MSG += "<td class =\"upEmCell\"> "+lastname+" </td>";
MSG += "<td class =\"upEmCell\"> "+username+" </td>";
MSG += "<td class =\"upEmCell\"> "+Password+" </td>";
MSG += "<td class =\"upEmCell\"> "+lifeguard+" </td>";
MSG += "<td class =\"upEmCell\"> "+instructor+" </td>";
MSG += "<td class =\"upEmCell\"> "+headguard+" </td>";
MSG += "<td class =\"upEmCell\"> "+supervisor+" </td>";
MSG += "</tr>";
}//End of for each employee in employeelist
//Put the rows into tbody of the table.
$('#UpdateEmployeeTableinner').empty();
$('#UpdateEmployeeTableinner').append( MSG );
}/* End of Function loadTable */
My Css being applied to the table in the pitcure
/* Start of Update Employee Table*/
/*table*/
#UpdateEmployeeTable {
border: 3px solid black;
margin: 0;
padding: 0 0 0 0;
overflow:hidden;
display: block;
}
/*thead*/
#UpdateTableHeadders {
background: rgb(221,221, 221);
display: block;
padding: 0em 1em 0em 1em;/* top right bottom left*/
margin: 0; /*margin: <margin-top> || <margin-right> || <margin-bottom> || <margin-left>*/
border-bottom: 3px solid black;
}
/*th*/
.UpHeaderCell {
display: inline;
border: 1px solid black;
width: 11%;
}
/*tbody*/
#UpdateEmployeeTableinner {
border: 1px solid black;
background: white;
overflow: auto;
height: 25vh;
display: block;
}
/*tr inside tbody*/
.UpdateEmployeeCell {
border: 1px solid black;
margin: 0.5em 0.2em 0.5em 0.2em ; /*top right bottom left*/
display: block;
overflow: hidden;
padding: 0.1em;
}
/*td*/
.upEmCell {
display: inline-block;
border: 1px solid black;
}
/*When a table row does not have mouse hover*/
.notHoverTable {
background-color: rgb(4,211,255);
color: black;
border: 2px solid black;
}
/*When a table row does have mouse hover*/
.liOVERTable {
background-color: rgb(5, 255, 12);
border: 2px solid black;
color: black;
cursor: pointer;
cursor: hand;
}
/* End of Update Employee Table*/
So how can I change my CSS to display my table columns aligned with the correct spacing? Do I need to use Javascript to implement correct alignment? I would prefer keeping the solution as CSS.