Display block && none duplicate issue with Javascript - javascript

I have a simple html table which has Name, Monthly Income and Income. I wrote a simple function that takes the values of the <tds> but only the Monthly Income and Income. If they are both 0 with one click hide the all the <tr>, and if you want you can show the <tr> again..
My code works fine. THE PROBLEM is, when i press hide and then show.. it is returning me an abnormal result of the specific <tr> i seriously don't know why..
function hideZeros() {
let trs, tds, td1, td2, total, i;
trs = document.getElementsByTagName("tr");
for (i = 1; i < trs.length; i++) {
tds = trs[i].getElementsByTagName("td");
td1 = parseInt(tds[1].innerHTML);
td2 = parseInt(tds[2].innerHTML);
total = (td1 + td2);
if (total === 0) {
if (trs[i].style.display === "none") {
trs[i].style.display = "block";
} else {
trs[i].style.display = "none";
}
}
}
}
<table>
<tr>
<th>Name</th>
<th>Monthly Income</th>
<th>Income</th>
</tr>
<tbody>
<tr>
<td>Jim</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>Joe</td>
<td>100.000</td>
<td>50.000</td>
</tr>
</tbody>
</table>
<button onclick="hideZeros()" class="btn btn-primary" type="button">Click</button>

The default display value for a <tr> is table-row not block.

This is because by default the style of a tr element is not "block" but "table-row"

Related

Sort a table with another table inside it

