Targeting Classes in Table Row - javascript

The code:
var table = document.getElementById('some-table');
var row = table.rows;
alert(row.length); // Returns number of rows
// Function to hide class on specific row when some action is performed
function someFunc(i) {
var elementToTarget = row[i].getElementsByClassName('some-class');
var otherElementToTarget = row[i].getElementsByClassName('some-other-class');
elementToTarget.style.display="none"; // Returns "elementToTarget.style
// is undefined"
otherElementToTarget.style.display="inline"; // Returns undefined
}
Basic table layout:
<table>
<tr>
<td>
<div class="some-class"></div>
<div class="some-other-class"></div>
</td>
</tr>
</table>
What I want to do: When a user triggers someFunc(), it hides some-class and displays some-other-class. But it only hides some-class for that particular row. Not all of the rows.
My Problem: It tells me that the elements in that row are undefined and I cannot perform any actions on them. It's very likely that I'm targetting those classes improperly.
Hopefully, I've been clear enough. If you need more clarification let me know.
Edit: There may not always be 'some-other-class' in the row. That's why I can't just target one of the divs. I need to know their row.

I'd refer you to the getElementsByClassName function's API. https://developer.mozilla.org/en-US/docs/Web/API/document.getElementsByName
Also, notice the name - Element*s*. It returns a list. And your function should treat it accordingly. so, e.g:
var elementToTarget = row[i].getElementsByClassName('some-class')[0];
var otherElementToTarget = row[i].getElementsByClassName('some-other-class')[0];
Check out this fiddle: http://jsfiddle.net/YD78S/

Related

Is there way to parse tr returned by 'this'?

Each row of my table has a button at the end of the row, which has an addEventListener like this,
button.addEventListener ("click", function() {
deleteSummary(this);
});
function deleteSummary(oButton)
{
console.log(oButton.parentNode.parentNode.innerHTML)
}
the console.log shows like this,
<td>966</td><td>TypeA</td><td>1234</td><td>10,000</td><td>9,861</td><td>139</td><td>2021-01-02</td><td>3</td><td>7</td><td>8</td><td>7</td><td>89</td><td>9</td><td>8</td><td>7</td><td>1</td><td><button>delete</button></td>
But I have no idea how to parse(?) it.
I always found answers you use document.getElementById() when googling.
Thanks
You should not aim to parse HTML. You have access to the DOM, so stick with that. You already found the tr element successfully, and then you can for instance use its cells property to get access to all the td elements, and you could map that list of cells to their text content. That way you get a standard array with all the cell texts of that particular row.
let buttons = document.querySelectorAll("td>button");
for (let button of buttons) {
// Your code:
button.addEventListener ("click", function() {
deleteSummary(this);
});
}
function deleteSummary(oButton) {
let tr = oButton.parentNode.parentNode;
let data = Array.from(tr.cells, cell => cell.textContent);
data.pop(); // Optional: get rid of the column with the delete button
console.log(data);
}
<table>
<tr>
<td>966</td>
<td>TypeA</td>
<td>1234</td>
<td>10,000</td>
<td>2021-01-02</td>
<td><button>delete</button></td>
</tr>
<tr>
<td>123</td>
<td>TypeB</td>
<td>9988</td>
<td>29,999</td>
<td>2020-09-20</td>
<td><button>delete</button></td>
</tr>
</table>

How to update the row indexes of a dynamic table when a row is deleted? [duplicate]

