Get id from html table when clicking an input inside the table - javascript

How can you get the id of a table when you click an input element?
I don't need the rowId etc.
I've tried parentNode.id but I can't seem to get the id.
In the end I'd like to do something like this:
var tabelid = INPUT....parentNode.parentNode.id;
var table = document.getElementById(tabelid);
Example:

How about this:-
Demo
Html
<table id="tblTest">
<tr>
<td>
<input type="text" id="txtTest" onclick="getParent.call(this)" />
</td>
</tr>
</table>
I am using call here so that i get the elements context inside the getParent event callback.
Javascript
function getParent()
{
var parent = this.parentNode;
var tagName = "table";
while (parent) { //Loop through until you find the desired parent tag name
if (parent.tagName && parent .tagName.toLowerCase() == tagName) {
alert(parent .id);
return;
}
else
{
parent = parent .parentNode;
}
}
}
If you are using Jquery:-
in the click event you can just do $(this).closest('table').attr('id')

If you are using jQuery you can use closest to find the closest matching ancestor like so:
var tableID = "";
$(document).ready(function(){
$('input[type="text"]').click(function(e){
tableID = $(this).closest('table').attr('id');
});
]);
Edit:
If you actually want to do something with that table (for instance add a class), you could do the following:
$(document).ready(function(){
$('input[type="text"]').click(function(e){
tableID = $(this).closest('table').addClass('myClass');
});
]);
This simply removes the need to fetch the table ID, store it, and then fetch the table based on it's ID. Since you already found the table in order to get its ID you can just manipulate it right away.

You have to ascend the DOM from TD to TABLE keeping in mind that browsers may inject a TBODY if you haven't specified it. So, your code should look something like this:
var tableCells = document.getElementsByTagName('td'),
cellCount = tableCells.length,
i;
for (i = 0; i < cellCount; i += 1) {
tableCells[i].onclick = function () {
var tableId = getTableId(this);
console.log(tableId);
};
}
function getTableId(node) {
var element = node;
while (element.tagName.toLowerCase() !== 'table') {
element = element.parentNode;
}
return element.id;
}
Check out the demo.

Related

Can't properly delete rows from a dynamically generated table using a button

I have the following code which is supposed to generate rows in a table where each row has its own content and delete button.
<!DOCTYPE html>
<html>
<head>
<title>table</title>
</head>
<body>
<input id="inputText">
<button onclick = "addRow()">Add text</button>
<table id = "table">
</table>
<script>
function addRow(){
var newRow = document.createElement("tr");
var col1 = document.createElement("td");
var col2 = document.createElement("td");
newRow.appendChild(col1);
newRow.appendChild(col2);
var button = document.createElement("button");
button.innerHTML = "delete";
button.onclick = function () {
var index = this.parentNode.parentNode.rowIndex;
document.getElementById("table").deleteRow(index);
}
col1.appendChild(button);
var enteredText = document.getElementById("inputText").value;
col2.innerHTML = enteredText;
document.getElementById("table").appendChild(newRow);
}
</script>
</body>
</html>
The problem is that no matter which delete button I press, it deletes the last row.
I tried using console.log(this.parentNode.parentNode) to see if it returns the right <tr> object, and it indeed does. But for some reason, the attribute rowIndex is -1 no matter what button is pressed; hence only the last row is deleted. Does it mean that each dynamically generated <tr> doesn't know its row index?
You can use HTMLTableElement.insertRow() function instead.
var newRow = document.getElementById("table").insertRow();
// newRow.rowIndex will return you the proper index
Here is a working fiddle
Update
It was a bug in the Webkit layout engine, (that moved to the forked Blink engine as well). This is why it works well in Firefox but not in earlier versions of Chrome (Blink) or Safari (Webkit).
The bug report is here, it's fixed now.
There are numerous way to achieve what you require. Here is another such example that is based on the code that you posted. Hopefully it will give you some further ideas.
(function() {
// create references to static elements, no need to search for them each time
var inputText = document.getElementById("inputText"),
butAdd = document.getElementById("butAdd"),
table = document.getElementById("table");
// a generic function for finding the first parent node, starting at the given node and
// of a given tag type. Retuns document if not found.
function findParent(startNode, tagName) {
var currentNode,
searchTag;
// check we were provided with a node otherwise set the return to document
if (startNode && startNode.nodeType) {
currentNode = startNode;
} else {
currentNode = document;
}
// check we were provided with a string to compare against the tagName of the nodes
if (typeof tagName === 'string') {
searchTag = tagName.toLowerCase();
} else {
currentNode = document;
}
// Keep searching until we find a parent with a mathing tagName or until we get to document
while (currentNode !== document && currentNode.tagName.toLowerCase() !== searchTag) {
currentNode = currentNode.parentNode;
}
// return the match or document
return currentNode;
}
// for deleting the current row in which delete was clicked
function deleteRow(e) {
// find the parent with the matching tagName
var parentTr = findParent(e.target, 'tr');
// did we find it?
if (parentTr !== document) {
// remove it
parentTr.parentNode.removeChild(parentTr);
}
}
// for adding a row to the end of the table
function addRow() {
// create the required elements
var newRow = document.createElement("tr"),
col1 = document.createElement("td"),
col2 = document.createElement("td"),
button = document.createElement("button");
// add some text to the new button
button.appendChild(document.createTextNode("delete"));
// add a click event listener to the delete button
button.addEventListener('click', deleteRow, false);
// append all the required elements
col1.appendChild(button);
col2.appendChild(document.createTextNode(inputText.value));
newRow.appendChild(col1);
newRow.appendChild(col2);
// finally append all the elements to the document
table.appendChild(newRow);
}
// add click event listener to the static Add text button
butAdd.addEventListener('click', addRow, false);
}());
<input id="inputText">
<button id="butAdd">Add text</button>
<table id="table"></table>

