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>
Related
I am trying to get the value of the cell right of the cell where i click.
But right now I get the value of the cell I want, but I can click any cell in that row and get the desired value. But it should only be possible with the first column. So I click the any cell in the first column and I wanna get it's next neighbour cell value.
document.querySelector("#tableEventListId").addEventListener("click",event => {
let dataTr = event.target.parentNode;
let deleteEventId = dataTr.querySelectorAll("td")[1].innerText;
console.log(deleteEventId);
alert(deleteEventId);
Any help?
You can use nextElementSibling
document.getElementById('table1').onclick = function(event){
//REM: Target
var tElement = event.target;
if(
//REM: Only cells (=<td>)
tElement.tagName === 'TD' &&
//REM: Only first column cells
tElement.parentNode.firstElementChild === tElement
){
//REM: Next Elementsibling of Target or Null
var tNext = tElement.nextElementSibling;
if(tNext){
console.log('TD: ', tElement.textContent);
console.log('Next: ', tElement.nextElementSibling.textContent)
}
}
}
table, td{
border: 1px solid black
}
<table id = 'table1'>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
<tr>
<td>A3</td>
<td>B3</td>
<td>C3</td>
</tr>
</tbody>
</table>
There is no HTML, so I can assume it's something like
<table border="1">
<tr>
<td class="first-column">1.1 (click here)</td>
<td>1.2</td>
<td>1.3</td>
</tr>
<tr>
<td class="first-column">2.1 (click here)</td>
<td>2.2</td>
<td>2.3</td>
</tr>
</table>
According to this HTML, you can try
const firstColumns = document.querySelectorAll(".first-column");
for (let i = 0; i < firstColumns.length; i++) {
firstColumns[i].addEventListener("click", function(event) {
let dataTr = event.target.parentNode;
let deleteEventId = dataTr.querySelectorAll("td")[1].innerText;
console.log(deleteEventId);
alert(deleteEventId);
});
}
Have a look https://jsfiddle.net/vyspiansky/k2toLd8w/
I would recommend you to a an event on every td element of the table. Then use nextElementSibling to get a next cell.
Look code snippet to see the example.
const cells = document.querySelectorAll('#tableEventListId td');
cells.forEach(cell => cell.onclick = function(){
const nextCell = cell.nextElementSibling;
if (nextCell)
alert(nextCell.innerHTML);
})
<table id="tableEventListId">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>11</td>
<td>22</td>
<td>33</td>
<td>44</td>
</tr>
<tr>
<td>111</td>
<td>222</td>
<td>333</td>
<td>444</td>
</tr>
<tr>
<td>1111</td>
<td>2222</td>
<td>3333</td>
<td>4444</td>
</tr>
</table>
If you want it to work only for cells at first column change the selector to #tableEventListId td:first-child.
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>
I have a table with four columns Name, Age, Country and a checkbox. If the checkbox is clicked(true) the name value of the row is showed in a textarea.
I am not really sure how I can realise that.
A row:
<tr>
<th scope="row">1</th>
<td>James</td>
<td>13</td>
<td>France</td>
<td><input type="checkbox"></td>
</tr>
if the checkbox is true the value "James" should be shown in a textarea.
Thank you all.
I believe you need to do this for multiple rows in a table.
First select all the checkboxes with Document.querySelectorAll() to attach the event (click) to all the checkboxes.
The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors.
Inside the event (click) handler function target all the checked checkboxes to loop through them to get the relevant names using Array.prototype.map():
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
Also it is not good practice to mix up th and td inside of the same tr element. You should place th inside of a thead and td inside of tbody element:
var cb = document.querySelectorAll('input[type=checkbox]');
cb.forEach(function(ck){
ck.addEventListener('click', function(el){
var checked = document.querySelectorAll(':checked');
var tArea = document.getElementById('myText');
tArea.value = Array.from(checked).map(c => c.closest('tr').querySelector('td:nth-child(2)').textContent);
//or using spread syntax
//tArea.value = [...checked].map(c => c.closest('tr').querySelector('td:nth-child(2)').textContent);
});
});
table, th, td {
border: 1px solid black;
}
<table>
<thead>
<tr>
<th>Sl</th>
<th>Name</th>
<th>No</th>
<th>Country</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row">1</td>
<td>James</td>
<td>13</td>
<td>France</td>
<td><input type="checkbox"></td>
</tr>
<tr>
<td scope="row">2</td>
<td>John</td>
<td>15</td>
<td>Germany</td>
<td><input type="checkbox"></td>
</tr>
</tbody>
</table>
<textarea id="myText"></textarea>
Try this:
[...document.querySelectorAll("input[type='checkbox']")].forEach(function (v){
v.addEventListener("change", function(){
document.querySelector("textarea").value = (this).checked ? (this).parentElement.parentElement.querySelector("td").innerHTML:'';
})});
<table>
<tr>
<th scope="row">1</th>
<td>James</td>
<td>13</td>
<td>France</td>
<td><input type="checkbox"></td>
</tr>
<tr>
<th scope="row">1</th>
<td>James</td>
<td>13</td>
<td>France</td>
<td><input type="checkbox"></td>
</tr>
</table>
<textarea></textarea>
Few javascript lines would be ok for you need.
let input = document.querySelector('input');
input.addEventListener('change', e=> {
if(e.target.checked == true){
// retreive tags
let name = document.querySelector('.name');
let textarea = document.querySelector('.textarea');
// insert data
textarea.innerText += name.innerText
}
})
<table>
<tr>
<th scope="row">1</th>
<td class="name">James</td>
<td>13</td>
<td>France</td>
<td><input type="checkbox"></td>
</tr>
</table>
<textarea class="textarea"></textarea>
Since your table can have multiple rows, where each can have the checkbox set or not, the textarea could get zero, one or more names.
So you would need to listen the change event, and then iterate the rows to collect the names, to finally set the value of the textarea:
let textarea = document.querySelector("textarea");
let table = document.querySelector("table");
table.addEventListener("change", function (e) {
let names = [];
for (let row of table.rows) {
if (row.querySelector("input[type=checkbox]").checked) {
names.push( row.children[1].textContent);
}
}
textarea.value = names.join("\n");
});
<table><tr>
<th scope="row">1</th>
<td>James</td>
<td>13</td>
<td>France</td>
<td><input type="checkbox"></td>
</tr><tr>
<th scope="row">2</th>
<td>Lucy</td>
<td>14</td>
<td>Germany</td>
<td><input type="checkbox"></td>
</tr></table>
<textarea></textarea>
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 here HTML Code:
<div class="actResult" style="border: solid">
<table>
<tbody>
<tr>
<td>Order Number</td>
<td>1</td>
</tr>
<tr>
<td>Customer Number</td>
<td>3</td>
</tr>
<tr>
<td>Complaint Code</td>
<td>b</td>
</tr>
<tr>
<td>Receivable Receipt Number</td>
<td>5</td>
</tr>
<tr>
<td>Date Called</td>
<td>2014-03-19</td>
</tr>
<tr>
<td>Scheduled Day Of Checkup</td>
<td>2014-03-19</td>
</tr>
<tr>
<td>Scheduled Day Of Service</td>
<td>2014-03-21</td>
</tr>
<tr>
<td>Checkup Status</td>
<td>Y</td>
</tr>
<tr>
<td>Service Status</td>
<td>N</td>
</tr>
<tr>
<td>Technician Number Checkup</td>
<td>3</td>
</tr>
<tr>
<td>Technician Number Service</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
I want to get the values of the tags and put them into an array with the a structure like array("first td" => "second td"), so for this case the array would be array("Order Number" => "1", "Customer Number" => "3", "Complaint Code" => "b", ...) and so on.
After that, the final array would be sent into a PHP code.
I've been trying to extract some of the values from the HTML using var html = $(this).filter(function( index ){ return $("td", this) }).filter(":odd").text(); and various other combinations of filter(), but it doesn't seem to work for me.
How do I go about doing what I want to do?
jsFiddle Demo
You are going to want to use .each for that and iterate through the rows in the table. For each row, take the first cell (.eq(0)) as the key, and the second cell (.eq(1)) as the value. Place these in a result object.
//object to hold resulting data
var result = {};
//iterate through rows
$('.actResult tr').each(function(){
//get collection of cells
var $tds = $(this).find('td');
//set the key in result to the first cell, and the value to the second cell
result[$tds.eq(0).html()] = $tds.eq(1).text();
});
You can get the rows property of the table element and create an object based on the cells' value:
var rows = document.querySelector('.actResult table').rows,
data = {}, c, l = rows.length, i = 0;
for (; i < l; i++) {
c = rows[i].cells;
data[c[0].innerHTML] = c[1].innerHTML;
}
http://jsfiddle.net/tG8F6/