How to count number of disabled columns in a table from javascript? - javascript

My table format is
<table class"tabletop">
<tr>
<td>
<table>
<tr>
<td id="mycol1"></td>
<td id="mycol2"></td>
<td id="mycol3"></td>
<td id="mycol4"></td>
</tr>
</table>
</td>
</tr>
<tr>
</tr>
</table>
I have to count columns(having id's) that are not disabled(or their display is not none) and that are disabled.
Suppose columns disabled are 4 and not disabled are 2.
So it must return disabled: 4 and not disabled: 2
td's are disabled by their id.
eg
mycol1.style.display="none";

Working Solution try this
<script type = "text/javascript" language = "javascript">
function getHiddenColumnCount() {
var tbl = document.getElementById("myTbl");
var HiddenColumnCount = 0;
for(var OuterCounter = 0 ; OuterCounter < tbl.rows.length ; OuterCounter++)
{
for(var InnerCounter = 0 ; InnerCounter < tbl.rows[OuterCounter].cells.length;InnerCounter++)
{
if (tbl.rows[OuterCounter].cells[InnerCounter].style.display == "none")
HiddenColumnCount++;
}
}
alert("There are " + HiddenColumnCount + " Hidden Columns in Table");
}
</script>

You can use
$('table td:visible').length

Try this: fiidle
<table border="1" id="myTbl">
<tr>
<td class="mycol1">
1
</td>
<td class="mycol2">
2
</td>
<td class="mycol3">
3
</td>
<td class="mycol4">
4
</td>
</tr>
</table>
<script>
function hideColumn(columnClass) {
var els = document.getElementsByClassName(columnClass);
for (var i = 0; i < els.length; i++) {
els[i].style.display = "none";
}
}
hideColumn('mycol1');
hideColumn('mycol2');
function getHiddenColumnsCount() {
var rows = document.getElementById('myTbl').rows;
var count = 0;
for (var i = 0; i < rows.length; i++) {
for (var j = 0; j < rows[i].cells.length; j++) {
if (rows[i].cells[j].style.display == "none")
count++;
}
}
alert(count);
}
getHiddenColumnsCount();
</script>
First of all you should use class for defining column instead of id as id should not be duplicate & to define a column we will have to give similar id to all cells of a column.

Related

How to Fix Uncaught Typeerror: cannot read property 'innerHTML'

i want to search data between tow dates but occurring same error again and again i have tried multiple searches and techniques but i am stuck i just keep getting error this error and dont know what to do to resolve this
there is search button above the table which get two dates from user and from those dates data is search and displayed again its kind filteration of data by dates
<button type="button" class="btn btn-info " style="font-size:17px; margin-left:548px; margin-top:-63px;" onclick="myFunction()">Search</button>
<table id="worksheet-list" class="table table-responsive">
<thead >
<tr class="table table-primary">
<th>
#*#Html.Label("SNo")*#
</th>
<th>
#Html.Label("Project")
</th>
<th>
#*#Html.DisplayNameFor(model => model.Hours)*#
Hours
</th>
<th>
#*#Html.DisplayNameFor(model => model.Date)*#
Date
</th>
<th>Action</th>
</tr>
</thead>
#*#foreach (var item in Model)*#
#for (int count = 0; count < 10; count++)
{
//count++;
<tr>
<td>
#count
</td>
<td>
#*#Html.DisplayFor(modelItem => item.Project.Name)*#
ASP.NET
</td>
<td>
#*#Html.DisplayFor(modelItem => item.Hours)*#
5 Hours
</td>
<td>
#*#Html.DisplayFor(modelItem => item.Date)*#
6/8/2018
</td>
<td>
Edit
#*Detail*#
Delete
</td>
</tr>
}
</table>
<script>
function myFunction() {
var from = document.getElementById("date-from");
var to = document.getElementById("date-to");
var table = document.getElementById("worksheet-list");
var tr = table.getElementsByTagName("tr");
var td;
for (var i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[3].innerHTML;
var d1 = from.split("/");
var d2 = to.split("/");
var c = td.split("/");
var from = new Date(d1[0], parseInt(d1[1]) - 1, d1[2]);
var to = new Date(d2[0], parseInt(d2[1]) - 1, d2[2]);
var check = new Date(c[0], parseInt(c[1]) - 1, c[2]);
if (check >= from && check <= to) {
tr[i].style.display = "";
}
else {
tr[i].style.display = "none";
}
}
}
</script>
Where you get the table rows with getElementsByTagName("tr"), you will also get the row in the thead element, which has no child td elements.
The simplest way to fix your problem is to ignore the first table row by starting your loop at 1...
for (var i = 1; i < tr.length; i++) {
If you wanted to, you could put a sense check in your code...
for (var i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td");
// if this row has no 3rd td then continue the loop
if (td.length < 4) continue;
td = td[3];

Deleting Empty Rows/Nodes

I am trying to delete the empty rows in a table. I traversed to those empty rows. But I don't know how to delete that particular node. I tried to traverse to the parent node and delete, but somehow it seems to show error.
empr[e].removeChild(empr[e].rows[et]) I used this inside the for loop
function emptyrows() {
var count = 0;
var empr = document.getElementsByClassName("tide");
var emlen = document.getElementsByClassName("tide").length;
alert(emlen);
for (var e = 0; e < emlen; e++) {
var emtab = empr[e].rows.length;
for (var et = 0; et < emtab; et++) {
if (empr[e].rows[et].innerHTML == "") {
} else {
console.log("Nothing Empty");
}
}
}
}
<table>
<tbody>
<tr>
<td>1</td>
<td>Barry</td>
<td>
<table class="tide">
<tr>50</tr>
<tr>10</tr>
<tr>200</tr>
</table>
</td>
</tr>
<tr>
<td>2</td>
<td>Allen</td>
<td>
<table class="tide">
<tr>50</tr>
<tr></tr>
<tr></tr>
</table>
</td>
</tr>
<tr>
<td>3</td>
<td>Mary</td>
<td>
<table class="tide">
<tr>50</tr>
<tr>20</tr>
<tr></tr>
</table>
</td>
</tr>
</tbody>
</table>
Try the below code, however you need to correct your HTML to be semantic (include inside ). But the code below should give you the general idea on how to proceed:
function emptyrows() {
var tables = document.getElementsByClassName("tide");
for (var i = 0; i < tables.length; i++) {
for (var j = 0; j < tables[i].childNodes.length; j++) {
if (tables[i].childNodes[j].innerHTML === '') {
tables[i].removeChild(tables[i].childNodes[j]);
}
}
}
}
emptyrows();

Select all button for selecting td tags

I have a table with each tr having class="ass testPageRow" I want to be able to all selected the td tags. I currently have some code that allows me to select the td individually. I am trying to implement a select all button.
var testPagesList = document.getElementsByClassName("testPageRow");
for (var i = 0; i < testPagesList.length; i++) {
var testPageItems = testPagesList[i].getElementsByTagName("td");
for (var j = 0; j < testPageItems.length; j++) {
testPageItems[j].onclick = function(event) {
if (this.className == "selected") {
this.className = "unselected";
} else {
this.className = "selected";
}
};
}
}
The format of my html
<table class="table">
<tbody>
<tr class="ass testPageRow">
<td id="tp1">1</td>
<td id="tp4">4</td>
<td id="tp5">5</td>
</tr>
<tr class="ass testPageRow">
<td id="tp12">12</td>
<td id="tp13">13</td>
<td id="tp14">14</td>
</tr>
<tr class="ass testPageRow">
<td id="tp14TTU">14TTU</td>
<td id="tp15">15</td>
<td id="tp16">16</td>
</tr>
<tr class="ass testPageRow">
<td id="tp18">18</td>
<td id="tp20">20</td>
<td id="tp21">21</td>
</tr>
</tbody>
</table>
Here is my current javascript code to select the tags. When I click the button, nothing happens. I'm not sure why. My logic was to iterate through all the objects and change the className to selected as I did in my previous code.
function selectAllTestPages() {
var selectAllTP = document.getElementById("selectAllTestPages");
selectAllTP.onclick = function(event) {
for (var i = 0; i < testPagesList.length; i++) {
var testPageTDTags = testPagesList[i].getElementsByTagName("td");
for (var td in testPageTDTags) {
td.className = "selected";
}
}
};
}
Button click:
<div class="center">
<button id="selectAllTestPages">Select All</button>
</div>
Perhaps try something like this?
Array.prototype.slice.call(document.querySelectorAll('.testPageRow td')).forEach(function(e) {
e.className = 'selected';
});
Demo: http://jsfiddle.net/62d4La7w/
You should really separate the function logic from the event listener logic.
The part of your code that was causing the functionality to break was the for in loop that you run on the testPageTDTags variable. You should have been using a regular loop with a counter.
Here's a new version of your code that will do what you are looking for:
// Logic to change all tds classes to 'selected'
function selectAllTestPages() {
var testPagesList = document.getElementsByClassName("testPageRow");
for (var i = 0; i < testPagesList.length; i++) {
var testPageTDTags = testPagesList[i].getElementsByTagName("td");
for (var j = 0; j < testPageTDTags.length; j++) {
testPageTDTags[j].className = "selected";
}
}
}
// Event listener that listens for button click
var button = document.getElementById('selectAllTestPages');
button.addEventListener('click', function(){
selectAllTestPages();
});
Here's a working example on jsfiddle

Follow-up of search values from first column in html table using JS?

This is my follow-up question of this... See here. I have a jscript(courtesy of hex494D49), searching values from first column.
All I need is, when the values is searching by the user, the table headers will also displayed and if the values is not store. There's a message will display like this "No results found". How to do that?
Here's the JSfiddle file with html
Here's the JScript:
document.getElementById('term').onkeyup = function(){
var term = this.value;
var column = 0;
var pattern = new RegExp(term, 'g');
var table = document.getElementById('dataTable');
var tr = table.getElementsByTagName('TR');
for(var i = 0; i < tr.length; i++){
var td = tr[i].getElementsByTagName('TD');
for(var j = 0; j < td.length; j++){
if(j == column && td[j].innerHTML == term){
console.log('Found it: ' + td[j].innerHTML);
tr[i].style.display = 'block';
return;
alert('Found it: ' + td[j].innerHTML);
}else{
tr[i].style.display = 'none';
}
}
}
};
This would be the table markup. As you can see, I added thead, tbody and tfoot groups
<!-- search box -->
<input type="text" name="term" id="term" autocomplete = "off" />
<!-- table results -->
<table id="dataTable">
<thead>
<tr>
<th>Example No.</th>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="3"></th>
</tr>
</tfoot>
<tbody>
<tbody>
<tr>
<td>345678917</td>
<td>Test 1</td>
<td>one_test1#gmail.com</td>
</tr>
<tr>
<td>3512376894</td>
<td>Test 2</td>
<td>two.test2#hotmail.com</td>
</tr>
</tbody>
</table>
Default CSS for the markup above. Next step would be merging the following with the rest of your CSS.
table thead {
display: table-row-group;
}
table tbody {
display: table-row-group;
}
table tbody tr {
display: none;
}
And finally the JavaScript snippet using getElementsByTagName() method
// JavaScript
document.getElementById('term').onkeyup = function(){
var term = this.value;
var column = 0;
var msg = 'No results found!';
var pattern = new RegExp(term, 'g');
var table = document.getElementById('dataTable');
var tr = table.getElementsByTagName('TR');
for(var i = 0; i < tr.length; i++){
var td = tr[i].getElementsByTagName('TD');
for(var j = 0; j < td.length; j++){
if(j == column && td[j].innerHTML == term){
tr[i].style.display = 'table-row';
table.tFoot.innerHTML = '';
return;
}else{
tr[i].style.display = 'none';
table.tFoot.innerHTML = msg;
}
}
}
};
Working jsFiddle | Version without tfoot jsFiddle
The same as above but using rows[] and cells[] collection
HTML
<!-- Search box -->
<input type="text" id="search" autocomplete = "off" />
<!-- Table -->
<table id="table">
<thead>
<tr>
<th>Product</th>
<th>Manufacturer</th>
<th>Price</th>
<th>InStock</th>
</tr>
</thead>
<tbody>
<tr>
<td>MacBook Air</td>
<td>Apple</td>
<td>$456</td>
<td>85</td>
</tr>
<tr>
<td>Arc GIS</td>
<td>ESRI</td>
<td>$4556</td>
<td>15</td>
</tr>
<tr>
<td>3ds MAX</td>
<td>Aurodesk</td>
<td>$6556</td>
<td>359</td>
</tr>
<tr>
<td>Windows 7</td>
<td>Micorsoft</td>
<td>$256</td>
<td>2567</td>
</tr>
</tbody>
</table>
<!-- Message -->
<div id="message"></div>
CSS
table thead {
display: table-row-group;
}
table tbody tr {
display: none;
}
JavaScript
document.getElementById('search').onkeyup = function(){
var table = document.getElementById('table'),
tr = table.rows, td,
term = this.value.toLowerCase(), column = 0, i, j,
message = document.getElementById('message');
for(i = 1; i < tr.length; i++){
td = tr[i].cells;
for(j = 0; j < td.length; j++){
if(j == column && td[j].innerHTML.toLowerCase() == term){
tr[i].style.display = 'table-row';
message.innerHTML = '';
return;
}else{
tr[i].style.display = 'none';
message.innerHTML = 'No results found!';
}
}
}
};
Working jsFiddle If you won't use thead and tbody in your table here is another version jsFiddle
I case you want to search all columns, just change this line
if(j == column && td[j].innerHTML.toLowerCase() == term){
to this one
if(td[j].innerHTML.toLowerCase() == term){
And finally, if you want to have more flexible search try the version below
document.getElementById('search').onkeyup = function(){
var table = document.getElementById('table'),
tr = table.rows, td,
term = this.value.toLowerCase().trim(), column = 0, i, j,
message = document.getElementById('message'),
pattern = new RegExp(term, 'gi');
for(i = 1; i < tr.length; i++){
td = tr[i].cells;
for(j = 0; j < td.length; j++){
if(j == column && term.length > 0 && td[j].innerHTML.match(pattern)){
tr[i].style.display = 'table-row';
message.innerHTML = '';
return;
}else{
tr[i].style.display = 'none';
message.innerHTML = 'No results found!';
}
}
}
};
Working jsFiddle

Iterate over table cells, re-using rowspan values

I have a simple HTML table, which uses rowspans in some random columns. An example might look like
A | B |
---|---| C
D | |
---| E |---
F | | G
I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.
I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...
without jquery:
function tableToMatrix(table) {
var M = [];
for (var i = 0; i < table.rows.length; i++) {
var tr = table.rows[i];
M[i] = [];
for (var j = 0, k = 0; j < M[0].length || k < tr.cells.length;) {
var c = (M[i-1]||[])[j];
// first check if there's a continuing cell above with rowSpan
if (c && c.parentNode.rowIndex + c.rowSpan > i) {
M[i].push(...Array.from({length: c.colSpan}, () => c))
j += c.colSpan;
} else if (tr.cells[k]) {
var td = tr.cells[k++];
M[i].push(...Array.from({length: td.colSpan}, () => td));
j += td.colSpan;
}
}
}
return M;
}
var M = tableToMatrix(document.querySelector('table'));
console.table(M.map(r => r.map(c => c.innerText)));
var pre = document.createElement('pre');
pre.innerText = M.map(row => row.map(c => c.innerText).join('\t')).join('\n');
document.body.append(pre);
td {
border: 1px solid rgba(0,0,0,.3);
}
<table>
<tr>
<td colspan=2>A</td>
<td rowspan=2>B</td>
</tr>
<tr>
<td>C</td>
<td rowspan=3>D</td>
</tr>
<tr>
<td rowspan=2>E</td>
<td rowspan=4>F</td>
</tr>
<tr></tr>
<tr>
<td rowspan=2 colspan=2>G</td>
</tr>
<tr></tr>
<tr>
<td rowspan=3 colspan=3>H</td>
</tr>
<tr></tr>
<tr></tr>
<tr>
<td colspan=3>I</td>
</tr>
</table>
Try this:
<table id="tbl">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="2" rowspan="2">A</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
Script:
var finalResult = '';
var totalTds = $('#tbl TR')[0].length;
var trArray = [];
var trArrayValue = [];
var trIndex = 1;
$('#tbl TR').each(function(){
var currentTr = $(this);
var tdIndex = 1;
trArray[trIndex] = [];
trArrayValue[trIndex] = [];
var tdActuallyTraversed = 0;
var colspanCount = 1;
$('#tbl TR').first().children().each(function(){
if(trIndex > 1 && trArray[trIndex - 1][tdIndex] > 1)
{
trArray[trIndex][tdIndex] = trArray[trIndex - 1][tdIndex] - 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex - 1][tdIndex];
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
else
{
if(colspanCount <= 1)
{
colspanCount = currentTr.children().eq(tdActuallyTraversed).attr('colspan') != undefined ? currentTr.children().eq(tdActuallyTraversed).attr('colspan') : 1;
}
if(colspanCount > 1 && tdIndex > 1)
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex][tdIndex - 1];
colspanCount--;
}
else
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).html();
tdActuallyTraversed++;
}
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
tdIndex++;
});
trIndex++;
});
alert(finalResult);
Fiddle
i am not sure about the performance, but it works well.
what I understood with your question is: You want to split the merged cell with same value and then iterate the table simply by row.
I've created a JSFiddle that will split the merged cells with the same value. Then you'll have a table that can be iterated simply by rows to get the desired output that you specified.
See it running here http://jsfiddle.net/9PZQj/3/
Here's the complete code:
<table id="tbl" border = "1">
<tr>
<td>A</td>
<td>B</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td>D</td>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
<br>
<div id="test"> </div>
Here's the jquery that is used to manipulate the table's data.
var tempTable = $('#tbl').clone(true);
var tableBody = $(tempTable).children();
$(tableBody).children().each(function(index , item){
var currentRow = item;
$(currentRow).children().each(function(index1, item1){
if($(item1).attr("rowspan"))
{
// copy the cell
var item2 = $(item1).clone(true);
// Remove rowspan
$(item1).removeAttr("rowspan");
$(item2).removeAttr("rowspan");
// last item's index in next row
var indexOfLastElement = $(currentRow).next().last().index();
if(indexOfLastElement <= index1)
{
$(currentRow).next().append(item2)
}
else
{
// intermediate cell insertion at right position
$(item2).insertBefore($(currentRow).next().children().eq(index1))
}
}
});
console.log(currentRow)
});
$('#test').append(tempTable);
You can use this Gist. It supports all the requirements by W3C, even "rowspan=0" (which seems to be only supported by Firefox).

Categories

Resources