I am trying to get the contents of a table cell to change when I click on it. Here is the page source:
function cellClick(c) {
alert(c + " is {" + document.getElementById(c).innerHtml + "}");
document.getElementById(c).innerHtml = "<b>It Works</b>";
alert(c + " is now {" + document.getElementById(c).innerHtml + "}");
}
<table border="1">
<tr>
<td id="Cell1" onclick='cellClick("Cell1")'>
Row 1
</td>
</tr>
<tr>
<td id='Cell2' onclick="cellClick('Cell2')">
Row 2
</td>
</tr>
</table>
Yes, I am aware that the calls in Cell1 and Cell2 switch the single and double-quotes around; I was testing that as well.
Anyway, the first time I click on a cell, its innerHtml value returns "undefined" (instead of "Row 1" or "Row 2"), and after it is set in the function, it shows the set value; when I click on that cell again, the value previously set by the function is there. However, the value on the page itself never changes.
This has been tried on:
Firefox (64-bit) 65.0.1
IE 11.2791 (which won't show the alerts)
Edge 38.14393
but all of them do the same thing - the value is set, but the page doesn't change.
What am I missing?
you have written badly innerHtml innerHTML
Your code does not work because on innerHTML case.
Secondly it will be tedious to add id to every td and pass argument with onclick. So you can use querySelectorAll then iterate this and add click event listener to it. On click get the innerHTML from the target and alert it
function cellClick(c) {
alert(c + " is {" + document.getElementById(c).innerHTML + "}");
document.getElementById(c).innerHtml = "<b>It Works</b>";
alert(c + " is now {" + document.getElementById(c).innerHTML + "}");
}
<table border="1">
<tr>
<td id="Cell1" onclick='cellClick("Cell1")'>
Row 1
</td>
</tr>
<tr>
<td id='Cell2' onclick="cellClick('Cell2')">
Row 2
</td>
</tr>
</table>
document.querySelectorAll('td').forEach((cell) => {
cell.addEventListener('click', (e) => {
let text = e.target.innerHTML.trim();
alert(text)
})
})
<table border="1">
<tr>
<td>
Row 1
</td>
</tr>
<tr>
<td>
Row 2
</td>
</tr>
</table>
document.querySelectorAll('td').forEach((cell) => {
cell.addEventListener('click', function(e) {
let text = this.innerHTML.trim();
alert(text)
})
})
<table border="1">
<tr>
<td>
Row 1
</td>
</tr>
<tr>
<td>
Row 2
</td>
</tr>
</table>
You can take the benefits of event delegation here.
It will create less number of event handlers in memory.
It is scalable and will have better performance.
Here is the code snippet for it.
function cellClick(e) {
if (e.target.tagName === "TD") { //e.target.tagname.toLowerCase() === "td")
console.log(e.target.innerHTML);
e.target.innerHTML = "<b>It Works</b>"
}
}
<table border="1" onclick='cellClick(event)'>
<tr>
<td id="Cell1">
Row 1
</td>
</tr>
<tr>
<td id='Cell2'>
Row 2
</td>
</tr>
</table>
Thanks!
Related
This question already has answers here:
How would you compare jQuery objects?
(4 answers)
jQuery compare two DOM object?
(2 answers)
Closed 5 years ago.
When a cell of the table is clicked, I want to set the content of this cell but only if it is neither in the first row nor in the first column.
$('td').click(function() {
console.log($(this).parents('tr'));
console.log($('#matrix').find('tr:first'));
console.log($('#matrix').find('tr:first') == $(this).parents('tr'));
if ($(this).parents('tr') != $('#matrix').find('tr:first')) {
console.log("is ok");
if ($(this).text() != "x") { // Connect
$(this).text("x");
alert("Connecting " +
$('td:first', $(this).parents('tr')).text() +
" with " +
$('tr:first', $(this).parents('td')).text());
} else { //Disconnect
$(this).text("");
alert("Disconnecting Endpoint " +
$('td:first', $(this).parents('tr')).text() +
" with Endpoint " +
$('tr:first', $(this).parents('td')).text());
};
}; // row/columns > 0 only
}); // click()
td {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="matrix" border="0">
<tr>
<td>Matrix</td>
<td>_name_</td>
<td>_name_</td>
</tr>
<tr>
<td>_name_</td>
<td></td>
<td></td>
</tr>
<tr>
<td>_name_</td>
<td></td>
<td></td>
</tr>
</table>
The Firefox debuging console highlights the exact same elements, but
console.log( $(this).parents('tr') == $('#matrix').find('tr:first') );
always shows false, regardless on which cell I click.
What am I doing wrong?
Maybe two are pointing to the same dom element but object reference would be different. For checking the equality use is() method in jQuery.
console.log( $(this).parents('tr').is($('#matrix').find('tr:first')));
or compare the DOM object by getting using the index or get() method.
console.log( $(this).parents('tr')[0] == $('#matrix').find('tr:first')[0]);
// or
console.log( $(this).parents('tr').get(0) == $('#matrix').find('tr:first').get(0));
UPDATE : Additionally, you can reduce the code by binding click event only for the td elements which need to update the content. Where use :nth-child pseudo-class selector(pure CSS selector) to filter the td.
$('#matrix tr:nth-child(n + 2) td:nth-child(n + 2)').click(function() {
// use text method with callback to update text based on the existing content
$(this).text(function(i, txt) {
return txt === 'x' ? '' : 'x';
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="matrix" border="0">
<tr>
<td>Matrix</td>
<td>_name_</td>
<td>_name_</td>
</tr>
<tr>
<td>_name_</td>
<td></td>
<td></td>
</tr>
<tr>
<td>_name_</td>
<td></td>
<td></td>
</tr>
</table>
You don't need to compare object, You can just use :gt() and :not() along with :first-child selector to exclude first row and first column.
$('#matrix tr:gt(0) td:not(:first-child)').click(function() {
if ($(this).text() != "x") {
$(this).text("x");
} else {
$(this).text("");
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="matrix" border="0">
<tr>
<td>Matrix</td>
<td>_name_</td>
<td>_name_</td>
</tr>
<tr>
<td>_name_</td>
<td></td>
<td></td>
</tr>
<tr>
<td>_name_</td>
<td></td>
<td></td>
</tr>
</table>
Exclude first row and do it so much easier in the selector:
$('tr:not(:first) > :not(:first-child)').click(function() {
//Code
});
I have a table with following rows and cells:
<table id='table1'>
<tr id='row1'>
<th>index</th>
<th>Product</th>
<th>Description</th>
</tr>
<tr id='row2' name='row'>
<td name='index'>1</td>
<td name='product'>Apples</td>
<td name='description'>fruits</td>
</tr>
<tr id='row3' name='row'>
<td name='index'>2</td>
<td name='product'>Bananas</td>
<td name='description'>fruits</td>
</tr>
<tr id='row4' name='row'>
<td name='index'>3</td>
<td name='product'>Carrots</td>
<td name='description'>vegetables</td>
</tr>
<tr id='row5' name='row'>
<td name='index'></td>
<td name='product'></td>
<td name='description'></td>
</tr>
</table>
I need to select the value for the last td with name='index' which is not null. Anyone has any idea how can this be done.
Use the following selector :
$('td[name=index]:not(:empty):last')
For purely educational purposes, here is a non jQuery version:
function getLastNonEmptyCell(tableSelector) {
//Find parent table by selector
var table = document.querySelector(tableSelector)
//Return null if we can't find the table
if(!table){
return null;
}
var cells = table.querySelectorAll("td")
var lastNonEmptyCell = null;
//Iterate each cell in the table
//We can just overwrite lastNonEmptyCell since it's a synchronous operation and the return value will be the lowest item in the DOM
cells.forEach(function(cell) {
//!! is used so it's so if it is not null, undefined, "", 0, false
//This could be changed so it's just cell.innerText.trim() !== ""
if (!!cell.innerText) {
lastNonEmptyCell = cell;
}
})
return lastNonEmptyCell;
}
var cell = getLastNonEmptyCell("#table1")
Edit
As #squint suggested this can be done much more succintly:
function lastNonEmptyCell(tableSelector) {
//Since we want the last cell that has content, we get the last-child where it's not empty. This returns the last row.
var row = document.querySelectorAll(tableSelector + " td:not(:empty):last-child")
//Just grabbing the last cell using the index
return row[row.length - 1]
}
The problem is explained in the picture below. Once clicking the expanding function of "Parameter 1", the level of "Parameter 2" will change as seen in the middle picture. But actually it should remain in the same level.
Any suggestion is highly appreciated. Thanks in advance.
JAVASript
$('.P1').click(function() {
$(this).find('span').text(function(_, value) {
return value == '-' ? '+' : '-'
});
$(this).closest('tr').nextUntil('tr:has(.P2)').slideToggle(100, function() {});
});
$('.Sub-parameter-1').click(function() {
$(this).find('span').text(function(_, value) {
return value == '-' ? '+' : '-'
});
$(this).closest('tr').nextUntil('tr:has(.Sub-parameter-2)').slideToggle(100, function() {});
});
HTML
<table width="200" border="1">
<tr>
<td rowspan="6">Summary </td>
<td colspan="3">
<div align="center">1 st level</div>
</td>
</tr>
<tr>
<td colspan="3">
<div class="P1"><span>-</span>Parameter 1</div>
</td>
</tr>
<tr>
<td rowspan="3">L1</td>
<td colspan="2"><div class="Sub-parameter-1"><span>-</span>Sub parameter (1)</div></td>
</tr>
<tr>
<td>L2</td>
<td>description</td>
</tr>
<tr>
<td colspan="2"><div class="Sub-parameter-2"><span>-</span>Sub parameter (2)</td>
</tr>
<tr>
<td colspan="3">
<div class="P2">Parameter 2</div>
</td>
</tr>
</table>
JSFiddle: https://jsfiddle.net/gft08cmb/4/
EDIT based on answer
When applying the answer to more than 1 row of sub parameter, then the "Parameter 2" still changes its level seen in following link.
https://jsfiddle.net/gka7312L/ or https://jsfiddle.net/p2a2wxfv/1/
Your rowspan attribute in L1 is making problems since it should change from 3 to 2 and back in your case.
This works as you would want I think: https://jsfiddle.net/gft08cmb/6/
You should of course make it dynamic if your data is going to be dynamic also.
So probably a count of rows etc. and then manipulate based on this.
Let me know if you need further help.
I have following table
<table class="data">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>
1 data
</td>
<td>
2 data
</td>
<td>
123456789123
</td>
</tr>
</tbody>
</table>
how can I dynamically scan table and replace only values in third table body td values where information like 123456789123 is stored.
This information should be placed with certain character on certain string location so
<td> 123456789123 </td> should be <td> 12345678*12* </td>
Please find below code block for your need, I have added one specific class to TD for which you want to modify value.
$( document ).ready(function() {
$('.value_td').each(function(key, ele){
// Getting Original Value
var original_val = $(ele).text().trim();
// You can change your logic here to modify text
var new_value = original_val.substr(0, 8) + '*' + original_val.substr(9, 2) + '*';
// Replacing new value
$(ele).text(new_value);
});
});
<table class="data">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>
1 data
</td>
<td>
2 data
</td>
<td class="value_td">
123456789123
</td>
</tr>
</tbody>
</table>
JS Fiddle
To replace the selected texts by indexs, use this:
// replace the 'n'th character of 's' with 't'
function replaceAt(s, n, t) {
return s.substring(0, n) + t + s.substring(n + 1);
}
$('td:nth-of-type(3)').each(function(i, item){
$(this).text($(this).text().trim()); // remove extra spaces
$(this).text(replaceAt($(this).text(), 8, '*')); // replace character in position 8
$(this).text(replaceAt($(this).text(), 11, '*')); // replace character in position 11
});
See the working demo: https://jsfiddle.net/lmgonzalves/6ppo0xp3/
Try this:
$('.data td:nth-child(3n)').text('foo');
This will change every 3rd td’s text inside .data to foo. Here’s a demo: http://jsbin.com/katuwumeyu/1/edit?html,js,output
Let me know if that helps, I’ll gladly adapt my answer in case this isn’t what you need.
You can use jquery ":eq(2)" to track 3rd td position like this:
var el = $('table.data tbody tr td:eq(2)');
el.text(el.text().replace('123456789123','12345678*12*'));
https://jsfiddle.net/v25gu3xk/
or maybe you need to replace char positions:
var el = $('table.data tbody tr td:eq(2)');
var vl = el.text().trim();
el.text(vl.substr(0, 8) + '*' + vl.substr(9, 2) + '*');
https://jsfiddle.net/v25gu3xk/1/
I have a table. see my table structure
<table width="100%" border="1">
<tr>
<td width="2%"><h2># SL NO</h2></td>
<td width="70%"><h2>Name</h2></td>
<td width="15%"><h2>Edit</h2></td>
<td width="13%"><h2>Delete</h2></td>
</tr>
<tr id="id0">
<td >1</td>
<td>XXXXXXX</td>
<td><img src="../images/icon_edit.gif" alt="Edit" /></td>
<td width="13%"><img src="../images/delete_07.png" alt="Delete" onclick="fnDeleteState(0)" /></td>
</tr>
<tr id="id1">
<td>2</td>
<td>XXXXXXX</td>
<td><img src="../images/icon_edit.gif" alt="Edit" /></td>
<td%"><img src="../images/delete_07.png" alt="Delete" onclick="fnDeleteState(1)" /></td>
</tr>
...
....
..
When press on the delete button i need to hide that row I have used this to remove particular row from the table
$("#id" + i).remove();
Its working fine. But the serial number... i's display as wrong. I.e. when I delete second row the serial number with in the third row is still 3 I need to display this s 2 and so on...
I there is any way to do this in jquery
Thanks in advance
function fnDeleteState(i) {
$("#id" + i).remove();
$("tr").each(function (index) { // traverse through all the rows
if(index != 0) { // if the row is not the heading one
$(this).find("td:first").html(index + ""); // set the index number in the first 'td' of the row
}
});
}
If I understand correctly, you need to update the first cell of each row so they display the rank of the row.
You can achieve it by adding a class for each of your content row, for example "contentrow" (to distinguish them from the heading row) and then write a function like this:
function refreshRowIDs(){
$(".contentrow").each(function(index){
$(this).children("td:first").html(index);
});
}
You need to reorder the Serial no. after deletion . You can use something like this :
function reorder(){
var i = 1;
$('#tableid tr').each(function() {
$(this).find("td:first").text(i);
i++;
});
}