Show / Hide HTML Table rows using Javascript - javascript

I don't know why something this simple isn't working.
<table id="df">
<tr><td>foo</td></tr>
<tr><td>bar</td></tr>
<tr><td>abc#yahoo.com</td></tr>
</table>
Say we have an HTML table. How would I hide all rows / only some rows, and vice versa, how would I show all rows / only some rows?
Things that aren't working:
//one
document.getElementByTagName('table').style.display = "none";
//two
var rows = document.getElementsByTagName("table")[0].rows;
rows.hidden = false;
//three
var table = document.getElementById("df");
table.style = "display:table-row";
Thanks in advance

You can select row n using nth-child css selector
const table = document.querySelector("#df tbody")
const toggleRow = (rowIndex = 0) => {
if (table.childElementCount < rowIndex) return
const row = table.querySelector(`:nth-child(${rowIndex})`)
row.style.display = row.style.display === 'none' ? 'block' : 'none'
}
toggleRow(1) // Hide first row
toggleRow(2) // Hide second row
toggleRow(4) // Will not be hidden because table only have 3 rows
toggleRow(2) // Show second row
<table id="df">
<tbody>
<tr>
<td>foo</td>
</tr>
<tr>
<td>bar</td>
</tr>
<tr>
<td>abc#yahoo.com</td>
</tr>
</tbody>
</table>