I currently have a table with a another table inside it that I have appended dynamically, for example:
<table>
<tr>
<th>Rank</th>
<th>Institute</th>
</tr>
<tr>
<td>1</td>
<td>MIT</td>
</tr>
<tr>
<td>
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>David</td>
<td>21</td>
</tr>
<tr>
<td>James</td>
<td>19</td>
</tr>
</table>
</td>
</tr>
<td>2</td>
<td>UBC</td>
</tr>
<tr>
<td>
<table>
<tr>
<th>Age</th>
<th>Height</th>
</tr>
<tr>
<th>Angela</th>
<th>18</th>
</tr>
<tr>
<th>Peter</th>
<th>23</th>
</tr>
</table>
</td>
<tr>
I used a javascript table sorting function from w3schools and it works well:
function sortTable(tableId, valueType, column) {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById(tableId);
switching = true;
while (switching) {
switching = false;
rows = table.rows;
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].$("TD")[column];
console.log("x: " + x);
y = rows[i + 1].$("TD")[column];
if (valueType == "String") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (valueType == "Integer") {
if (parseInt(x.innerHTML.toLowerCase()) < parseInt(y.innerHTML.toLowerCase())) {
shouldSwitch = true;
break;
}
} else if (valueType == "IntegerReverse") {
if (parseInt(x.innerHTML.toLowerCase()) > parseInt(y.innerHTML.toLowerCase())) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}
However, the problem is when I sort the table, the outer table sorts fine but the inner table gets messed up. I tried to give the inner table's parent td an id and tried to use the 'not' operator but I think because I am mixing jQuery with javascript, it still doesn't work.
Does anyone know how to sort just the outer table and keep the inner table as it is while still being appends to its parent td? Any help is much appreciated! ^^
Thank you!

How to obtain row and column information of a clicked table

I have the following fiddle - where I am testing out a concept of getting to the data in a table. At the moment, I can get to the value displayed in a particular cell, when i click on the cell.
In addition, I would like to be able to get the row and column index of the clicked cell. Does anyone here know how to do this?
Link to fiddle
var tbl = document.getElementById("recordingTable");
if (tbl != null) {
for (var i = 0; i < tbl.rows.length; i++) {
for (var j = 0; j < tbl.rows[i].cells.length; j++)
tbl.rows[i].cells[j].onclick = function () { getval(this); };
}
}
function getval(cel) {
alert(cel.innerHTML);
}
<table cellspacing="1" id="recordingTable">
<!-- this is the head element -->
<thead class="callView">
<!--specify the columns -->
<tr>
<th>STATE</th>
<th>CALLID</th>
<th>COLLECTED</th>
<th>ZONE</th>
</tr>
</thead>
<!-- -->
<tbody class="callView">
<tr>
<td>0</td>
<td>10001</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>10002</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>10003</td>
<td>spring</td>
<td>1</td>
</tr>
</tbody>
</table>
Insead of adding onclick event to each cell you can add it to table, and get neccesary info from argument:
var tbl = document.getElementById("recordingTable");
tbl.onclick = function(e)
{
console.log(e.target.innerHTML);
console.log(e.target.cellIndex);
console.log(e.target.parentElement.rowIndex);
}
JsFiddle: https://jsfiddle.net/19qfsxr9/14/
You can get by using
cel.rowIndex
cel.cellIndex
in the function

Make entire column disappear

How can I make the left column in a table disappear using plain JS?
This is my approach:
<table id="tab" border="1">
<tr>
<td>abc</td>
<td>def</td>
</tr>
<tr>
<td>ghi</td>
<td>jkl</td>
</tr>
<tr>
<td>mno</td>
<td>pqr</td>
</tr>
</table>
<button onclick="inv()">invisible</button>
<button onclick="vis()">visible</button>
<script>
var tab, td;
window.onload = function() {
tab = document.getElementById("tab");
td = tab.getElementsByTagName("td");
}
function inv() {
for (i = 0; i < td.length; i++) {
td[i].style.display = "none";
i++;
}
}
function vis() {
for (i = 0; i < td.length; i++) {
td[i].style.display = "block";
i++;
}
}
</script>
It works, but I have to use "ugly" loops.
Maybe there is a more efficient way by just saying column[0].display = "none".
Here is the fiddle.
Take advantage of CSS hierarchy and nth-child selectors.
Use selector tr td:nth-child(1) to select all the first column td elements.
JSfiddle
var tab;
// Use DOMContentLoaded instead of load event
document.addEventListener('DOMContentLoaded', function() {
tab = document.getElementById('tab');
});
function inv() {
tab.classList.add('hide');
}
function vis() {
tab.classList.remove('hide');
}
.hide tr td:nth-child(1) {
display: none;
}
<table id="tab" border="1">
<tr>
<td>abc</td>
<td>def</td>
</tr>
<tr>
<td>ghi</td>
<td>jkl</td>
</tr>
<tr>
<td>mno</td>
<td>pqr</td>
</tr>
</table>
<button onclick="inv()">invisible</button>
<button onclick="vis()">visible</button>
Demo using toggle with single button.
function toggle() {
document.getElementById('tab').classList.toggle('hide');
}
.hide tr td:nth-child(1) {
display: none;
}
<table id="tab" border="1">
<tr>
<td>abc</td>
<td>def</td>
</tr>
<tr>
<td>ghi</td>
<td>jkl</td>
</tr>
<tr>
<td>mno</td>
<td>pqr</td>
</tr>
</table>
<button onclick="toggle()">Toggle</button>
By the use of some empty css classes and jQuery, you are able to achieve that in a one-liner:
<table id="tab" border="1">
<tr>
<td class="col1">abc</td>
<td class="col2">def</td>
</tr>
<tr>
<td class="col1">ghi</td>
<td class="col2">jkl</td>
</tr>
<tr >
<td class="col1">mno</td>
<td class="col2">pqr</td>
</tr>
</table>
now you can just do:
jQuery(".col1").hide();
(mind the selector with a dot before the class name)
The most efficient solution would be to inject and remove a stylesheet and let the browser do the work.
Fiddle: https://jsfiddle.net/4L4h7ea1/2/
var tab, td;
var hideFirstColumnCss = document.createElement('style');
hideFirstColumnCss.setAttribute('id', 'hideCssStyle');
hideFirstColumnCss.innerHTML = '#tab td:first-child { display: none; }';
window.onload = function () {
tab = document.getElementById("tab");
td = tab.getElementsByTagName("td");
}
function inv() {
document.head.appendChild(hideFirstColumnCss);
}
function vis() {
var style = document.getElementById('hideCssStyle');
style.parentNode.removeChild(style);
}
Use the row tags to get to your cells to hide/show them. That way you can specify an index for the row as all cells are direct children of their row.
var tab, td;
window.onload = function () {
tab = document.getElementById("tab");
tr = tab.getElementsByTagName("tr");
}
function inv() {
for (i = 0; i < td.length; i++) {
tr[i].children[0].style.display = "none";
}
}
function vis() {
for (i = 0; i < td.length; i++) {
tr[i].children[0].style.display = "block";
}
}

Show hidden rows in table with dropdown

I have something that seems fairly simple but I'm stumped. I want a dropdown within a table that affects how many table rows are shown. By default, only 2 rows are shown. By selecting 4 in the dropdown, 4 rows should be shown. I am only seeing one of the hidden rows show up, and I've tried to wrap the 2 rows in a hidden div as well, no luck. Ideas?
<table border="1">
<tr>
<td class="noBG" colspan="3">
<select id="displayText" onchange="javascript:toggle();">
<option>2</option>
<option>4</option>
</select>Items
</td>
</tr>
<thead>
<tr>
<th>Dates</th>
<th>Time</th>
<th>Person</th>
</tr>
</thead>
<tr>
<td>12/3</td>
<td>12:45</td>
<td>John Doe</td>
</tr>
<tr>
<td>12/4</td>
<td>12:45</td>
<td>James Doe</td>
</tr>
<tr id="toggleText" style="display: none">
<td>12/4</td>
<td>12:45</td>
<td>Janey Doe</td>
</tr>
<tr id="toggleText" style="display: none">
<td>12/4</td>
<td>12:45</td>
<td>Janey Doe</td>
</tr>
</table>
<script language="javascript">
function toggle() {
var ele = document.getElementById("toggleText");
if(ele.style.display == "block") {
ele.style.display = "none";
}
else {
ele.style.display = "block";
}
}
</script>
​
Using display: block; doesn't work as the table rows will then displayed not in the right way. But you can toggle the visibility by adding and removing a class, which is defined with display: none;. So you must not switch display: none/block;, but the class.
This works (incl. jQuery): http://jsfiddle.net/Yuvvc/1/
You can use following code for JS function:
function toggle() {
$.each($('tr[name=toggleText]'), function() {
$(this).toggleClass("hiddenRow", $(this).attr('class') != "hiddenRow");
});
}
With the second parameter (bool) for .toggleClass you can add and remove the class.
EDIT
Here a non-jQuery version:
function toggle() {
var rows = document.getElementsByName("toggleText");
for(var i=0; i<rows.length; i++)
{
rows[i].className = (rows[i].className == "hiddenRow") ? "" : "hiddenRow";
}
}
Change all <tr id="toggleText" to <tr name="toggleText", and then change the toggle function to the following:
function toggle() {
var ele = document.getElementsByName("toggleText");
for (var i = 0; i < ele.length; i++) {
if (ele[i].style.display == "block") {
ele[i].style.display = "none";
}
else {
ele[i].style.display = "block";
}
}
}
You can toggle the hidden rows by giving each row an id like this:
<table class="table">
#foreach (var item in Model)
{
<tr>
<td onclick="toggle1(#item.ID)" colspan="3">
#Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
<tr class="hidden" id="bluh_#item.ID">
<td>
#Html.DisplayFor(modelItem => item.Code)
</td>
<td>
#Html.DisplayFor(modelItem => item.Position)
</td>
</tr>
}
then use JavaScript to Hide and Show the Children Rows
<script>
function toggle1(something) {
$("#bluh_"+something).toggleClass('hidden');
}
</script>

How can I get the corresponding table column (td) from a table header (th)?

I want to get the entire column of a table header.
For example, I want to select the table header "Address" to hide the address column, and select the "Phone" header to show the correspondent column.
<table>
<thead>
<tr>
<th id="name">Name</th>
<th id="address">Address</th>
<th id="address" class='hidden'>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td class='hidden'>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td class='hidden'>3456</td>
</tr>
</tbody>
I want to do something like http://www.google.com/finance?q=apl (see the related companies table) (click the "add or remove columns" link)
Something like this would work -
$('th').click(function() {
var index = $(this).index()+1;
$('table td:nth-child(' + index + '),table th:nth-child(' + index + ')').hide()
});
The code above will hide the relevant column if you click on the header, the logic could be changed to suit your requirements though.
Demo - http://jsfiddle.net/LUDWQ/
With a couple simple modifications to your HTML, I'd do something like the following (framework-less JS):
HTML:
<input class="chk" type="checkbox" checked="checked" data-index="0">Name</input>
<input class="chk" type="checkbox" checked="checked" data-index="1">Address</input>
<input class="chk" type="checkbox" checked="checked" data-index="2">Phone</input>
<table id="tbl">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td>3456</td>
</tr>
</tbody>
Javascript:
var cb = document.getElementsByClassName("chk");
var cbsz = cb.length;
for(var n = 0; n < cbsz ; ++n) {
cb[n].onclick = function(e) {
var idx = e.target.getAttribute("data-index");
toggleColumn(idx);
}
}
function toggleColumn(idx) {
var tbl = document.getElementById("tbl");
var rows = tbl.getElementsByTagName("tr");
var sz = rows.length;
for(var n = 0; n < sz; ++n) {
var el = n == 0 ? rows[n].getElementsByTagName("th")[idx] : rows[n].getElementsByTagName("td")[idx];
el.style.display = el.style.display === "none" ? "table-cell" : "none";
}
}
http://jsfiddle.net/dbrecht/YqUNz/1/
I added the checkboxes as it doesn't make sense to bind the click to the column headers as you won't be able to toggle the visibility, only hide them.
You can do something with CSS, like:
<html>
<head>
<style>
.c1 .c1, .c2 .c2, .c3 .c3{
display:none;
}
</style>
</head>
<body>
<table class="c2 c3">
<thead>
<tr>
<th id="name" class="c1">Name</th>
<th id="address" class="c2">Address</th>
<th id="phone" class="c3">Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td class="c1">Freddy</td>
<td class="c2">Nightmare Street</td>
<td class="c3">123</td>
</tr>
<tr>
<td class="c1">Luis</td>
<td class="c2">Lost Street</td>
<td class="c3">3456</td>
</tr>
</tbody>
</table>
</body>
</html>
To hide a column, you add with Javascript the corresponding class to the table. Here c2 and c3 are hidden.
You could add dynamically the .c1, .c2,... in a style tag, or define a maximum number.
The easiest way to do this would be to add a class to each td that matches the class of the header. When you click the , it checks the class, then hides every td with that class. Since only the s in that column would hide that class, it would effectively hide the column.
<table>
<thead>
<th>Name</th>
<th>Address</th>
</thead>
<tbody>
<tr>
<td class="Name">Joe</td>
<td class="Address">123 Main St.
</tbody>
</table>
And the script something like:
$('th').click( function() {
var col = $(this).html(); // Get the content of the <th>
$('.'+col).hide(); // Hide everything with a class that matches the col value.
});
Something like that, anyway. That's probably more verbose than it needs to be, but it should demonstrate the principle.
Another way would be to simply count how many columns over the in question is, and then loop through each row and hide the td that is also that many columns over. For instance, if you want to hide the Address column and it is column #3 (index 2), then you would loop through each row and hide the third (index 2).
Good luck..
Simulating the Google Finance show/hide columns functionality:
http://jsfiddle.net/b9chris/HvA4s/
$('#edit').click(function() {
var headers = $('#table th').map(function() {
var th = $(this);
return {
text: th.text(),
shown: th.css('display') != 'none'
};
});
var h = ['<div id=tableEditor><button id=done>Done</button><table><thead><tr>'];
$.each(headers, function() {
h.push('<th><input type=checkbox',
(this.shown ? ' checked ' : ' '),
'/> ',
this.text,
'</th>');
});
h.push('</tr></thead></table></div>');
$('body').append(h.join(''));
$('#done').click(function() {
var showHeaders = $('#tableEditor input').map(function() { return this.checked; });
$.each(showHeaders, function(i, show) {
var cssIndex = i + 1;
var tags = $('#table th:nth-child(' + cssIndex + '), #table td:nth-child(' + cssIndex + ')');
if (show)
tags.show();
else
tags.hide();
});
$('#tableEditor').remove();
return false;
});
return false;
});
jQuery('thead td').click( function () {
var th_index = jQuery(this).index();
jQuery('#my_table tbody tr').each(
function(index) {
jQuery(this).children('td:eq(' + th_index + ');').each(
function(index) {
// do stuff here
}
);
}
);
});
here's a working fiddle of this behaviour:
http://jsfiddle.net/tycRW/
of course, hiding the column with out hiding the header for it will have some strange results.

Categories