How to renumber remaining table rows after .hide() - javascript

The Javascript increments each visible number in these dynamically generated rows of a static table.
The jQuery dutifully hides each row when clicked, but, of course, the numbers don't change. How can I use jQuery to re-number the rows when the visitor is done removing the unwanted lines? I want the user to click 'renumber' to renumber the remaining rows correctly. What I have didn't work :-)
Help is deeply appreciated.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
var keepTrack = 1;
</script>
<table>
<tr><td colspan="2" id="renumber">renumber</td></tr>
<tr id="sWH1">
<td>
<script>
document.write(keepTrack);keepTrack++;
</script></td>
<td>someWordsHere</td></tr>
<script>
$(document).ready(function() {
$("#sWH1").click(function() {
$("#sWH1").hide(100);});
});</script>
<tr id="sWH2">
<td>
<script>
document.write(keepTrack);keepTrack++;
</script></td>
<td>someWordsHere</td></tr>
<script>
$(document).ready(function() {
$("#sWH2").click(function() {
$("#sWH2").hide(100);});
});</script>
<tr id="sWH3">
<td>
<script>
document.write(keepTrack);keepTrack++;
</script></td>
<td>someWordsHere</td></tr>
<script>
$(document).ready(function() {
$("#sWH3").click(function() {
$("#sWH3").hide(100);});
});</script>
</table>
<script language="JavaScript" type="text/JavaScript">
$(document).ready(function() {
$("#renumber").click(function() {
'magically renumber the remaining table rows'
});
});
</script>

The straightforward answer
To renumber the rows you can use the each() method that allows you to iterate over a set of elements (the rows in this case) and provides an i enumerator parameter.
A general example:
$(some-tr-selector).each(function(i) {
$(this).children(some-td-selector).text(i+1);
});
Now to do this, you'll need to define better selectors. The problem with your current code is that your selectors are too specific. This prevents you from creating general event handlers, instead of creating a click handler for each row.
How to improve your code
Consider setting a class for the relevant numbered rows. This will allow you to create a single click handler for all rows and make the relevant rows much easier to select when renumbering.
For example:
HTML
<table>
<tr><td colspan="2" id="renumber">renumber</td></tr>
<tr class="numbered_row">
<td class="row_number"></td>
<td>someWordsHere</td>
</tr>
<tr class="numbered_row">
<td class="row_number"></td>
<td>someWordsHere</td>
</tr>
<tr class="numbered_row">
<td class="row_number"></td>
<td>someWordsHere</td>
</tr>
...
</table>
Javascript
$(document).ready(function() {
// Number all rows onload
$('table tr.numbered_row').each(function(i) {
$(this).children('.row_number').text(i+1);
});
// Row click handler
$('table tr.numbered_row').on('click', function() {
$(this).hide(100);
});
// Renumber click handler
$('#renumber').on('click', function() {
$('table tr.numbered_row:visible').each(function(i) { // Iterate over all _visible_ rows
$(this).children('.row_number').text(i+1);
});
});
});
Note how by adding two classes numbered_row and row_number we are able to do everything efficiently in one block of code: initial numbering of the rows, a single click handler to hide them and the renumbering action.
An even more general approach
If you wanted, you could make this even more general and efficient, by chaining the each() and on() methods as well as handling the renumbering within the on() each time a row is hidden.
For example:
$(document).ready(function() {
// Number all rows onload
$('table tr.numbered_row').each(function(i) {
$(this).children('.row_number').text(i+1);
// Row click handler
}).on('click', function() {
// Hide current row
$(this).hide(100);
// Renumber visible rows
$('table tr.numbered_row:visible').each(function(i) { // Iterate over all _visible_ rows
$(this).children('.row_number').text(i+1);
});
});
});

Here is another solution:
http://jsbin.com/ufahac/1/edit
This is your code with few changes: the table has an id=myTable
and 'magically renumber the remaining table rows' has been replaced with
$('#myTable tr[id]:visible').each(function(i){
$(this).find('td:first').text(i+1);
})

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>

Get value of td table using hierarchy css (without id/classes) with javascript