First, the problems:
document.getElementByTagName('table').style.display = "none";
getElementByTagName() doesn't exist; this will have generated an error and would have been shown to you in the developer console had you looked. While getElementsByTagName() exists, the existence of a means to get all elements of a given means (id,tag-name, class...) doesn't imply that a similar method exists to get a singular element via the same approach.
This didn't work because it couldn't work (unless you created the function yourself).
var rows = document.getElementsByTagName("table")[0].rows;
rows.hidden = false;
This couldn't work because while document.getElementsByTagName('table')[0] would return the first <table> in the document, HTMLTableElement.rows property returns a NodeList over which you would have to iterate to hide each row in turn. Again, this would have generated an error which you should have seen in your developer console.
Further, setting rows.hidden to false means that even if it had worked, and assigned the false value to the hidden property of the collection of elements, they would still be visible because you tried to set their hidden to false (which means they would be visible), instead of true which would hide them.
var table = document.getElementById("df");
table.style = "display:table-row";
I don't honestly know what you were trying to achieve with this, but displaying the <table> as if it was a <tr> was never going to hide the <table>, just make it look like something else.
const hideMethods = {
// here we map the 'data-demo' attribute-value of each <button> to a particular function:
getElementsByTagName: (e) =>
// we navigate from the Event Object's currentTarget (the element to which the initiating
// function was bound) to the closest ancestor <section> element:
e.currentTarget.closest('section')
// within that <section> we use getElementsByTagName() to retrieve all <table> elements,
// and then supply the zeroeth index to get the first:
.getElementsByTagName('table')[0]
// we then update the 'display' property of the CSSStyleDeclaration object, setting it to
// 'none' to have it be hidden:
.style.display = "none",
// here we use the 'hidden' property of various nodes:
hidden: (e) =>
// again, navigating to the ancestor <section>:
e.currentTarget.closest('section')
// using Element.querySelectorAll() to find all <tr> elements inside of <table> elements:
.querySelectorAll('table tr')
// and iterating over each of those <tr> elements in turn, using NodeList.prototype.forEach():
.forEach(
// we use an Arrow function to pass a reference to the current <tr> of the NodeList over
// which we're iterating, and within the function body we update the
// HTMLElement.hidden property, setting it to true, in order to hide it:
(row) => row.hidden = true),
querySelector: (e) =>
// navigating to the ancestor <section>:
e.currentTarget.closest('section')
// using Element.querySelector to retrieve the first/only <table> within the <section>
.querySelector('table')
// updating the HTMLElement.hidden property to hide the element (along with its
// descendants):
.hidden = true
},
showMethods = {
// here we map the 'data-demo' attribute-value of each <button> to a particular function:
getElementsByTagName: (e) =>
// we navigate from the Event Object's currentTarget (the element to which the initiating
// function was bound) to the closest ancestor <section> element:
e.currentTarget.closest('section')
// within that <section> we use getElementsByTagName() to retrieve all <table> elements,
// and then supply the zeroeth index to get the first:
.getElementsByTagName('table')[0]
// we then update the 'display' property of the CSSStyleDeclaration object, setting it to
// 'block' to have it be visible:
.style.display = "",
// here we use the 'hidden' property of various nodes:
hidden: (e) =>
// again, navigating to the ancestor <section>:
e.currentTarget.closest('section')
// using Element.querySelectorAll() to find all <tr> elements inside of <table> elements:
.querySelectorAll('table tr')
// and iterating over each of those <tr> elements in turn, using NodeList.prototype.forEach():
.forEach(
// we use an Arrow function to pass a reference to the current <tr> of the NodeList over
// which we're iterating, and within the function body we update the
// HTMLElement.hidden property, setting it to false, in order to show it:
(row) => row.hidden = false),
querySelector: (e) =>
// navigating to the ancestor <section>:
e.currentTarget.closest('section')
// using Element.querySelector to retrieve the first/only <table> within the <section>
.querySelector('table')
// updating the HTMLElement.hidden property to show the element (along with its
// descendants):
.hidden = false,
},
// simple function which takes an element node:
getIndex = (el) => {
// caches the parentNode of that element node:
let parent = el.parentNode,
// retrieves the iterable children NodeList from
// the parent, and converts it into an Array:
children = [...parent.children];
// returns the result of calling Array.prototype.indexOf()
// on that Array looking for the passed-in element:
return children.indexOf(el);
};
// retrieving all <button> elements in the document, and iterating over that collection
// with NodeList.prototype.forEach():
document.querySelectorAll('button.close').forEach(
// Arrow function passing a reference to the current <button> into the function, in
// which we use EventTarget.addEventListener() to bind the anonymous function as
// the event-handler for the 'click' event on the <button>:
(btn) => btn.addEventListener('click', (e) =>
// here we call the functions defined in the hideMethods Object:
hideMethods[
// retrieving the function-name from the 'data-demo' attribute, using
// the Element.dataset API
btn.dataset.demo
// passing a reference to the outer Event Object to the function:
](e))
)
// retrieving all <button> elements in the document, and iterating over that collection
// with NodeList.prototype.forEach():
document.querySelectorAll('button.show').forEach(
// Arrow function passing a reference to the current <button> into the function, in
// which we use EventTarget.addEventListener() to bind the anonymous function as
// the event-handler for the 'click' event on the <button>:
(btn) => btn.addEventListener('click', (e) =>
// here we call the functions defined in the showMethods Object:
showMethods[
// retrieving the function-name from the 'data-demo' attribute, using
// the Element.dataset API
btn.dataset.demo
// passing a reference to the outer Event Object to the function:
](e))
)
document.querySelectorAll('table button.hide').forEach(
(btn) => btn.addEventListener('click', (e)=> btn.closest('tr').hidden = true)
);
// retrieving all <button> elements with a class of 'hide' inside of an ancestor
// element with a class of 'controls', and iterating over that collection with
// NodeList.prototype.forEach():
document.querySelectorAll('.controls button.hide').forEach(
// passing the current button element into the function bocy; and binding the
// anonymous function of EventTarget.addEventListener() as the event-handler
// for the 'click' event:
(btn) => btn.addEventListener('click', (e)=> {
// caching a reference to the <tr> element, which was found by navigating
// to the closest <section> ancestor, finding the first/only <table>
// element inside that <section> and accessing the HTMLTableElement.rows
// colleaction, passing in the current index of the <button> from amongst
// its own siblings to retrieve a <tr> element of the same index in its
// own sibling collection:
let row = btn.closest('section').querySelector('table').rows[ getIndex(btn) ],
// caching the current state since we're using a toggle function:
currentState = row.hidden;
// setting the HTMLElement.hidden property to the inverse of its current
// state using the negation operator:
row.hidden = !currentState;
})
);
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
main {
display: grid;
gap: 0.5em;
grid-template-columns: repeat(auto-fit, 13em);
inline-size: clamp(13em, 80vw, 1200px);
margin-block: 1em;
margin-inline: auto;
}
section {
border: 1px solid #000;
display: flex;
flex-flow: column nowrap;
justify-content: space-between;
gap: 0.5em;
padding: 0.5em;
}
h2 {
font-size: 1.1em;
font-style: italic;
font-weight: 400;
}
<main>
<section>
<h2>Hide the table</h2>
<button type="button" class="show" data-demo="getElementsByTagName">Show with 'getElementsByTagName'</button>
<table class="df">
<tr>
<td>foo</td>
</tr>
<tr>
<td>bar</td>
</tr>
<tr>
<td>abc#yahoo.com</td>
</tr>
</table>
<button type="button" class="close" data-demo="getElementsByTagName">Hide with 'getElementsByTagName()''</button>
</section>
<section>
<h2>Hide the table</h2>
<button type="button" class="show" data-demo="hidden">Show with 'hidden'</button>
<table class="df">
<tr>
<td>foo</td>
</tr>
<tr>
<td>bar</td>
</tr>
<tr>
<td>abc#yahoo.com</td>
</tr>
</table>
<button type="button" class="close" data-demo="hidden">Hide with 'hidden'</button>
</section>
<section>
<h2>Hide the table</h2>
<button type="button" class="show" data-demo="querySelector">Show with 'hidden'</button>
<table class="df">
<tr>
<td>foo</td>
</tr>
<tr>
<td>bar</td>
</tr>
<tr>
<td>abc#yahoo.com</td>
</tr>
</table>
<button type="button" class="close" data-demo="querySelector">Hide with 'hidden'</button>
</section>
<section>
<h2>Hide rows</h2>
<table class="df">
<tr>
<td>foo</td><td><button type="button" class="hide">X</button></td>
</tr>
<tr>
<td>bar</td><td><button type="button" class="hide">X</button></td>
</tr>
<tr>
<td>abc#yahoo.com</td><td><button type="button" class="hide">X</button></td>
</tr>
</table>
</section>
<section>
<h2>Toggle rows</h2>
<table class="df">
<tr>
<td>foo</td>
</tr>
<tr>
<td>bar</td>
</tr>
<tr>
<td>abc#yahoo.com</td>
</tr>
</table>
<div class="controls">
<button type="button" class="hide">1</button>
<button type="button" class="hide">2</button>
<button type="button" class="hide">3</button>
</div>
</section>
</main>
JS Fiddle demo.
References:
document.querySelector().
document.querySelectorAll().
Element.querySelector().
Element.querySelectorAll().
Element.closest().
HTMLElement.dataset API.
HTMLElement.hidden.
HTMLTableElement.rows.

