I created a code to convert json data to html table using javascript and ajax:
Data:
[
["text1", "https://www.amazon.com", "text2", "https://www.ebay.com"],
["text3", "https://www.google.com", "text4", "https://www.yahoo.com"],
...
]
This is the code, it work well, but on the table result, the td containing links is text (column2 and column4,
I want to put the text inside href so the cell become link (instead of text):
const TabBody = document.querySelector("#tab > tbody")
function loadData() {
const request = new XMLHttpRequest();
request.open("get", "rows.json");
request.onload = () => {
try {
const json = JSON.parse(request.responseText);
populateTable(json);
} catch (e) {
console.warn("error");
}
};
request.send();
}
function populateTable(json){
while(TabBody.firstChild){TabBody.removeChild(TabBody.firstChild);}
json.forEach((row) => {
const tr = document.createElement("tr");
row.forEach((cell) => {
const td = document.createElement("td");
td.textContent = cell;
tr.appendChild(td);})
TabBody.appendChild(tr);
})
}
document.addEventListener("DOMContentLoaded", () => { loadData();})
<body>
<table id="tab">
<thead>
<tr>
<th>column_1</th>
<th>column_2_link</th>
<th>column_3</th>
<th>column_4_link</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
Instead of just adding a td with you can generate a link inside by checking the string with a Regular Expresion if that's your intention:
const td = document.createElement("td");
td.innerHTML = /https:\/\//g.test(cell)
? `${cell}`
: cell;
tr.appendChild(td);
You could create an anchor element if innerHTML is not safe for you, but that should get you going.
Sharing you one sample. Here, on clicking the update link button, it will update all td that have a link to a clickable item , ie it will get updated with an anchor tag
function populateTable(json){
var regex = new RegExp("(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})"); // expression here
while(TabBody.firstChild){TabBody.removeChild(TabBody.firstChild);}
json.forEach((row) => {
const tr = document.createElement("tr");
row.forEach((cell) => {
const td = document.createElement("td");
if(regex.test($(this).text())){
td.innerHTML = `Link`;
}
else{
td.textContent = cell;
}
tr.appendChild(td);})
TabBody.appendChild(tr);
})
}
Complete sample code for testing
<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
// $('#tbl>tbody').find('td').css("background-color", "yellow");
var regex = new RegExp("(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})"); // expression here
$('table').find("td").each(function(data) {
if(regex.test($(this).text())){
$(this).html(`Contact`)
}
});
});
});
</script>
</head>
<body>
<table id="tbl">
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tbody> <tr>
<td>123123</td>
<td>https://www.amazon.com</td>
<td>Mexico</td>
</tr>
<tr>
<td>123123</td>
<td>https://www.amazon.com</td>
<td>Mexico</td>
</tr>
</tbody>
</table>
<button>Update Link</button>
</body>
</html>
Related
I'm new to Javascript and learn about querySelector(), createElement(), setAttribute and loop.
I try to create a table with a row, which contains 5 cells in it.
Imagine I create in HTML file. I use following code to execute my idea:
// 1. select id = pixelCanvas and store in var table.
const table = document.querySelector('#pixelCanvas');
// 2. create table row element <tr></tr> and append to var table.
table.appendChild(document.createElement('tr'));
// 3. create element table data and store in var data.
const data = document.createElement('td');
// 4. set html attribute with class="cell", width: 20px & height: 20px for table data
data.setAttribute('style', 'width: 20px; height: 20px:');
// 5. use for loop and appendChild() to append 5 <td></td> to <tr></tr>
for (i = 0; i < 5; i++) {
let tblRow = document.querySelector('tr');
tblRow.appendChild(data);
};
Here is the result in HTML page.
Obviously my idea doesn't work as expected. Appreciate your advice: where goes wrong?
prefer to use css to style attributes.
there is also js methods for tables :
HTMLTableElement.insertRow()
HTMLTableRowElement.insertCell()
const myTable = document.querySelector('table#pixelCanvas')
for (let r=0;r<5;++r) {
let row = myTable.insertRow()
for (c=0;c<5;++c) {
row.insertCell().textContent = `${r}.${c}`
}
}
table#pixelCanvas {
border-collapse: collapse;
font-size: 9px;
}
table#pixelCanvas td {
padding: 5px;
width: 20px;
height: 20px;
border: 1px solid black;
}
<table id="pixelCanvas"></table>
Your code is very close to working - you just need to create a seperate td element for each iteration of the for loop, and setting the style attribute is much easier when done via the .style property of the element.
Also instead of trying to query for the row you have just created, you can use the return value of the createElement function - it will give you the variable containing the new element.
See this snippet:
const table = document.querySelector('#pixelCanvas');
const colors = ["red", "orange", "green", "blue", "purple"];
const row = document.createElement('tr');
table.appendChild(row);
for (i = 0; i < 5; i++) {
const cell = document.createElement('td');
cell.style.width = "20px";
cell.style.height = "20px";
cell.style.backgroundColor = colors[i];
row.appendChild(cell);
};
<table id="pixelCanvas"></table>
You mean this
Move the row outside the loop and if you need the cells to be the same, clone the one you made - you also had a typo in it (colon instead of semicolon)
I would also target the tbody since a table should have such a thing
const table = document.querySelector('#pixelCanvas tbody');
const data = document.createElement('td');
data.setAttribute('style', 'width: 20px; height: 20px;');
let tblRow = document.createElement('tr');
for (let i = 0; i < 5; i++) {
let cell = data.cloneNode(true)
cell.textContent = i;
tblRow.appendChild(cell);
}
table.appendChild(tblRow);
<table id="pixelCanvas">
<thead>
</thead>
<tbody>
</tbody>
</table>
Result
<table id="pixelCanvas">
<thead>
</thead>
<tbody>
<tr>
<td style="width: 20px; height: 20px;">0</td>
<td style="width: 20px; height: 20px;">1</td>
<td style="width: 20px; height: 20px;">2</td>
<td style="width: 20px; height: 20px;">3</td>
<td style="width: 20px; height: 20px;">4</td>
</tr>
</tbody>
</table>
I am trying to add a table row containing a div dynamically using JavaScript. Everything is working fine except, when it is added, my columns move slightly. Weirdly, it seems to only happen when the div contains text longer than a certain length.
In the stripped down version below, you can see the problem clearly. After trying it, go to line 24 of the JavaScript, remove the "i" at the end of the string, and it will no longer move my columns.
JSFiddle
setEventListeners();
function setEventListeners() {
var hideMe = document.getElementById('hide-me');
var table = document.getElementById('table');
hideMe.addEventListener('mouseenter', showHoverMenu);
table.addEventListener('mouseleave', deleteOtherMenus);
}
function showHoverMenu(e) {
e.preventDefault();
deleteOtherMenus();
var tr = document.createElement('tr');
tr.setAttribute('class', 'row-menu-parent')
var td = document.createElement('td');
td.colSpan = 4;
var rowMenu = document.createElement('div');
rowMenu.classList.add('row-menu');
var div = document.createElement('div');
// Delete the "i" at the end of the string and try hovering again
div.innerHTML = 'abcdefghi';
rowMenu.appendChild(div);
td.appendChild(rowMenu);
tr.appendChild(td);
var target = e.currentTarget;
target.parentNode.insertBefore(tr, target.nextSibling);
}
function deleteOtherMenus() {
var rowMenu = document.getElementsByClassName('row-menu-parent');
if (rowMenu.length > 0) {
rowMenu[0].parentNode.removeChild(rowMenu[0]);
}
}
* {
border: 1px solid red;
}
table {
width: 100%;
}
.row-menu div {
background-color: lightGrey;
}
<table id="table">
<tr id="hide-me">
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
</tr>
</table>
What is causing my columns to move, and how do I fix it?
EDIT: The columns need to be able to automatically resize, so a fixed table layout will not work.
You can set your table to table-layout: fixed; if you don't want it resizing.
table {
table-layout: fixed; /* Add this */
width: 100%;
}
setEventListeners();
function setEventListeners() {
var hideMe = document.getElementById('hide-me');
var table = document.getElementById('table');
hideMe.addEventListener('mouseenter', showHoverMenu);
table.addEventListener('mouseleave', deleteOtherMenus);
}
function showHoverMenu(e) {
e.preventDefault();
deleteOtherMenus();
var tr = document.createElement('tr');
tr.setAttribute('class', 'row-menu-parent')
var td = document.createElement('td');
td.colSpan = 4;
var rowMenu = document.createElement('div');
rowMenu.classList.add('row-menu');
var div = document.createElement('div');
// Delete the "i" at the end of the string and try hovering again
div.innerHTML = 'abcdefghi';
rowMenu.appendChild(div);
td.appendChild(rowMenu);
tr.appendChild(td);
var target = e.currentTarget;
target.parentNode.insertBefore(tr, target.nextSibling);
}
function deleteOtherMenus() {
var rowMenu = document.getElementsByClassName('row-menu-parent');
if (rowMenu.length > 0) {
rowMenu[0].parentNode.removeChild(rowMenu[0]);
}
}
* {
border: 1px solid red;
}
table {
table-layout: fixed;
width: 100%;
}
.row-menu div {
background-color: lightGrey;
}
<table id="table">
<tr id="hide-me">
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
</tr>
</table>
Try setting box-sizing: border-box in CSS for the table and/or wrap the .row-menu div in a div that does not have any styling.
If you look closely, the inner div's border is expanding the size of the parent TD which is causing the table to re-adjust.
What I am trying to do is create a admin page the I can use edit a table using Javascript. What this is for are live results for tractor pulling to post to our website. All I need is to be able to post the driver, vehicle, distance, and it automatically sort by distance. Currently I am able to do all this for one table, but I want to add a second table for another class. I don't know if this is possible or not. I thought about trying to call another table from a different html file, but don't know how to display both the tables from two different html files together. Any assistance is appreciated. I have some Javascript experience, but not as much as needed for this project.
I have tried to update two different html files which works, but can't get them on the same html page as if it were on our website.
I should be able to be on the admin page, type in the driver's details, click new row for next puller, save it and so on. Once done with the class, click new class (new table) and do it all over again. Once done I want to be able to publish it, but clear everything to be ready for the next event.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Results</title>
<style>
table {
border-spacing: 0;
width: 50%;
border: 1px solid #000000;
counter-reset: rowNumber;
}
th, td {
text-align: left;
padding: 16px;
}
table tr{
counter-increment: rowNumber;
}
tr:nth-child(even){
background-color: #f2f2f2
}
table tr td:first-child::before {
content: counter(rowNumber);
min-width: 1em;
margin-right: 0.5em;
}
</style>
</head>
<table>
<thead>
<th colspan="3"><h1 align="center">Medford, WI</h1></th>
<tr>
<th colspan="3"><h2 align="center">Light Super Stock Tractors</h2></th>
</tr>
<tr>
<th>Driver</th>
<th>Vehicle</th>
<th>Distance</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</html>
<?php
if(!isset($_POST['myTable']))
die('No data provided.');
$table = $_POST['myTable'];
$handle = fopen('myTable.html','w');
$result = fwrite($handle,$table);
if($result)
fclose($handle);
else
die('Error writing file');
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery AJAX</title>
<link type="text/css" rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<style rel="stylesheet" type="text/css">
tr, td,th{
border-collapse: collapse;
border:1px solid;
}
td{
height:22px;
min-width:125px;
}
</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js">"http://jquery.com"</script>
<script type="text/javascript">
$(document).ready(function () {
var getTable = function () {
/*We empty the div */
$('#myTable').html('');
/*We load the table */
$.get('myTable.html', function (callback_data) {
var table = callback_data;
document.getElementById('myTable').innerHTML = table;
});
};
getTable();
/* ----- */
/* New row button */
$('#addRow').click(function (event) {
/* Prevents the real anchor click event (going to href link)*/
event.preventDefault();
/* We get the number of columns in a row*/
var colNumber = $($('#myTable tbody tr')[0]).children('td').length;
var tr = document.createElement('tr');
var td = "";
for (var i = 0; i < colNumber; i++) {
td = document.createElement('td');
td.appendChild(document.createTextNode("\n"));
tr.appendChild(td);
}
$('#myTable tbody').append(tr);
});
$('#addColumn').click(function (event) {
event.preventDefault();
$.each($('#myTable table thead tr'), function () {
$(this).append('<th></th>');
})
$.each($('#myTable table tbody tr'), function () {
$(this).append('<td></td>');
});
});
$('#saveTable').click(function (event) {
event.preventDefault();
var table = $('#myTable').html();
$.post('saveTable.php', {
'myTable': table
}, function (callback_data) {
console.log(callback_data);
$('#myTable').slideToggle('fast');
setTimeout(function () {
getTable();
$('#myTable').slideToggle();
}, 100);
});
});
});
</script>
<script type="text/javascript">
$(document).ready(function () {
var getTable = function () {
/*We empty the div */
$('#myTable2').html('');
/*We load the table */
$.get('myTable2.html', function (callback_data) {
var table = callback_data;
document.getElementById('myTable2').innerHTML = table;
});
};
getTable();
/* ----- */
/* New row button */
$('#addRow2').click(function (event) {
/* Prevents the real anchor click event (going to href link)*/
event.preventDefault();
/* We get the number of columns in a row*/
var colNumber = $($('#myTable2 tbody tr')[0]).children('td').length;
var tr = document.createElement('tr');
var td = "";
for (var i = 0; i < colNumber; i++) {
td = document.createElement('td');
td.appendChild(document.createTextNode("\n"));
tr.appendChild(td);
}
$('#myTable2 tbody').append(tr);
});
$('#addHeader2').click(function (event) {
/* Prevents the real anchor click event (going to href link)*/
event.preventDefault();
/* We get the number of columns in a row*/
var colNumber = $($('#myTable2 tbody tr')[0]).children('td').length;
var tr = document.createElement('tr');
var td = "";
for (var i = 0; i < colNumber; i++) {
td = document.createElement('td');
td.appendChild(document.createTextNode("\n"));
tr.appendChild(td);
}
$('#myTable2 tbody').append(tr);
});
$('#addColumn2').click(function (event) {
event.preventDefault();
$.each($('#myTable2 table thead tr'), function () {
$(this).append('<th></th>');
})
$.each($('#myTable2 table tbody tr'), function () {
$(this).append('<td></td>');
});
});
$('#saveTable2').click(function (event) {
event.preventDefault();
var table = $('#myTable2').html();
$.post('saveTable.php', {
'myTable': table
}, function (callback_data) {
console.log(callback_data);
$('#myTable2').slideToggle('fast');
setTimeout(function () {
getTable();
$('#myTable2').slideToggle();
}, 100);
});
});
});
</script>
</head>
<body>
<h1 align="center">Live Results Admin Page</h1>
<section>
<article>
<div id="myTable" contenteditable></div>
<nav data-type="table-tools">
<ul>
<li>
New row
</li>
<li>
New column
</li>
<li>
Save table
</li>
</ul>
</nav>
</article>
</section>
<section>
<article>
<div id="myTable2" contenteditable></div>
<nav data-type="table-tools">
<ul>
<li>
New row
</li>
<li>
New column
</li>
<li>
Save table
</li>
</ul>
</nav>
</article>
</section>
</body>
</html>
I have an HTML table dynamically generated by js, and I want to add each row an onClick event.
Like this
(because of need to pass complex parameters in my original code, I use Javascript to add onclick function):
<!DOCTYPE html>
<html>
<body>
<table align="center" id="tableID" border="1" style="cursor: pointer;">
<thead>
<th>Text</th>
<th>MoreText</th>
<th>Lorem</th>
<th>Ipsum</th>
</thead>
</table>
<br />
<script type="text/javascript">
for (var i = 0; i < 4; i++) {
document.getElementById("tableID").innerHTML += '<tr><td>Text</td><td>MoreText</td><td>Lorem</td><td>Ipsum</td></tr>';
document.getElementById("tableID").rows[i+1].onclick = function () {
alert("Hello World");
//alert(i);
};
}
</script>
</body>
</html>
If the table row is fixed and declared in HTML document, using this method is working,
but in my code (dynamically generated table row), the onClick function only works in the last row.
I guess that maybe is asynchronous problem, but I can't figure out.
UPDATE
According to #Quentin's method, I edited my code. It works fine.
<!DOCTYPE html>
<html>
<body>
<table align="center" id="tableID" border="1" style="cursor: pointer;">
<thead>
<th>Text</th>
<th>MoreText</th>
<th>Lorem</th>
<th>Ipsum</th>
</thead>
</table>
<br />
<script type="text/javascript">
for (var i = 0; i < 4; i++) {
var table = document.getElementById('tableID');
var tr = document.createElement('tr');
tr.onclick = function () {
alert("Hello World");
};
var td1 = document.createElement('td');
td1.innerText = "Text";
var td2 = document.createElement('td');
td2.innerText = "MoreText";
var td3 = document.createElement('td');
td3.innerText = "Lorem";
var td4 = document.createElement('td');
td4.innerText = "Ipsum";
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
table.appendChild(tr);
}
</script>
</body>
</html>
You are assigning a new value to innerHTML.
This erases all the existing DOM elements and the event handlers attached to them and creates new ones (but you haven't got any code to recreate the event handlers you are deleting).
Don't use innerHTML. Use standard DOM methods: createElement, appendChild, etc. Then you can add your new row to the table body without changing what is already there.
<!DOCTYPE html>
<html>
<head>
<style>
table td { cursor: pointer; border: 1px solid black; }
#out { color: red; }
</style>
</head>
<body>
<table id="tableID">
<thead>
<th>Text</th>
<th>MoreText</th>
<th>Lorem</th>
<th>Ipsum</th>
</thead>
<tbody>
</tbody>
</table>
<div id="out"></div>
<script type="text/javascript">
function createCell(i, row, text) {
var td = document.createElement('td');
var content = document.createTextNode(text + i);
td.appendChild(content);
td.addEventListener('click', function() { document.getElementById('out').innerHTML = 'You clicked ' + this.innerHTML; }, false);
row.appendChild(td);
}
for (var i = 0; i < 4; i++) {
var tr = document.createElement('tr');
createCell(i, tr, 'a');
createCell(i, tr, 'b');
createCell(i, tr, 'c');
createCell(i, tr, 'd');
document.querySelectorAll('#tableID tbody')[0].appendChild(tr);
}
</script>
</body>
</html>
This should probably work, see demo: http://jsbin.com/lucequgotu
I need to write a function (or building onto code below) that will highlight a specific row in a table. It needs to always ignore the table headers so start a row count of 0 after table headers.
<style type="text/css">
#myTbl {
border: 1px solid black
}
#myTbl td, th {
border: 1px solid black
}
#myTbl tr.normal td {
color: black;
background-color: white;
}
#myTbl tr.highlighted td {
color: white;
background-color: gray;
}
</style>
<table id="myTbl">
<thead>
<tr>
<th>ID</th>
<th>CreatedDate</th>
<th>Name</th>
<th>Colour</th>
</tr>
</thead>
<tbody>
<tr>
<td>DFRF</td>
<td>05/03/2010</td>
<td>Lamp</td>
<td>Blue</td>
</tr>
Ect...
</tbody>
</table>
<script type="text/javascript">
var table = document.getElementById("myTbl");
var thead = table.getElementsByTagName("thead")[0];
var tbody = table.getElementsByTagName("tbody")[0];
tbody.onclick = function (e) {
e = e || window.event;
var td = e.target || e.srcElement;
//so must be no other elements inside the td
var row = td.parentNode;
alert('Row is ' + (row.rowIndex - 1))
if (this.lst&&this.lst!=row){
this.lst.className='';
}
row.className = row.className==="highlighted" ? "" : "highlighted";
this.lst=row;
}
thead.onclick = function (e) {
e = e || window.event;
var th = e.target || e.srcElement;
//so must be no other elements in the th
alert(th.innerHTML);
}
</script>
Something like
function goToRow('2')
To select row 2.
Need help please
You could add the count as the ID for each TR.
See below:
<table id="myTbl">
<thead>
<tr id="tr0">
<th>ID</th>
<th>CreatedDate</th>
<th>Name</th>
<th>Colour</th>
</tr>
</thead>
<tbody>
<tr id="tr1">
<td>DFRF</td>
<td>05/03/2010</td>
<td>Lamp</td>
<td>Blue</td>
</tr>
Then use this JavaScript:
function goToRow(where)
{
document.getElementById("tr"+where+"").style.color="white";
document.getElementById("tr"+where+"").style.backgroundColor="gray";
}
Hope that helps