How to check whether a html column contains empty cells? - javascript

I want to check whether a cells of a certain column of a html table is filled completely. The 5th column of the #mf-table could not be kept unfilled.
I used following function to select the column. It works fine.
$.fn.column = function(i) {
return $('tr td:nth-child('+(i+1)+')', this);
}
I used the following method to pop up a warning if column has empty cells.
if ($('#mf-table').column(5).is(":empty")) {
toastr.error('Fill empty fields');
}
This method does not working. Can any one tell what is wrong here?
edit:
I tried following method. In order to test my code I colored the column 5 and it works fine. Here I have considered a situation where any of the cell is empty in whole table
if ($('#mf-table tr td').is(":empty")) {
$('#mf-table').column(5).css( "background-color", "red" )
}
So in the above method, if at least one cell is empty, the column 5 is colored. I need help to alter this method to check whether at least one cell is empty in column 5.

Try this :
jQuery('table tr').each(function(){
if(jQuery(this).children('td:empty').length > 0){
console.log('Ther is Empty Cell');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>20</td>
<td>20</td>
<td>20</td>
<td></td>
</tr>
</tbody>
</table>

Try to use this function instead (copied from here):
function isEmpty( el ){
return !$.trim(el.html())
}

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>

Use jQuery arguments in JavaScript function

I want to use a jQuery argument in a JavaScript function. At the moment, my code looks like this:
window.nextGen = function(cell) {
// code...
}
window.prepareNextGen = function() {
nextGen($('#grundtabelle').rows[1].cells[1]);
}
But that doesn't work. Any help?
Simple Fix
To access the table object rows and cells you can simply add an array index like so:
nextGen( $('#grundtabelle')[0].rows[1].cells[1] );
See this previous question for more detail: How to get a DOM Element from a JQuery Selector
Run the snippet to try
nextGen( $('#grundtabelle')[0].rows[1].cells[1] );
function nextGen( cell ) {
console.info( cell.innerHTML ); // displays B1
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<table id="grundtabelle">
<tr>
<td>A0</td>
<td>B0</td>
</tr>
<tr>
<td>A1</td>
<td>B1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
</tr>
</table>
A jQuery object does not have a rows or cells property. Assuming you're trying to get the second td of the second tr (note that the indexes are zero-based, so the item with index of 1 is the second), then you need to use jQuery's DOM traversal methods. In this case, find() and :eq. Try this:
nextGen($('#grundtabelle').find('tr:eq(1) td:eq(1)'));
If the nextGen() function is expecting a DOMElement instead of a jQuery object then you can retrieve that from the jQuery object like this:
nextGen($('#grundtabelle').find('tr:eq(1) td:eq(1)')[0]);
// or:
nextGen($('#grundtabelle').find('tr:eq(1) td:eq(1)').get());

Keep rows with certain values always at the bottom while sorting in jquery tablesorter plugin

I'm using JQuery Table sorter plugin(http://tablesorter.com/docs/) in my application it works great but I would like to exclude certain rows which has N/A for the clicked column while sorting and keep them always at the end.
As far as i have checked if we put elements in tfoot it will always remains at the bottom. But i wanted to display those rows initially only when sorting happens I would like to move them at the end.
Below is my HTML
<table id="myTable" class="tablesorter">
<thead>
<tr>
<th>Code</th><th>Name</th><th>Count</th><th>Percentage</th>
</tr>
</thead>
<tbody>
<tr>
<td>1011</td><td>Cheif Executives</td><td>2385</td><td>20%</td>
</tr>
<tr>
<td>1012</td><td>General and Operations Manager</td><td>2986</td><td>N/A</td>
</tr>
<tr>
<td>1013</td><td>Advertising Promo Managers</td><td>3412</td><td>30%</td>
</tr>
<tr>
<td>1014</td><td>Marketing Managers</td><td>2154</td><td>5%</td>
</tr>
</tbody>
</table>
Javascript
In JavaScript we can specify a text extraction method for table sorter. While sorting higher to lower I'm trying to make the N/A as ' ' which has lower ASCII value than other symbols so the row will be in lower end of the table. Similarly lower to higher sorting i need to replace N/A with ~ symbol to give N/A a higher value to make to appear at the end.
Below is the code snippet I'm trying
$(document).ready(function () {
$("#myTable").tablesorter({
textExtraction: function (node) {
var s = '';
var hdrs = $("#myTable th");
var direction = '';
hdrs.each(function (index) {
if ($(this).hasClass('headerSortDown')) {
direction = 'down';
return;
}
else if ($(this).hasClass('headerSortUp')) {
direction = 'up';
return;
}
});
if (direction === 'down')
s = $(node).text().replace('N/A', ' ');
else if (direction === 'up')
s = $(node).text().replace('N/A', '~');
return s;
},
cssAsc: 'headerSortUp',
cssDesc: 'headerSortDown'
});
});
But it seems like the css classes are not getting added by default so the result is not as expected. My expected Result during both sort is the row while has code 1012 should always appear below the table.
Note i cant add any static classes to the table markup for the N/A values since it is from the table is generated dynamically
Thanks in advance
I'm glad that I fixed this issue by myself and I'm happy to share this to folks who might need this in future. There are two things to this issue
Tell table sorter to consider the N/A as empty. this can be done using the textExtraction(method used to extract values from the cells for sorting) method that table sorter provides
Ask tableSorter to keep all the empty values to the bottom using emptyTo attribute
Below is the code
$(document).ready(function () {
$("#myTable").tablesorter({
textExtraction: function (node) {
var txt = $(node).text();
txt = txt.replace('N/A', '');
return txt;
},
emptyTo: 'bottom'
});
});

How to make a <tr> invisible if it's <td>'s are empty?

I have a table which contains 'n' rows dynamically generated. All <td>'s may or may not contain data. I want to hide or delete '<tr>' if all it's td's are empty.
I don't know how to parse through all <td>'s and make sure it's empty or not.
example table as follows,
<table id='ex_table'>
<tr>
<td>one</td>
<td>two</td>
</tr>
<tr>
<td></td>
<td>one</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
In the above table last row need to be hidden since all it's <td>'s are empty. I prefer jquery to do this.
You don't actually have to inspect the td elements. You can select the rows and use .filter to filter out those with text content, i.e. only keep those which are empty:
$('#ex_table tr').filter(function() {
return $.trim($(this).text()) === '';
}).hide(); // or .remove()
This works because .text gets the combined inner text of all descendants and $.trim removes whitespace characters that might occur due to your HTML formatting (but are not actually content).
If you have cells which contain HTML elements but no text content (e.g. icons styled through CSS), and you want to keep those, you'd have actually have to test whether a cell contains HTML or not. The approach is basically the same as testing for text content
$('#ex_table tr').filter(function() {
return $(this).children().filter(function() {
return $.trim($(this).html()) !== '';
}).length === 0;
}).hide();
only this time we count the number of cells in a row that contain HTML. If there is none, the row is considered empty.
try something like this
$(function(){
$('#ex_table tr').each(function(){
var val = $(this).text().trim();
if(val == ''){
$(this).remove();
}
})
})
Try this:
$('#ex_table tr').each(function){
if($(this).text()==''){
$(this).remove();
}
}
Straight jQuery you say?
EDIT: I'd use Felix's answer.. just change ".hide()" to ".remove()" if you'd like to delete the element.
$('tr').each(function(){
var hasValue = false;
$(this).children().each(function(){
if ($(this).html() != "")
hasValue = true;
});
if (!hasValue)
$(this).remove();
});
Try this code
var hide;
$("tbody").find("tr").each(function(){
hide=true;
$(this).find("td").each(function(){
if($(this).html()!='') {
hide=false;
}
});
if(hide==true) {
$(this).hide();
}
});

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