try this way...
<table id="df">
<tr id="row_1"><td>foo</td></tr>
<tr id="row_2"><td>bar</td></tr>
<tr id="row_3"><td>abc#yahoo.com</td></tr>
</table>
Hide all rows:
const tableRows = document.querySelectorAll('#df tr');
tableRows.forEach(tr => tr.style.display = 'none');
Hide some row:
const rowOne = document.getElementById('row_1');
rowOne.style.display = 'none';

Actually there is some mistake in your spelling.
try this
document.getElementsByTagName("table");
document.getElementsByTagName("table")[0].rows

Related

Create a function that follows a moving text on a table

I found a function to move data between table cells but the functions never seem to stick to whatever tag is "attached" to the cell itself. I'm not sure if I was using ids wrong. I need help finding a way to "attach" a function to a tag that moves between cells.
Can you help me create a button to move a tag (unit 1) upwards and downwards through a table such that it stops at the end of the table?
Original code attached here
//Send to the "bottom"
function sendOS() {
var node = document.getElementById("r1c1").lastChild;
document.getElementById("r1c3").appendChild(node);
/*
var node = document.getElementById("r1c3").lastChild;
document.getElementById("r1c2").appendChild(node);
*/
}
//Send to the "top"
function sendTop() {
var node = document.getElementById("r1c2").lastChild;
document.getElementById("r1c1").appendChild(node);
}
table,
th,
td {
border: 1px solid black;
width: 32px;
height: 32px;
}
<table>
<tr id="row1">
<td id="r1c1">Unit1</th>
<td id="r1c2">Unit2</th>
<td id="r1c3">Unit3</th>
</tr>
<tr id="row2">
<td id="r2c1">r1c2</td>
<td id="r2c2">r2c2</td>
<td id="r2c2">r2c3</td>
</tr>
<tr id="row3">
<td id="r2c2">r3c1</td>
<td id="r2c2">r3c2</td>
<td id="r2c2">r3c3</td>
</tr>
</table>
<!--Table ends -->
<!-------------------------------------------------------------->
<button onclick="sendOS()">move to the other side</button>
<button onclick="sendTop()">move to the right</button>
I can't help you with creating all that. You should try it out for yourself, you'll learn a lot more.
But I can help you with the code you provided.
A lot of your id attributes are the same. Every id on the page should be unique.
Change your HTML structure slightly by adding a <span> around the texts inside your cells (<td><span id="target-1">Text</span></td>). That way you can select elements inside your cells and move those around. Using lastChild to get the TextNode is not the right approach.
The functions should check if there is a cell next to it in the direction you want to move the text. If there is, move the text. If not, then do nothing.
Below I've made a small demonstration on how this might work. Here target is the element that we move. It's the <span id="target">Foo</span> element in the HTML.
When clicking either button, the code will go one element up from the target element with parentElement, that will be the <td> our target is in.
It then tries to access the previous or next <td> in the row (depending on the direction). If a neighbouring <td> is found, it will append the element.
The advantage of this approach is that you always have a reference to the element that you are moving.
const target = document.querySelector('#target');
const buttonLeft = document.querySelector('.js-target-move-left');
const buttonRight = document.querySelector('.js-target-move-right');
function targetMoveLeft() {
const previousCell = target.parentElement.previousElementSibling;
if (previousCell) {
previousCell.append(target);
}
}
function targetMoveRight() {
const nextCell = target.parentElement.nextElementSibling;
if (nextCell) {
nextCell.append(target);
}
}
buttonLeft.addEventListener('click', targetMoveLeft);
buttonRight.addEventListener('click', targetMoveRight);
<table>
<tbody>
<tr>
<td><span id="target">Foo</span></td>
<td><span>Bar</span></td>
<td><span>Baz</span></td>
</tbody>
</table>
<button class="js-target-move-left">Left</button>
<button class="js-target-move-right">Right</button>
I hope this will at least push you in the right direction. Good luck with implementing the other features.