How to get the row value on clicking a link

I have a table with 3 rows, each having hrefs. On click of these links, i need to get the entire value of the row where the link is clicked.
Data
Test1_link image_link view-link
Test2_link image_link view-link
the data above are links, on click on any link, its corresponding row value should be rendered.
Can anyone please suggest me on how to achieve that?
Thanks.
You could put a simple script immediately after your table:
<script>
(function (d) {
// Get the table element
var table = function() {
var tables = d.getElementsByTagName('table');
return tables[tables.length - 1];
}();
table.onclick = function (e) {
var target = e.target;
// If an <a> was clicked
if( target.nodeName.toLowerCase() === 'a' ) {
// Find the tr containing that a
var node = target;
while (node.nodeName.toLowerCase() !== 'tr' )
node = node.parentNode;
var tr = node;
// Output the contents of the table cells in that row
var cells = tr.cells;
for (var i = 0; i < cells.length; i++ )
console.log(cells[i].innerHTML);
// Return false to prevent the link from loading
return false;
}
}
})(document)
</script>
JSFiddle
Try this with jQuery http://www.jquery.com.
<table class="js-mytable">
<tr data-id="23" data-something="you've got it!">
<td>
Test Link
</td>
<td>
Image Link
</td>
<td>
View Link
</td>
</tr>
</table>
<script>
//run after document ready event
$(function(){
//all links in table with class js-mytable
$('table.js-mytable').on('click','a',function(){
//var $cell = $(this).parents('td'); //get the parent td of the link
var $row = $(this).parents('tr'); //get the parent tr of the link
//get the html5 data attributes from the row
var id = $row.data('id');
var something = $row.data('something');
//do something with the vars
//alert('Id: '+id+': '+something);
//get the full html <tr>...</tr>
//we need to merge it to a new pseudo html element
//to get the full html with surrounding <tr>
var html = $('<div>').append($row.clone()).html();
alert(html);
return false; //prevent default link action (href)
});
});
</script>
If you need more details, you need to extend your question...
JsFiddle: http://jsfiddle.net/7ud43

How can I reference an element after I have appended it using javascript not jquery

I am doing some basic javascripting and am creating a 3 column table created by javascript sourced from an xml. The table is created by appending all the data in rows via javascript.
The first column has an input checkbox, created via javascript, that if ticked fetches a price from the third column on that row and adds all the prices of the rows selected to give a price total.
The problem I am having is I don't seem to be able to reference the appended information to obtain the information in the related price column (third column).
I have attached both the function I am using to create the table which is working and the function I am using to try and add it up which isnt working.
I found the following two articles Getting access to a jquery element that was just appended to the DOM and How do I refer to an appended item in jQuery? but I am using only javascript not jquery and would like a javascript only solution if possible.
Can you help? - its just the calculateBill function that isn't working as expected.
Thank you in advance
function addSection() {
var section = xmlDoc.getElementsByTagName("section");
for (i=0; i < section.length; i++) {
var sectionName = section[i].getAttribute("name");
var td = document.createElement("td");
td.setAttribute("colspan", "3");
td.setAttribute("class","level");
td.appendChild(document.createTextNode(sectionName));
var tr = document.createElement("tr");
tr.appendChild(td);
tbody.appendChild(tr);
var server = section.item(i).getElementsByTagName("server");
for (j=0; j < server.length; j++) {
var createTR = document.createElement("tr");
var createTD = document.createElement("td");
var createInput = document.createElement("input");
createInput.setAttribute("type", "checkbox");
createInput.setAttribute("id", "checkInput");
createTD.appendChild(createInput);
createTR.appendChild(createTD);
var item = server[j].getElementsByTagName("item")[0].innerHTML;
var createTD2 = document.createElement("td");
var createText = document.createTextNode(item);
createTD2.appendChild(createText);
createTR.appendChild(createTD2);
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
}
}
}
onload = addSection();
function calculateBill() {
var finalBill = 0.0;
var checkBox = document.getElementById("checkInput");
for (i=0; i < checkBox.length; i++) {
if (checkBox[i].checked) {
var parentTR = checkBox[i].parentNode;
var priceTD = parentTR.getElementsByTagName('td')[2];
finalBill += parseFloat(priceTD.firstChild.data);
}
}
return Math.round(finalBill*100.0)/100.0;
}
var button = document.getElementById("button");
button.onClick=document.forms[0].textTotal.value=calculateBill();
When you do x.appendChild(y), y is the DOM node that you are appending. You can reference it via javascript either before or after appending it. You don't have to find it again if you just hang on to the DOM reference.
So, in this piece of code:
var createInput = document.createElement("input");
createInput.setAttribute("type", "checkbox");
createInput.setAttribute("id", "checkInput");
createTD.appendChild(createInput);
createInput is the input element. You can reference it with javascript at any time, either before or after you've inserted it in the DOM.
In this piece of code:
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
You're creating a <td> element and putting a price into it. createTD3 is that particular <td> element.
If you want to be able to find that element sometime in the future long after the block of code has run, then I'd suggest you give it an identifying id or class name such that you can use some sort of DOM query to find it again. For example, you could put a class name on it "price" and then be able to find it again later:
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
createTD3.className = "price";
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
Then, you could find all the price elements again with:
tbody.querySelectorAll(".price");
Assuming tbody is the table where you put all these elements (since that's what you're using in your enclosed code). If the table itself had an id on it like id="mainData", then you could simply use
document.querySelectorAll("#mainData .price")
to get all the price elements.
FYI, here's a handy function that goes up the DOM tree starting from any node and finds the first node that is of a particular tag type:
function findParent(node, tag) {
tag = tag.upperCase();
while (node && node.tagName !== tag) {
node = node.parentNode;
}
return node;
}
// example usage:
var row, priceElement, price;
var checkboxes = document.querySelectorAll(".checkInput");
for (var i = 0; i < checkboxes.length; i++) {
// go up to the parent chain to find out row
row = findParent(checkboxes[i], "tr");
// look in this row for the price
priceElement = row.querySelectorAll(".price")[0];
// parse the price out of the price element
price = parseFloat(priceElement.innerHTML.replace(/^[^\d\.]+/, ""));
// do something here with the price
}