I'm trying get the value of td value usgin hierarchy css with javascript.
This is my code:
This code returns the value of first td when I click in element, but my alert is undefined.
How I can solve it?
var ee = $(".table tr td:nth-child(1)").attr('value');
$(".table").on('click', function (e) {
e.preventDefault();
alert(ee);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<tr>
<td>one</td>
<td>two</td>
</tr>
</table>
<td> do not have values, that's why:
var ee = $(".table tr td:nth-child(1)").text();
$(".table").on('click', function (e) {
e.preventDefault();
alert(ee);
});
Your click event is fine. You're just grabbing an undefined item, hence why the alert is acting how it is. You need to grab <td>--this--</td>
Helpful Advice:
This isn't going to give you the text of the 1st <td>, since that's not how nth child works with this. If you want that, try this as a selector:
var ee = $(".table tr td:eq(0)").text();
0 would be the first, 1 is second, 2 is third, etc.
You can also drop the e.preventDefault() and e in the function heading. A table has no default action unlike a form or button.
use
var ee = $(".table tr td:nth-child(1)").html();
instead of
var ee = $(".table tr td:nth-child(1)").attr('value');
First one would refer to a value property on the tag, like an input one. eg : <input type="radio" name="field" value="1" >

Javascript/Jquery: Cannot target Sibling Node in Table

I have a function that hides/shows a table by clicking on it's header which is contained in a <thead> tag. When clicked the table hides and all that is left is the header, which, by clicking again, can un-hide the table.
I have multiple tables and would like to only have to use on function, instead of writing one for each table. To do this I am trying to pass the arguments (this,this.lastSibling). For some reason this.lastSibling is not targeting any object. I've tried every way of navigating the node tree I can think of, but I cannot target the tbody.
My Javascript/Jquery
function ToggleTable(trigger,target){
$(trigger).click(function(){
$(target).toggle();
ToggleTable(trigger,target)
});
}
My HTML
<table class="format2" >
<thead onmouseover="ToggleTable(this,this.lastSibling)">
<!--Title-->
</thead>
<tbody>
<!--Cells with information in here-->
</tbody>
<!--Note No TFooter Tag-->
</table>
<--Other tables similar to the one above-->
Thanks in advance!
I have a function that hides/shows a table by clicking on it's header which is contained in a <thead> tag. When clicked the table hides and all that is left is the header, which, by clicking again, can un-hide the table.
I'm lost in your current code. But If you want to toggle the visibility of the tbody (or the last child element in your <table> tag you could try this.
function ready() {
$('table > thead')
.each(function(e){
$(this).siblings(':last').hide();
})
.click(function(e) {
$(this).siblings(':last').toggle();
});
}
$(ready);
Live sample: http://bl.ocks.org/3078240
If you would like to try a solution that utilizes core JavaScript instead of jQuery shims, this might work for you. It's a function I quickly wrote that returns the last sibling that is an HTML element (e.g. not a text node) although you should be able to easily modify it to accept any node in the DOM:
function getLastSibling(el) {
var siblings, x, sib;
siblings = el.parentNode.children;
x = siblings.length;
while ((sib = siblings[x - 1]) && x >= 0) {
console.log(sib);
console.log(sib.nodeType);
if (sib.nodeType != 1 || sib.tagName == 'SCRIPT') {
x--;
} else {
return sib;
}
}
return null;
}
Assuming all your tables will have the class format2 .
Try this:
$("table.format2 > thead").click(function(){
$(this).next("tbody").toggle();
});
JSFiddle: http://jsfiddle.net/KcY4X/

How to target another element on the same row in a table with jQuery

I am trying to use jQuery to pick an item in a table row that will make a change within the same row
<table>
<tr id="t1"><td><input type="checkbox" id="t1" value="" /></td></tr>
<tr id="t2"><td><input type="checkbox" id="t2" value="" /></td>{want new stuff here}</tr>
</table>
In this instance - if I select the checkbox with the id of 2 - I would want a new column to be added/appended just after the last and if this same checkbox was unchecked it would remove the content just added.
Can anyone suggest how this is done?
Make sure your id values are unique on all elements, then you can use .parents("tr"):
$(".mytable tr :checkbox").click(function () {
var checked = $(this).is(":checked"),
$tr = $(this).parents("tr").first();
if (checked) {
$tr.append("<td></td>");
} else {
$tr.find("td:last").remove();
}
});
If you're adding multiple <td>'s, then store a reference to them or use an identifier to find them again. I'm assuming you just want to add/remove a column at the end.
As with anything jQuery, there are multiple solutions! This was the one off the top of my head.
I would better have dynamic content inserted into specified TD cell instead of creating and removing td container so that you would not have to take care about correct colspans.
$('#table :checkbox').change(function() {
var cont = $(this).closest('tr').find('.content');
if ($(this).is(':checked')) {
cont.append('Some content');
}
else {
cont.empty();
}
});
Check this out:
http://jsfiddle.net/sCjXg/1/
See this jsFiddle for a quick-written example
$(function(){
$("#t2").find("input").click(function(){
if($(this).is(":checked")){
$(this).parents('tr').append("<td class='t2-add'>have new stuff</td>")
}
else{
$(this).parents('tr').find('.t2-add').remove()
}
})
})
Try something like the following:
$('[type="checkbox"]').change(function () {
var $this = $(this);
if ($this.is(':checked') {
$this.closest('tr').append('<td></td>');
} else {
$this.closest('tr').children('td:last-child').remove();
}
});
This uses the jQuery .closest(selector) method.

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().

Categories

Resources