HostListner with particular element in the template Angular4?

My requirement is I want to fix the table header after certain scroll to up,while the table body is scrolling.
My app.html is below.
<table class="table table-fixed-ok" #scroller [class.fixed]="fixed">
<thead >
<tr class="row-hor-heading">
<th colspan="3" scope="row"><span class="bank-name">
{{offer.name}}</span>
</tr>
</thead>
<tbody>
<tr class="row-2-data bg-white">
</tr>
</tbody>
</table>
So i want to listen the scroll of this table only(app.html contains many more other div.i want this div scroll to be listened.)
My app.ts section is below
#HostListener('window:scroll', ['$event'])
onWindowScroll(event: Event) {
debugger;
let num = this.el.nativeElement.querySelector('.table-fixed-ok').scrollTop;
if ( num >50 ) {
this.fixed = true;
}else if (this.fixed && num < 5) {
this.fixed = false;
}
}
But this is not working as i needed.While printing the num variable always giving 0.And also it is triggering whole whole body scrolling.How to solve this.Please give me a solution.
There is no way to specify an element for #HostListener(), but you can just apply the event binding to the element directly like:
<div (scroll)="myScrollHandler($event)"

Appending a table to another table in the DOM. Targeting with no class or id available

I am currently attempting to append a specific , via jquery, to another table. Here's the HTML, and the two elements involved in the move.
<div id="content_area">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr><td></td></tr>
<tr>
<td></td> <-- TD needing to move -->
</tr>
</tbody>
</table> <-- Needs to move-->
<table width="100%" cellspacing="0" cellpadding="5" border="0">
<tbody>
<tr>
<td width="190" valign="top">
<table width="100%"></table>
<-- Move Above TD Here -->
</td>
</tr>
</tbody>
</table>
</div>
Although I'm hardly experienced with jquery/javascript, I have used the following method in the past to append a div to another div.
$(".target").appendTo($(".destination"));
This method I have used in the past required that the elements have some sort of unique identification. Since this is not possible with the current site I am developing (The software has locked down the HTML), how can I target these two tables in order to make the append?
You can view the issue at the following page:
http://xlevj.jyetp.servertrust.com/Pro-Audio-Equipment-s/1824.htm
It's pretty obvious to see on that page what I'm trying to accomplish with the move. Thanks for any help!
Try this:
//Find the td we want to move.
var tdToMove = $('#divWaitModal + table > tbody > tr:nth-child(2) td');
//Find the td we want to insert into after.
var tdToInsertAfter = $('#divWaitModal + table + table tr:first-child td:first-child');
//Detach the td to move.
tdToMove.detach();
//Insert it at the proper place.
tdToInsertAfter.after(tdToMove);
Just use child number of the node and target trough that :
$('body table:first-child').appendTo( $('table:eq(1) td:eq(0)') );
In words it takes the first table and it's appending it to second table > first cell. You can use :eq( number ) where number starts from 0, or first-child selector in some cases ..
This CSS might accomplish what you're after:
#content_area {
overflow: hidden;
}
#content_area table {
display: inline;
float: left;
}
If you want to target the elements, you can use the #content_area as a selector:
var $tables = $('#content_area>table');
var $table1 = $(tables[0]);
var $table2 = $(tables[1]);