Using variable from .closest() into a selector

I am sure this is something very easy to do, but I'm stuck.
I have multiple forms in a page each one with a "duplicate" button.
The button duplicates a row and put it at the end of a table that is inside of each form. The class of the tables is '.table-add'. So I'm trying to tell the button to find the closest form element and add it to the path on my selector, but it is not working. I know it can work if I put an ID in each form and call for them, but that's not what I want. Thanks for help.
This is my code:
i=0;
$(".duplicate").on("click", function(e) {
i++;
$newID = 'clon'+i;
selectedObj = $($( e.target ).closest("form"));
alert(selectedObj.html()); //**THIS WORKS**
$cloned = '<tr class="'+$newID+'">'+$(selectedObj+' .table-add tr:first').next().html()+'</tr>';
$(selectedObj+' .table-add > tbody:last').append($cloned);
});
Just use this:
var i=0;
$(".duplicate").on("click", function(e) {
i++;
var $newID = 'clon'+i;
var selectedObj = $(e.target).closest("form");
alert(selectedObj.html()); //**THIS WORKS**
var $cloned = '<tr class="'+$newID+'">'+selectedObj.find('.table-add tr:first').next().html()+'</tr>';
selectedObj.find('.table-add > tbody:last').append($cloned);
});
selectedObj is a jQuery object so you can use the .find() function to select .table-add tr:first and '.table-add > tbody:last'.

JavaScript DOM : add an attribute to a <tr>

I want to create a JavaScript function that parses my HTML page, get the Table by it's ID, and after that, add a class attribute to each <tr> as if the line is the 1st, I'll add :
class="line1" to the <tr>
but if the line is the second, I'll add class="line2" to the <tr>
How to do please
If I understand you corrrectly, you want to alternate the class names to get some kind of zebra style right?
var table = document.getElementById('yourTableId');
var rows = table.rows;
for(var i = 0, l = rows.length;i < l; i++) {
rows[i].className = 'class' + ((i%2) + 1);
}
See the HTML DOM Table Object.
its very easy in jquery ... as below :-
$(document).ready(function() {
//for table row
$("tr:even").addClass("AlternateBG1");
$("tr:odd").addClass("AlternateBG2");
})
BUT IN JQUERY...
var table = document.getElementById("yourTableId");
for(var i in table.rows){
table.rows[i].className = 'line'+(i+1).toString();
}
It is easy without jQuery:
oTBody=document.getElementById("tBodyId");
//for (key in oTbody.childNodes) {
for (var nPos=0, nLength = oTbody.childNodes.length; nPos<nLegth; nPos++)}
oRow = oTbody.childNodes[nPos];
if (oRow && oRow.tagName && oRow.tagName.toLowerCase() == "tr") {
oRow.className = (bNormalRow? sClass1:sClass2);
bNormalRow = !bNormalRow;
}
}
With jQuery is really simple, do something like:
var i = 1;
$("#myTable tr").each(function() {
$(this).addClass("line"+i);
i++;
});
Where #myTable is your table id, and $(this) inside each function will be the current element on the cycle.

Categories