I'm working on making a dynamic HTML table using jQuery. In a table, my user has two interactions:
Append a row
Remove a specific row
The problem with numbering the rows is that if a user removes a specific row, all of the rows following that row need to be renumbered. I would have to select all rows following the removed row and subtract their number by 1.
Is there a better way to go about this?
EDIT: Here's a JSFiddle demonstrating the problem: http://jsfiddle.net/LNXae/2/
I'm aware that an ordered-list would automatically renumber my rows, but I'd rather use a table since the example I'm giving now is pretty boiled-down.
http://jsfiddle.net/mblase75/LNXae/1/
First, wrap the counter number in a <span> with a class for easy finding later:
$new_row.children('td').prepend('Row #<span class="num">' + ($new_row.index() + 1) + "</span>");
Then update all these spans with an .each loop after you remove the desired row. The first argument passed into .each's callback function is a zero-based index number, and the second is the HTML element:
var $row = $(this).closest('tr'),
$table = $row.closest('table');
$row.remove();
$table.find('tr').each(function(i, v) {
$(v).find('span.num').text(i + 1);
});
After the user has appended a row, or deleted one, you just need to iterate over the "number" cells. If we assume that you have a <td> element, we:
1) give them a nice ID, e.g. row_0, row_1, etc...
2) write a function to iterate over them:
function updateRows(){
$('[id*="row_"]').each(function(index){
$(this).html(index + 1); // add +1 to prevent 0 index.
};
};
I have written a jquery plugin which does exactly this, and you shouldnt need to "number" the rows per-se. All you need to do when deleting a row is to pass the index of the row being deleted.
eg, if you have a delete button in a row:
<table>
<tr>
<td> <input type="button" class="delete" value="delete this row" /></td>
</tr>
</table>
The jQuery might look like
$('.delete').click(function(){
var index = $(this).parents('tr').index();
// tell your plugin to delete row "index"
});
The method from my plugin which does this looks something like:
removeRow: function (index) {
return this.each(function () {
var $this = $(this);
var $tbody = $('tbody', $this);
var $tr = $('tr', $tbody).eq(index);
$this.trigger('rowRemoved', [$tr]);
$tr.remove();
});
}

Javascript placing table rows between rows with greater and smaller ID

I'm building a system which outputs a list of cars on a screen(in a table element). The page loads the updates automatically with an HTTP call to the server.
Every car has an ID, a status and some irrelevant things.
Now when the user loads the page, the cars without the statuses 'maintenance' and 'wrecked' are shown and every five seconds new JSON data will be loaded from the server. If there comes a car out of the maintenance this one should be added to the table. The table is sorted by the car id and here comes the problem.
I have written a bit of pseudo code to clarify my problem:
if (row_with_greater_id_exits && row_with_lower_id_exists) {
place_row_between_firstRowWithGreaterId_and_FirstRowWithLowerId();
} else if (is_row_with_greater_id) {
jQuery('table#cars tbody').append(generatedHtml);
} else if (is_row_with_lower_id) {
jQuery('table#cars tbody').prepend(generatedHtml);
}
The problem is I don't know how to find the first row with a greater id or the first row with a smaller ID. The ID's are not always succeeding because some cars are wrecked and have the status wrecked.
I hope someone here has had a similar problem and can help me on my way to the solution.
Many thanks in advance!
You need to loop over the rows, and compare the ids. When your new row has and ID less than the current row in the loop, insert the new row before the current row, and break the loop.
rows.each(function(i, el) {
if (+newrow.id < +el.id) {
$(el).before(newrow);
return false;
}
})
if (!newrow.parentNode)
rows.parent().append(newrow);
This code assumes rows is a jQuery object that has a collection of all the rows, and newrow is a DOM element representing the new row.
Also assumes that the IDs are simple numbers. Note that numeric IDs are only valid in HTML5.
Personally, I'd just use the native API for this:
var tbody = document.querySelector("tbody");
tbody.insertBefore(newrow, [].reduce.call(tbody.rows, function(bef, el) {
return bef || +newrow.id > +el.id ? bef : el;
}, null));
No need to test for the isFirstLoad. When the tbody is empty, it'll still work. But you'll need a .reduce() shim for older browsers.
I have this: id="car-1" data-id="1"
I'll assume that data attribute is on the tr elements. Obviously you can adapt the following if it is on a cell within a row.
Loop through the table checking each row's id, and insert the new row immediately before the first row that has an id greater than the new one:
// assume newId is the new ID, somehow set from your JSON
var rowInserted = false;
jQuery('#invoices-outstanding tbody tr').each(function() {
var $row = $(this);
if (+$row.attr("data-id") > newId) {
$row.before(generatedHtml);
rowInserted = true;
// break out of each loop
return false;
}
});
if (!rowInserted)
jQuery('#invoices-outstanding tbody').append(generatedHtml);

Jquery, selection several TRs in a table

I have a html table which has several rows - lets say 17 for this example. On row 2, 9 and 15 I have some BOLD text which are basically headers for the rows after it. I've used the following code to add an IMAGE after each header:
$("#tblResults tr.lGreyBG td span.gridTXT b").each (function(index) {
$(this).after(" <img class='ChartButton' id='c"+ index +"'src='Images//chart_bar.png' alt='Chart' width='20' />");
});
I also have the following bit of code which binds a click event to each of the chart buttons.
$("img.ChartButton").click(function(){
alert ($(this).attr("id")); // THIS LINE WILL BE REPLACED
});
At the moment, it simply displays the ID of the chart button. What I need to do is replace the alert to pull back the rows afters the header row that was clicked, upto the next header row, of until the end of the table, (whichever comes first). So if the first button was clicked then rows 3 to 8 will be pulled back. Once I have these I can then iterate through each of the TD cells to look at the data in the table.
Many thanks for any help on what "selectors" I need to use to pull back the correct rows. Also note that this needs to be dynamic as other tables will have different number of rows.
Thanks
H
If there is a set of rows that belong together my first instinct would be to declare classes that help me select all of them at once e.g.
<tr class="group-1"> ... </tr>
<tr class="group-1"> ... </tr>
<tr class="group-2"> ... </tr>
<tr class="group-2"> ... </tr>
...
Or multiple theads and tbodies as Tomalak suggests.
If this is not possible and you want to do this using jQuery you can select all the rows after the header using nextAll(). You'll just have to filter out all rows that are after the next heading.
var nextBlockAndTheRest = $(this). // create jQuery object out of this img
closest("tr"). // find the parent tr
nextAll("tr.lGreyBg"). // find all next lGreyBg rows
first("td span.gridTXT b"). // find the first with b
nextAll(). // select all following rows
andSelf(); // add the row with b
var thisBlock = $(this). // create jQuery object out of the img
closest("tr"). // find the parent tr
nextUntil("td span.gridTXT b"). // select everything after the tr
andSelf(). // add the current block heading
not(nextBlockAndTheRest); // remove all the rest of the rows
jsFiddle
// notice that use after() directly, without each()
$("#tblResults tr.lGreyBG td span.gridTXT b").after(function (index) {
return "<img class='ChartButton' id='c"+ index +"'src='Images//chart_bar.png' alt='Chart' width='20' />";
});
$("#tblResults").delegate("img.ChartButton", "click", function () {
var currentRows = $(this).closest("tr").nextUntil("tr:has(span.gridTXT b)");
});
BTW: You definitely should think about a more semantic markup using multiple <thead> and <tbody> tags if your table has multiple heads and bodies.
$("#tblResults thead span.gridTXT b").after(function (index) {
return "<img class='ChartButton' id='c"+ index +"'src='Images//chart_bar.png' alt='Chart' width='20' />";
});
$("#tblResults").delegate("img.ChartButton", "click", function () {
var currentRows = $(this).closest("thead").next("tbody").find("tr");
});
Edit: Changed answer to use nextUntil().

get values from adjacent table rows

i have a function to handle click of clickedcell. I want to exctract value of sibling cell with class "desired". how exactly to specify?
<tr>
<td class="desired">someValue</td>
<td><span "clickedcell"></span></td>
<td></td>
/tr>
$("span.clickedcell").click(function() {
var desired = $(this).closest(".desired").text();
...
});
or more simply:
$("span.clickedcell").click(function() {
var desired = $(this).parent().prev().text();
...
});
Also, the selector changes if you want to click anywhere in the cell:
$("td:has(span.clickedcell)").click(function() {
var desired = $(this).prev().text(); // OR
var desired2 = $(this).closest(".desired").text();
...
});
This can change depending on the nature of the relationship from clickedcell to desired. For example, the second example assumes desired is always the previous sibling. If there can be intervening siblings or it can be after then obviously the traversal needs to change to reflect that.
$(".clickedcell").click(function(){
$(this).closest("td").siblings(".desired").text();
});
Try YUI's DOM collection
YAHOO.util.Dom.getNextSibling(curTD);

Categories

Resources