Navigate in divs with table Jquery

I try to navigate in a table. Without the table it works, but with nope!
here's the code :
<table>
<th><div class="section selected">E1</div></th>
<th><div class="section">E2</div></th>
<th><div class="section">E3</div></th>
</table>
<br />
CLICK
then
$('#button').click(function(){
$('.selected + .section, .section:eq(0)')
.last().addClass('selected')
.siblings('.selected').removeClass('selected');
});
CSS
.selected{background:red}
And How to triggered the link with Enter Key?
Thanks!
this might want you want to do:
$('#button').click(function () {
var selected = $('.section.selected');
selected.removeClass('selected');
var tbl = selected.closest("table");
var th = tbl.find("th");
var index = selected.closest("th").index();
if(index < th.length-1) index++;
else index=0;
tbl.find(".section:eq(" + index + ")").addClass('selected');
});
this is the working DEMO.
The problem in your code was using jQuery siblings function, which goes through the all node siblings at the same DOM level, for instance if you had:
<table>
<th>
<div class="section selected">E1
</div>
<div class="section">E1 Sibling
</div>
</th>
</table>
then sibling function would select the E1 Sibling node, but non of .section nodes in your html are siblings.

Simple setting off display: none / block with javascript

I have the following Code:
<table>
<tr class="odd"><td>Entry 1</td></tr>
<tr class="even clickable" onclick="showHide('sub2')"><td>> Entry 2</td></tr>
<tr class="even" id="sub2">
<td><ul><li>Information 1</li><li>Information 2</li></ul></td>
</tr>
<tr class="odd"><td>Entry 3</td></tr>
<tr class="even"><td>Entry 4</td></tr>
</table>
and the following js:
function showHide(id) {
var el = document.getElementById(id);
if( el && el.style.display == 'none')
el.style.display = 'block';
else
el.style.display = 'none';
}
with this css:
tr.odd{
background-color: #dedede;
}
tr.even{
background-color: #7ea9ff;
}
tr.clickable{
cursor: pointer;
}
tr.clickable:hover{
color: white;
}
tr[id^="sub"]{
display: none;
}
Could someone please tell me, why it doesn't work? I'm trying to show / hide onclick the row with the id="sub2"
example in jsfiddle
Open your debug console when you run your code, and you will get the message "ReferenceError: showHide is not defined".
If you place your html and javascript inside a file and run that that particular issue is resolved. It has something to do with the order with which jsfiddle processes sources.
Secondly, you are trying to get an element by id, but give it the class name - that does not make sense. By giving elements id's and using that it works.
But this is very unwieldy, and just serves to explain why it did not work. You are better off using jQuery as raphael said.
edit: replaced html with link
function showHide(id) {
var el = document.getElementById(id);
if( el && el.style.display == 'block')
el.style.display = 'none';
else
el.style.display = 'block';
}
First of all, in your JSFiddle example, the function is wrapped into a domready event. You should change the wrap of your JavaScript to No wrap - in body. This can be set up in the second dropdown in the left bar. Your function won't be accessible otherwise.
Then, the second line in your JavaScript searches for an element with an ID - but your document does not contain any ID's, it contains classes. document.getElementById can only find elements by their IDs.
I would suggest that you use jQuery for this task. With jQuery, the task can be solved like this:
HTML:
<table>
<tr class="odd"><td>Product 1</td></tr>
<tr class="trigger"><td>> Product 2</td></tr>
<tr class="even"><td> Information 1</td></tr>
<tr class="even"><td> Information 2</td></tr>
<tr class="odd"><td>Product 3</td></tr>
<tr class="even"><td>Product 4</td></tr>
</table>
JavaScript:
$(document).ready(function() {
$(".trigger").click(function() {
$(".even").toggle();
});
});
JSFiddle
jQuery Toggle Documentation
I don't know to explain to you why this is happening, but you need to check if css display property is set to none or it is empty. So this will trigger your function from the first time, otherwise it will go to "else", and then trigger on the next click.
So you need to check the following conditions:
if( el && el.style.display === 'none' || el.style.display === '')

Categories