This question already has answers here:
Adding a table row in jQuery
(42 answers)
How can I clone a table row using jQuery?
(1 answer)
Closed 2 years ago.
I wonder whether I can insert rows in html talbe by clicking them.
For example when I prepare this table like below, and by clicking them
<table>
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
My desired result is like this.
And I would like to know how to add any rows by clicking
<table>
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
.
.
.
.
</tbody>
</table>
If someone has opinion, please let me know.
Thanks
table {
border-collapse:collapse;}
td {
border:solid black 1px;
transition-duration:0.5s;
padding: 5px}
<table>
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
You could do it like this:
$(document).ready(function() {
$("table").on( "click", "tr", function() {
$("table").append($(this).clone());
});
});
Note that it's necessary to pass the event from a parent element that's already there when the page is initially loaded - table - to all tr-elements using on().
jQuery on()
If you simply want to create new tr elements and add them to the table when it's clicked, you could simply create a click event handler to do so. For example:
// Store DOM elements in some variables
const [tbodyEl] = document.querySelector('table').children;
const [trEl] = tbodyEl.children;
// Create an event handler function
const sppendAdditionalRowToTable = e => {
const newTrEl = document.createElement('tr');
for (let i = 0; i < 3; i += 1) {
newTrEl.appendChild(document.createElement('td'));
}
tbodyEl.appendChild(newTrEl);
};
// Call handler function on click event
tbodyEl.addEventListener('click', sppendAdditionalRowToTable);
table {
border-collapse: collapse;
}
td {
border: solid black 1px;
transition-duration: 0.5s;
padding: 5px
}
<table>
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
This works:
$( document ).ready(function() {
$('#tableID').on( "click", "tr", function() {
$("tbody").append("<tr><td>0</td><td>1</td><td>2</td></tr>");
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tableID">
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
Related
I started using jQuery around a week ago and I wanted to make something like a search from an existing table.
When calling text() from any row it shows and empty string '' making it impossible to compare the searched string to the existing ones in the table.
For example, the following code returns 4 instances of ''. How can I fix this?
$(document).ready(() => {
$('#test tr').filter(() => {
console.log($(this).text());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<table>
<tbody id="test">
<tr>
<td>example</td>
<td>1</td>
</tr>
<tr>
<td>example</td>
<td>2</td>
</tr>
<tr>
<td>example</td>
<td>3</td>
</tr>
<tr>
<td>example</td>
<td>4</td>
</tr>
</tbody>
</table>
There's two problems in your code. Firstly you're using an arrow function so the this keyword will point to the outer context, not the tr element within the iteration. To fix this use an anonymous function, or receive the tr as the argument to the arrow function. I've done the latter in the example below.
The second issue is that you're using filter() as an iterator, which is not correct. filter() should be used to reduce a set of elements within a jQuery object. As you want to loop in this case, you should just use each() instead.
jQuery($ => {
$('#test tr').each((i, tr) => {
console.log($(tr).text().trim());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<table>
<tbody id="test">
<tr>
<td>example</td>
<td>1</td>
</tr>
<tr>
<td>example</td>
<td>2</td>
</tr>
<tr>
<td>example</td>
<td>3</td>
</tr>
<tr>
<td>example</td>
<td>4</td>
</tr>
</tbody>
</table>
I have created HTML markup using Javascript now I want to remove that element when clicked, but its not working
if (tBody) {
return (
`<tr class="tr1">
<th class="th1"> Category Name </th>
<th class="th1">Delete </th>
</tr>` +
getdata.data
.map(function (wizard) {
return `<tr class="td1"> <td class=".th1"> ${wizard.categoryName}</td>
<td class="td1"><a class="delClass" onclick="removeCat()" data-remove="${JSON.stringify(wizard._id)}" href="#">Delete</a></td>
</tr>`;
})
.join('')
);
Now I want to remove the above elements when clicked but I use getElementsByClassName and other methods but its not working
Error message and code images
new images**********
enter image description here
the html is rendered dynamically
here is the picture
data-remove image here********
You can use .closest() to find the tr and remove it:
function removeCat(e) {
e.closest('tr').remove()
};
<table>
<tr>
<td>1</td>
<td><button onclick="removeCat(this)">-</button>
</tr>
<tr>
<td>2</td>
<td><button onclick="removeCat(this)">-</button>
</tr>
<tr>
<td>3</td>
<td><button onclick="removeCat(this)">-</button>
</tr>
</table>
Beside, I see your delete buttons has class delClass so you can add event listener to this class and avoid inline script. For example:
var elements = document.getElementsByClassName("delClass");
var removeCat = function() {
console.log(this.dataset.remove)
this.closest('tr').remove();
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', removeCat, false);
}
<table>
<tr>
<td>1</td>
<td><button class="delClass" data-remove="1">-</button>
</tr>
<tr>
<td>2</td>
<td><button class="delClass" data-remove="2">-</button>
</tr>
<tr>
<td>3</td>
<td><button class="delClass" data-remove="3">-</button>
</tr>
</table>
You use a query selector and the remove method:
tBody.querySelectorAll('tr').forEach(tr => tr.remove());
Or if your table has other rows you don't want to delete, then you must have a way of targeting those exactly. Either give them some special class, or maybe you can use the ones you've already given:
tBody.querySelectorAll('.tr1, .td1').forEach(tr => tr.remove());
I've hardly used javascript and I'm stuck:
I've got a table with id JamTable
I'm trying to write some JS that will get me an array of each <td> value for any row clicked on, so that I can present it in a popup, wing it back to the server via POST request using an ajax call and then update the elements on the table so no postback is required - but so far I can't even get an array populated.
I've got:
$(document).ready(function () {
// Get all table row elements <tr> in table 'JamTable' into var 'tr'
var tr = $('#JamTable').find('tr');
// Bind a 'click' event for each of those <tr> row elements
tr.bind('click', function (e) {
// so that when a row is clicked:
var r = $(this).closest('tr').row;
var myArray = new Array(r.cells);
for (var c = 0, col; col = r.cells[c]; c++) {
alert(col.text)
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="JamTable">
<tbody>
<tr>
<td>1</td>
<td>JAM</td>
<td>0.004</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>0.24</td>
</tr>
<tr>
<td>9</td>
<td>Nasty Simon</td>
<td>94.3</td>
</tr>
</tbody>
</table>
Yeah I'm totally lost when it comes to JS
Using proper event-delegation is key to success in such scenarios. Catching "click" events on rows is guaranteed to work, even with dynamically-added rows (which were added to the DOM after the event listener was defined)
Breakdown (see comments):
const tableElm = document.querySelector('table')
// listen to "click" event anywhere on the <table>
tableElm.addEventListener('click', onTableClick)
function onTableClick(e){
// event delegation
const rowElm = e.target.closest('tr')
// traverse each child of the row (HTMLCollection). map the text value into an Array
// https://stackoverflow.com/a/34250397/104380
const values = rowElm ? [...rowElm.children].map(td => td.innerText) : []
// print result
console.clear()
console.log( values )
}
<table>
<tbody>
<tr>
<td>1</td>
<td>JAM</td>
<td>0.004</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>0.24</td>
</tr>
<tr>
<td>9</td>
<td>Nasty Simon</td>
<td>94.3</td>
</tr>
</tbody>
</table>
You should probably also have some unique id on the <tr> if you are sending data back to the server, it might need to know to which row it belongs to
You can delegate the event from tr. On click of it get the children. Using Array.from will create an array of td. Using map to iterate that and get the text from the td
$("#JamTable").on('click', 'tr', function(e) {
let k = Array.from($(this).children()).map((item) => {
return item.innerHTML;
})
console.log(k)
})
td {
border: 1px solid green;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id='JamTable'>
<tbody>
<tr>
<td>1</td>
<td>JAM</td>
<td>0.004</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>0.24</td>
</tr>
<tr>
<td>9</td>
<td>Nasty Simon</td>
<td>94.3</td>
</tr>
</tbody>
</table>
You don't need jquery for that.
You may use querySelectorAll to get the trs and simply children on the tr node to get the tds
const trs = [...document.querySelectorAll('tr')]
trs.forEach(tr => tr.addEventListener('click', e => {
// whenever it is clicked, get its tds
const values = [...tr.children].map(td => td.innerText)
console.log('click', values)
}, false))
<table>
<tbody>
<tr>
<td>1</td>
<td>JAM</td>
<td>0.004</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>0.24</td>
</tr>
<tr>
<td>9</td>
<td>Nasty Simon</td>
<td>94.3</td>
</tr>
</tbody>
</table>
As #vsync suggested, better to use event delegation in case you have a lot of rows to avoid binding several clicks. This also allows to add more rows later on without to have to bind more click handler
edit2 still thx to #vsync, avoid using onclick and prefer addEventListener to avoid overriding existing events
const table = document.querySelector('table')
table.addEventListener('click', e => {
if (e.target.nodeName !== 'TD') { return }
const values = [...e.target.parentNode.children].map(c => c.innerText)
console.log(values)
}, false)
<table>
<tbody>
<tr>
<td>1</td>
<td>JAM</td>
<td>0.004</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>0.24</td>
</tr>
<tr>
<td>9</td>
<td>Nasty Simon</td>
<td>94.3</td>
</tr>
</tbody>
</table>
$('#JamTable tbody tr').click(function () {
var arr = [];
$($(this).children('td')).each(function (index, val) {
arr.push(val.innerText);
});
console.log(arr);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="JamTable">
<tbody>
<tr>
<td>1</td>
<td>JAM</td>
<td>0.004</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>0.24</td>
</tr>
<tr>
<td>9</td>
<td>Nasty Simon</td>
<td>94.3</td>
</tr>
</tbody>
</table>
I want to remove the TR if its 2nd TD value is similar to another TRs TD value and it's last TD value shouldn't be HIT. And the another scenario is if I have 3 TRs with the same data then 2 of them should be removed and 1 should remain there.
Example:
<table>
<tr>
<td>ID</td>
<td>Ref No</td>
<td>Name</td>
<td>Result</td>
</tr>
<tr>
<td>1</td>
<td>1121</td>
<td>Joseph</td>
<td>CLEAR</td>
</tr>
<tr>
<td>2</td>
<td>1122</td>
<td>Mike</td>
<td>CLEAR</td>
</tr>
<tr>
<td>3</td>
<td>1122</td>
<td>Mike</td>
<td>CLEAR</td>
</tr>
<tr>
<td>4</td>
<td>1122</td>
<td>Mike</td>
<td>HIT</td>
</tr>
<tr>
<td>5</td>
<td>1123</td>
<td>Jim</td>
<td>HIT</td>
</tr>
<tr>
<td>6</td>
<td>1124</td>
<td>James</td>
<td>CLEAR</td>
</tr>
<tr>
<td>7</td>
<td>1124</td>
<td>James</td>
<td>CLEAR</td>
</tr>
<tr>
<td>8</td>
<td>1124</td>
<td>James</td>
<td>CLEAR</td>
</tr>
</table>
What I want:
<table>
<tr>
<td>ID</td>
<td>Ref No</td>
<td>Name</td>
<td>Result</td>
</tr>
<tr>
<td>1</td>
<td>1121</td>
<td>Joseph</td>
<td>CLEAR</td>
</tr>
<tr>
<td>4</td>
<td>1122</td>
<td>Mike</td>
<td>HIT</td>
</tr>
<tr>
<td>5</td>
<td>1123</td>
<td>Jim</td>
<td>HIT</td>
</tr>
<tr>
<td>6</td>
<td>1124</td>
<td>James</td>
<td>CLEAR</td>
</tr>
</table>
Can anybody tell me how to achieve this task?
Any help would be highly appreciated.
So i made this clumsy answer for you. You can check it out in the fiddle here.
EDIT: after some discussion about what should the behaviour be, i updated the fiddle. so now it adds the check if there are any fields in the duplicates that have a "HIT" value in fourth column it will keep the first row with HIT value, otherwise it will keep the first value for each unique second column value.
I am sure there is a better/simpler/more effective way to do this with jQuery, but that is what I came up with. The basic algorithm is this: get all rows and iterate. For each row: find the value in second td (column), check all subsequent rows, fetch the value in second column there and compare them. if they are the same, remove the duplicate row from DOM.
//get the table rows, this should be done with a different selector if there are more tables e.g. with class or id...
$tableRows = $("tr");
//iterate over all elements (rows)
$tableRows.each(function(index, element) {
var $element = $(element);
//get the value of the current element
var currentRowValue = $element.find("td:nth-child(2)").text();
//check all elements that come after the current element if the value matches, if so, remove the matching element
for (var i = index + 1; i < $tableRows.length; i++) {
var $rowToCompare = $($tableRows[i]);
var valueToCompare = $rowToCompare.find("td:nth-child(2)").text();
if(valueToCompare === currentRowValue) {
//remove the duplicate from dom
//if the second row (the duplicate) has 4th column of "HIT" then keep the second row and remove the first row
var duplicateRowFourthColumnVal = $rowToCompare.find("td:nth-child(4)").text();
if(duplicateRowFourthColumnVal == "HIT") {
$element.remove();
}
else {
$rowToCompare.remove();
}
}
}
});`
I have an HTML table created with dynamic data and cannot predict the number of rows in it. What I want to do is to get the value of a cell when a row is clicked. I know to use td onclick but I do not know how to access the cell value in the Javascript function.
The value of the cell is actually the index of a record and it is hidden in the table. After the record key is located I can retrieve the whole record from db.
How to get the cell value if I do not know the row index and column index of the table that I clicked?
Don't use in-line JavaScript, separate your behaviour from your data and it gets much easier to handle. I'd suggest the following:
var table = document.getElementById('tableID'),
cells = table.getElementsByTagName('td');
for (var i=0,len=cells.length; i<len; i++){
cells[i].onclick = function(){
console.log(this.innerHTML);
/* if you know it's going to be numeric:
console.log(parseInt(this.innerHTML),10);
*/
}
}
var table = document.getElementById('tableID'),
cells = table.getElementsByTagName('td');
for (var i = 0, len = cells.length; i < len; i++) {
cells[i].onclick = function() {
console.log(this.innerHTML);
};
}
th,
td {
border: 1px solid #000;
padding: 0.2em 0.3em 0.1em 0.3em;
}
<table id="tableID">
<thead>
<tr>
<th>Column heading 1</th>
<th>Column heading 2</th>
<th>Column heading 3</th>
<th>Column heading 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>43</td>
<td>23</td>
<td>89</td>
<td>5</td>
</tr>
<tr>
<td>4</td>
<td>3</td>
<td>0</td>
<td>98</td>
</tr>
<tr>
<td>10</td>
<td>32</td>
<td>7</td>
<td>2</td>
</tr>
</tbody>
</table>
JS Fiddle proof-of-concept.
A revised approach, in response to the comment (below):
You're missing a semicolon. Also, don't make functions within a loop.
This revision binds a (single) named function as the click event-handler of the multiple <td> elements, and avoids the unnecessary overhead of creating multiple anonymous functions within a loop (which is poor practice due to repetition and the impact on performance, due to memory usage):
function logText() {
// 'this' is automatically passed to the named
// function via the use of addEventListener()
// (later):
console.log(this.textContent);
}
// using a CSS Selector, with document.querySelectorAll()
// to get a NodeList of <td> elements within the #tableID element:
var cells = document.querySelectorAll('#tableID td');
// iterating over the array-like NodeList, using
// Array.prototype.forEach() and Function.prototype.call():
Array.prototype.forEach.call(cells, function(td) {
// the first argument of the anonymous function (here: 'td')
// is the element of the array over which we're iterating.
// adding an event-handler (the function logText) to handle
// the click events on the <td> elements:
td.addEventListener('click', logText);
});
function logText() {
console.log(this.textContent);
}
var cells = document.querySelectorAll('#tableID td');
Array.prototype.forEach.call(cells, function(td) {
td.addEventListener('click', logText);
});
th,
td {
border: 1px solid #000;
padding: 0.2em 0.3em 0.1em 0.3em;
}
<table id="tableID">
<thead>
<tr>
<th>Column heading 1</th>
<th>Column heading 2</th>
<th>Column heading 3</th>
<th>Column heading 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>43</td>
<td>23</td>
<td>89</td>
<td>5</td>
</tr>
<tr>
<td>4</td>
<td>3</td>
<td>0</td>
<td>98</td>
</tr>
<tr>
<td>10</td>
<td>32</td>
<td>7</td>
<td>2</td>
</tr>
</tbody>
</table>
JS Fiddle proof-of-concept.
References:
Array.prototype.forEach().
document.getElementById().
document.getElementsByTagName().
document.querySelectorAll().
EventTarget.addEventListener().
Function.prototype.call().
This is my solution
var cells = Array.prototype.slice.call(document.getElementById("tableI").getElementsByTagName("td"));
for(var i in cells){
console.log("My contents is \"" + cells[i].innerHTML + "\"");
}
You can use:
<td onclick='javascript:someFunc(this);'></td>
With passing this you can access the DOM object via your function parameters.
I gave the table an id so I could find it. On onload (when the page is loaded by the browser), I set onclick event handlers to all rows of the table. Those handlers alert the content of the first cell.
<!DOCTYPE html>
<html>
<head>
<script>
var p = {
onload: function() {
var rows = document.getElementById("mytable").rows;
for(var i = 0, ceiling = rows.length; i < ceiling; i++) {
rows[i].onclick = function() {
alert(this.cells[0].innerHTML);
}
}
}
};
</script>
</head>
<body onload="p.onload()">
<table id="mytable">
<tr>
<td>0</td>
<td>row 1 cell 2</td>
</tr>
<tr>
<td>1</td>
<td>row 2 cell 2</td>
</tr>
</table>
</body>
</html>
.......................
<head>
<title>Search students by courses/professors</title>
<script type="text/javascript">
function ChangeColor(tableRow, highLight)
{
if (highLight){
tableRow.style.backgroundColor = '00CCCC';
}
else{
tableRow.style.backgroundColor = 'white';
}
}
function DoNav(theUrl)
{
document.location.href = theUrl;
}
</script>
</head>
<body>
<table id = "c" width="180" border="1" cellpadding="0" cellspacing="0">
<% for (Course cs : courses){ %>
<tr onmouseover="ChangeColor(this, true);"
onmouseout="ChangeColor(this, false);"
onclick="DoNav('http://localhost:8080/Mydata/ComplexSearch/FoundS.jsp?courseId=<%=cs.getCourseId()%>');">
<td name = "title" align = "center"><%= cs.getTitle() %></td>
</tr>
<%}%>
........................
</body>
I wrote the HTML table in JSP.
Course is is a type. For example Course cs, cs= object of type Course which had 2 attributes: id, title.
courses is an ArrayList of Course objects.
The HTML table displays all the courses titles in each cell. So the table has 1 column only:
Course1
Course2
Course3
......
Taking aside:
onclick="DoNav('http://localhost:8080/Mydata/ComplexSearch/FoundS.jsp?courseId=<%=cs.getCourseId()%>');"
This means that after user selects a table cell, for example "Course2", the title of the course- "Course2" will travel to the page where the URL is directing the user: http://localhost:8080/Mydata/ComplexSearch/FoundS.jsp . "Course2" will arrive in FoundS.jsp page. The identifier of "Course2" is courseId. To declare the variable courseId, in which CourseX will be kept, you put a "?" after the URL and next to it the identifier.
It works.