I've got a two-row table (label row and data row) that gets filled in with all relevant information about a running service, however, about half of the cells are empty at any given time depending on which test is run.
I'm looking for a jquery statement that will find all empty cells and hide them along with the label for that cell. I've searched quite a bit and found this code that is meant to hide the empty cells
$('table#yourTable tr').each(function(){
if($(this).children('td:empty').length === $(this).children('td').length){
$(this).hide();
}
});
However, my "empty" cells are populated with " " and not truly empty. Is there a way to hide a cell and its associated label cell?
You can use .filter()
$(document).ready(function() {
var elems = $("tr").filter(function() {
return this.querySelector("td").innerHTML === " "
});
elems.hide();
})
following code will hide all of your not truly empty cell and it's label cell.
$(function () {
var $label = $('tr:first');
$('tr:last td').each(function (index, td) {
var $td = $(td);
if ($td.html() != ' ') return;
$td.hide();
$label.find('td:eq(' + index + ')').hide();
});
});
Related
I've been trying to find a good match to my question, but nothing really concrete. I'm still learning and don't know exactly what I'm missing.
So my code can be found here: Fiddle
This is a simplified version of what I'm working with. In the final version, I will upload a csv file to the html table you see there (id="dvCSV"). Upon uploading, the table will look like it is shown (with added dropdowns and a column of checkboxes). The checkboxes come "pre-chcecked" when I generate them but what I want is the user to be able to turn "off" the rows that I do not want to calculate on.
I'll run you through the process:
This function reads the columns that the user designates. I don't know which column they will upload the data into.
function CheckLocations() {
//Checks the uploaded data for the locations of the Lat/Lon Data based on user dropdowns
colLocs[0] = ($('#Value_0 :selected').text());
colLocs[1] = ($('#Value_1 :selected').text());
colLocs[2] = ($('#Value_2 :selected').text());
colLocs[3] = ($('#Value_3 :selected').text());
LatColumn = colLocs.indexOf("Lat");
LongColumn = colLocs.indexOf("Long");
}
function AllTheSame(array) { //if they do not designate the checkboxes, I prompt them to
var first = array[0];
return array.every(function (element) {
return element === first;
});
}
This function takes all of the data in the designated columns and places them into an array for calculation.
function data2Array() {
//gets the lat and long data from the assigned columns and transfers them to an array for calculation
$("#dvCSV tr td:nth-child(" + (LatColumn + 1) + ")").each(function () {
var tdNode = $("<td/>");
tdNode.html(this.innerHTML);
LatData.push(tdNode.text());
});
LatData.splice(0, 2);
LatData.unshift(1, 1);
$("#dvCSV tr td:nth-child(" + (LongColumn + 1) + ")").each(function () {
var tdNode = $("<td/>");
tdNode.html(this.innerHTML);
LongData.push(tdNode.text());
});
LongData.splice(0, 2); //these two lines remove the first two items then replace them with 0
LongData.unshift(1, 1);
}
The first of these functions removes the checkbox column after calculations are done then new calculated columns are appended at the end. The second one was my attempt to read the checkboxes into an array. Ideally I'd want an array of values true or false, then do the calculations and return the calculated values back to the dvCSV table. For the td's where no calculation was performed, the cell would be empty.
function removeChecks() {
$("#dvCSV th:last-child, #dvCSV td:last-child").remove();
}
function makeCheckArray() {
var searchIDs = $("#dvCSV tbody td:last() input:checkbox:checked").map(function () {
return $(this).val();
}).get();
alert(searchIDs);
}
Hopefully I made the problem clear. Any help would be appreciated.
Pass a class when your table is generated into the tr element. Then create an on change method for your checkboxes. Read more here: http://api.jquery.com/on/
Also if you cannot get the inserted rows id's from your table then start a counter outside of your js like this
counter = 0;
Then inside of your loop add counter++
SO..
<tr class="row-1">
<td>
</td>
</tr>
Then add this snippet outside all of your other JS
$( "tr" ).on( "change", function() {
//do something
$(this+'.row-'+(counter)).hide();
});
This should get you headed in the right direction.
I am trying to generate a table dynamically using ajax call. To simplify things i have just added my code to js fiddle here -> http://jsfiddle.net/5yLrE/81/
As you click on the button "HI" first two columns are created properly.. but some how as the td length reaches 2 . its not creating another row. The reason is that when i do find on the table elements its actually retrieving the children table elements. Can some one pls help.
I want a two column table.. Thank you.
sample code:
var tr = $("#maintable tbody tr:first");
if(!tr.length || tr.find("td:first").length >= max) {
$("#maintable").append("<tr>");
}
if(count==0) {
$("#maintable tr:last").append("<td>hi"+content+"</td>");
}
Basically the matching of descendants was allowing for great great grandchildren etc. Just needed to make the matching more specific.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/5yLrE/91/
max = 2
$("button").click(function () {
var content = $('#template').html();
var $table = $("#maintable");
var tr = $table.find(">tbody>tr:last");
if (!tr.length || tr.find(">td").length >= max) {
// Append a blank row
tr = $("<tr>");
$table.append(tr);
}
tr.append("<td>hi " + content + "</td>");
});
This one always targets the last row and adds a row if it does not exists at all (or there are too many divs already) which is what I gather you intended.
I also used the templating I suggested to separate messy HTML strings from the code.
You will want to check the length of the table cells before incrementing a new table row. After you have reached your max column length, reset the row and start over.
JSFiddle
max_columns = 2;
count=0;
$("button").click(function() {
var content='column';
if(count==max_columns||!$('#maintable tr').length){
$("#maintable").append("<tr>");
count=0;
}
if(count!=max_columns)
$("#maintable tr:last").append("<td>"+content+"</td>");
else
$("#maintable tr:first").append("<td>"+content+"</td>");
count++;
});
I have a table which is being generated from server side and it looks like this.
Now the requirement is to hide all the column of Category B, remove duplicate rows for Category A and show entries of corresponding entries of Category B in expand-collapse way. Each A1 Name Column cell will have a expand button and when it is clicked the entries of B columns of that row will be shown below that.
I'm able to hide B category and remove duplicate rows by
var hide_duplicate_row = function () {
var seen = {};
$('td:nth-child(2)').each(function () {
var txt = $(this).text();
if (seen[txt])
$(this).closest('tr').hide();
else
seen[txt] = true;
});
};
var show_only_head = function(){
$('td:nth-child(4),th:nth-child(4)').hide();
$('td:nth-child(3),th:nth-child(3)').hide();
}
hide_duplicate_row();
show_only_head();
Fiddle: http://jsfiddle.net/ME3kG/3/
but I'm stuck with the expand collapse part, how do I populate the B category's row data in this way? Any input on this will be appreciated, thanks.
Full table:
Desired table:
Here is the plan for this:
Goes through the table rows one by one:
$('table tr').each(function () {
On each row get the content you need:
var cell_3 = $("td:nth-child(3)", this).html(); // a3
var cell_4 = $("td:nth-child(4)", this).html(); // a4
While you are still processing the current row modify the A1 column like this:
$( "td:nth-child(1)", this ).append( '<div class="toggle">' + cell_3 + ' - ' + cell_4 + '</div>' );
Now you should have a newly generated DIV in each A1 column. You'll need to assign a toggle functionality on 'click' event and you should be done. The END.
It seems you are developing using jQuery and this is the reason to explain you the idea, not giving you the exact code. :-)
EDIT 1:
Here is the final code, according to the few specific requirements: http://jsfiddle.net/ME3kG/26/ and some formatting: http://jsfiddle.net/ME3kG/30/
Add a div in your td which is hidden onload and display it on click event
I'm pretty new to jQuery and I'm having a little trouble accomplishing a specific function that I want for my table.
I have a db list that gets dynamically sorted and I want to be able to create a textarea that includes the text from a specific column on the click of the column header. I have some of the functionality from the code that I used from this http://jsfiddle.net/4BwGG/3/ but here are some things I just can't figure out:
I have some of the rows in my table hidden using style="display: none" property within the <tr> tag and when the script parses everything, the information from those hidden rows get included too. How do I do a check so that only the displayed rows are copied to the text area?
Here is what one row entry looks like:
<tr filtermatch="false" style="display: none;">
<td>< a href="http://example.edu">Tommy Trojan< /a>< /td>
< td>123-555-1231< /td>
< td>Statue Man< /td>
< td>[LTS1] [LTS2] [PM] [PM2] [TA1] [TA2] < /td>
< td>tommy#example.edu< /td>
< /tr>`
Here is the Function:
function SelectColumn(index, tableId) {
var columnText = 'You selected:\n\n';
var columnSelector = '#' + tableId + ' tbody > tr > td:nth-child(' + (index + 1) + ')';
var cells = $(columnSelector);
// clear existing selections
if (window.getSelection) { // all browsers, except IE before version 9
window.getSelection().removeAllRanges();
}
if (document.createRange) {
cells.each(function(i, cell) {
var rangeObj = document.createRange();
rangeObj.selectNodeContents(cell);
window.getSelection().addRange(rangeObj);
columnText = columnText + '\n' + rangeObj.toString();
});
}
else { // Internet Explorer before version 9
cells.each(function(i, cell) {
var rangeObj = document.body.createTextRange();
rangeObj.moveToElementText(cell);
rangeObj.select();
columnText = columnText + '\n' + rangeObj.toString();
});
}
alert(columnText);
}
Try wrapping the code in a conditional statement that checks the visibility of the tr.
For example:
if (document.createRange) {
cells.each(function(i, cell) {
if ($(cell).closest('tr').is(':visible')) {
var rangeObj = document.createRange();
rangeObj.selectNodeContents(cell);
window.getSelection().addRange(rangeObj);
columnText = columnText + '\n' + rangeObj.toString();
}
});
}
Of course, you'd want to do the same thing in the else block as well. But for the record, that jsFiddle did not work for me in IE7 (it throws an error about unsupported property or method).
I know you didn't ask, but unless you need the column to actually be selected, I would refactor the code. If you want the column to appear selected, I'd probably add a little CSS.
Someone else could probably improve the code even more. But here is my suggestion. I've added comments to explain what I did and why.
function SelectColumn(index, tableId) {
// cache the table selector in a local variable
// because we are going to use it more than once
var columnText = 'You selected:\n\n',
table = $('#' + tableId),
cells = table.find('td:nth-child(' + (index + 1) + ')');
// reset the background color of all cells
table.find('td').css('background-color', '#fff');
cells.each(function(i, cell) {
// turn cell into a jQuery object and cache it
// because we are going to use it more than once
cell = $(cell);
if (cell.closest('tr').is(':visible')) {
// get the cell text and trim it
// because different browsers treat newlines differently
columnText += $.trim(cell.text()) + '\n';
// set a background color on the selected cells
cell.css('background-color', '#ccc');
}
});
alert(columnText);
}
If you are using jquery it will make things very easy.
To select only visible elements you can use :visible in jquery.
$(document).ready(function(){
var textAreaContent=[];
$('tr:visible').each(function(){
var content=$('<div />').append($(this).clone()).html();
textAreaContent.push(content);
});
$('.textarea').val(textAreaContent.join(''));
});
check on jsfiddle http://jsfiddle.net/sudhanshu414/9YeLm/
Other option of selecting is using filter. This can also be useful if you want to filter on some other condition.
$(document).ready(function(){
var textAreaContent=[];
$('tr').filter(function(){ return $(this).css('display')!='none';}).each(function(){
var content=$('<div />').append($(this).clone()).html();
textAreaContent.push(content);
});
$('.textarea').val(textAreaContent.join(''));
});
Jsfiddle : http://jsfiddle.net/sudhanshu414/3GfqN/
I'm using DataTable and I'm trying to get some filtering function working with select element positioned in cells of the table.
The filtering works by entering text in input field positioned below each column. Then the filter function checks the selected text in all cells of that column and if no match is found in one cell, related row is hidden.
When the table has been loaded, it works to filter the table once. The problem is when clearing the filter, then it doesn't work. The reason seems to be related to that I'm using selectedIndex for the select DOM objects positioned in the rows that are not visible for the moment.
"qu_owner_xxx" is the ID of the select elements.
var el1 = document.getElementById("qu_owner_4"); //Visible, works like a charm
console.log("ID 1 " + el1.id); //ID is printed
console.log("EL 1 " + el1.selectedIndex);
var el2 = document.getElementById("qu_owner_17"); //Hidden, returns null
console.log("ID 2 " + el2.id); //Not reaching here
console.log("EL 2 " + el2.selectedIndex) ; //Not reaching here
str = el.options[el.selectedIndex].text; //Just for showing how to get the string used for filtering later
The thing is that the data of the cell is passed to the filter function as pure html, not as object. I can get the id from that part doing $(aData[i2]).attr('id') where aData is the table row. But using jQuery there seems to be some information you cannot reach compared to using the actual DOM object (e.g. selectedIndex), especially when you have to "recreate" the object from html.
How can I get the text from the selected value of the hidden select box/row? Is it even possible?
UPDATE
I tested my theory in jsfiddle, but it actually works retrieving the information from the hidden row/select. But it's no question about it, in my filter function is the rows that are not displayed that's failing.
My filter function (DataTable is calling this function when it is time for filtering)
$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
var ret = true;
//Loop through all input fields i tfoot that has class 'sl_filter' attached
$('tfoot .sl_filter').each(function(i, obj){
//$(this) can be used. Get the index of this colum.
var i2 = $("tfoot input").index($(this));
//Create regexp to math
var r = new RegExp($(this).val(), "i");
var str = "";
if(i2 == 5){//This is just during development, don't want to care about other columns with select element so just doing things on this column
//Here I just pick two id, one that I know is visible and one that is not
var el1 = document.getElementById("qu_owner_4"); //Visible, works like a charm
console.log("ID 1 " + el1.id); //ID is printed
console.log("EL 1 " + el1.selectedIndex); //selectedIndex is printed
var el2 = document.getElementById("qu_owner_17"); //Hidden, returns null
console.log("ID 2 " + el2.id); //Not reaching here
console.log("EL 2 " + el2.selectedIndex) ; //Not reaching here
//This is how I intended to get it working, but fail
var el = document.getElementById($(aData[i2]).attr('id'));
str = el.options[el.selectedIndex].text; //String to be used for comparing
}
/*Test to see if there is a match or if the input value is the default
(the initial value of input before it has any fokus/text) */
if(r.test(str) || $(this).val()=="Search"){
//Return true only exits this function
return true;
}else{
/*Return false returns both function an .each. Retain 'false' in a variable scoped
to be reached outside the .each */
ret = false;
return false;
}
});
//Return true or false
return ret;
}
);
aData = the row. aData[x] gives me the cell content of cell x on that row. For the select element it's the raw html.
this = the input field in which the search string i entered.
Of course you can have the text from the selected value !
Here is one way (probably not the best, but works) :
$('select').change(function() {
var selectedValue = jQuery(this).val();
var selectedText = '';
jQuery(this).children('option').each(function() {
if (jQuery(this).val() == selectedValue) {
selectedText = jQuery(this).text();
}
});
});
The selectedText variable will contain the text from the selected value.
See here.