Toggle Function with Button Onclick - javascript

I had create a table with two method of toggle function, first toggle is toggle table row with its specific ID and second toggle is toggle all the table row. However, if i click on first toggle at first parent row, and then when i click on second toggle, the child of first parent will hide, where it suppose follow other parent show their child and then click again to hide the child. And if all child is shown, the image also should change from details_open.png become details_close.png
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="w3.css" rel="stylesheet" />
<body>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function toggle(thisname, image) {
var path = image.src;
var filename = path.match(/.*\/([^/]+)\.([^?]+)/i)[1];
if (filename == 'details_open') {
image.src = 'details_close.png';
}
if (filename == 'details_close') {
image.src = 'details_open.png';
}
tr = document.getElementsByTagName('tr')
for (i = 0; i < tr.length; i++) {
if (tr[i].getAttribute(thisname)) {
if (tr[i].style.display == 'none') {
tr[i].style.display = '';
} else {
tr[i].style.display = 'none';
}
}
}
}
$(function() {
$('#btn').click(function(e) {
e.preventDefault();
$('.td1').toggle();
});
});
</script>
<input type="button" id="btn" style="color:red" name=btn value="Toggle Child Accessories">
<table class="w3-table-all">
<thead>
<tr>
<td onclick="toggle(1,open_1);">
<center><img id="open_1" src="details_open.png" style="width:20px;cursor: pointer;"></center>
</td>
<td> A </td>
<td> B </td>
</tr>
</thead>
<thead>
<tr 1=fred style='display:none;' class='td1' id='td1'>
<td> </td>
<td> C </td>
<td> D </td>
</tr>
</thead>
<thead>
<tr>
<td onclick="toggle(2,open_2);">
<center><img id="open_2" src="details_open.png" style="width:20px;cursor: pointer;"></center>
</td>
<td> E </td>
<td> F</td>
</tr>
</thead>
<thead>
<tr 2=fred style='display:none;' class='td1' id='td1'>
<td> </td>
<td> G </td>
<td> H </td>
</tr>
</thead>
</table>
</body>
</html>

If i understand correcly your need, you just need to control your rows's visibility to force toggle to hide or show all with his parameter display http://api.jquery.com/toggle/#toggle-display
$('#btn').click(function(e) {
e.preventDefault();
var display = true;
if ($('.td1:visible').length == $('.td1').length) {
display = false;
}
$('.td1').toggle(display);
});
https://codepen.io/anon/pen/xJymRr?editors=1010
I hope this will help you

Since you are using jQuery, you can use jquery toggleClass()to swap the images using your css classes. jquery toggleClass. also noticed you have double <body> tag

Related

How can I change background of each table data if the checkbox is checked?

I am trying to make a simple task manager for myself where if I complete doing something I mark the checkbox and the background of that table data changes, and I read that question too: How to change color of my div if check-box is checked?
then I wrote something like this:
var cbs = document.querySelectorAll('input[type=checkbox]');
for (var i = 0; i < cbs.length; i++) {
cbs[i].addEventListener('change', function() {
if (this.checked) {
document.getElementById("box").style.backgroundColor = "green";
} else {
document.getElementById("box").style.backgroundColor = "transparent";
}
});
}
<table border="1">
<tr>
<td id="box">
English<input type="checkbox" name="block" id="block">
</td>
<td id="box">
Math<input type="checkbox" name="block" id="block">
</td>
<td class="box">
Physics<input type="checkbox" name="block" id="block">
</td>
</tr>
</table>
The problem I am facing is only the first box' background gets changed after checking any of 3 checkboxes as bellow. I just want each box background to change only when it is checked.
Change document.getElementById("box") to this.parentElement; getting the click event target is superfluous.
var cbs = document.querySelectorAll('input[type=checkbox]');
for (var i = 0; i < cbs.length; i++) {
cbs[i].addEventListener('change', function() {
if (this.checked) {
this.parentElement.style.backgroundColor = "green";
} else {
this.parentElement.style.backgroundColor = "transparent";
}
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Task Achievement</title>
</head>
<body>
<table border="1">
<tr>
<td id="box">
English<input type="checkbox" name="block" id="block">
</td>
<td id="box">
Math<input type="checkbox" name="block" id="block">
</td>
<td class="box">
Physics<input type="checkbox" name="block" id="block">
</td>
</tr>
</table>
</body>
</html>
Use the event.Target to target the element being checked and then set its parentNode/s style. Your querySelectorAll returns a nodeList, you can use nodeList.forEach() on this function to loop over its list of nodes. Then pass the event into the eventListener and use event.target to get the element that is triggering the event.
Also, not sure why you had script tags in the middle of your HTML, no need for that. Place the script either a the bottom of the body or at the top and place a defer attribute. Read me: Script tags MDN
// # the top of the page in the head tag of the document:
<script defer>//javascript code</script>
// # the bottom of the page just above the body tag
<script>//javascript code</script>
<body>
<html>
var cbs = document.querySelectorAll('input[type=checkbox]');
cbs.forEach(item =>
item.addEventListener('change', e =>
e.target.checked ?
e.target.parentNode.style.backgroundColor = "green" :
e.target.parentNode.style.backgroundColor = "transparent"))
<table border="1">
<tr>
<td id="box">
English<input type="checkbox" name="block" id="block">
</td>
<td id="box">
Math<input type="checkbox" name="block" id="block">
</td>
<td class="box">
Physics<input type="checkbox" name="block" id="block">
</td>
</tr>
</table>
I have made some changes in your code, let me know if it works -
<!DOCTYPE html>
<html lang="en">
<head>
<title>Task Achievement</title>
<script>
function myFunction(item) {
if (item.checked) {
item.parentNode.style.backgroundColor = "green";
} else {
item.parentNode.style.backgroundColor = "transparent";
}
}
</script>
</head>
<body>
<table border="1">
<tr>
<td id="box">
English<input type="checkbox" name="block" id="block" onclick="myFunction(this)">
</td>
<td id="box">
Math<input type="checkbox" name="block" id="block" onclick="myFunction(this)">
</td>
<td class="box">
Physics<input type="checkbox" name="block" id="block" onclick="myFunction(this)">
</td>
</tr>
</table>
</body>
</html>

Element in div gets removed as a child but can't be used again

I am trying to display a hidden table in a div then hide it again with display: none/block toggle. It works. But, I can't get it to appear again once I toggle to display: none to hide it.
HTML:
The HTML has an empty div with id = tableContainer.
Next to it, I have a table with the names of animal families in each cell, along with a button. When the button is clicked, it takes the name of the animal family from that particular cell, finds the table of animal species with that name and switches from display: none to display:block and display it /inside the div. Then, if I click the button again, it toggles the display back to display: none.
When I click a button in another cell, it clears the div and displays the new table.
All good.
But, if I click a button that was previously used, the table that has now gone is no longer available.
I have gone through all sorts of hoops playing with removeChild and all that but no luck. I am currently using innerHTML to clear the div, but I'm missing something with the class name.
Console error says: tabletest2.html:523 Uncaught TypeError: Cannot read property 'classList' of null
at toggle (tabletest2.html:523)
at HTMLButtonElement.onclick (tabletest2.html:72)
So, it seems to me that it can't toggle any more because the table now no longer exists, or I may be wrong with that as I didn't delete the child element (I think).
<body>
<table>
<tbody>
<tr>
<td>Genus</td>
<td>Benthobatis
<button onclick="toggle(this, parentNode.firstChild)">Click me</button></td>
</tr>
<tr>
<td>Genus</td>
<td>Diplobatis
<button onclick="toggle(this, parentNode.firstChild)">Click me</button></td>
</tr>
</tbody>
</table>
<!-- <======== div display container here ================>-->
<div id="tableContainer"></div>
<table id="Benthobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th>Benthobatis</th>
</tr>
<tr>
<td>Benthobatis kreffti</td>
<td>Brazilian Blind Electric Ray</td>
</tr>
</tbody>
</table>
<!-- <==================================-->
<table id="Diplobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th> Diplobatis </th>
</tr>
<tr>
<td>Diplobatis colombiensis</td>
<td>Colombian electric ray</td>
</tr>
</tbody>
</table>
</body>
<script>
function toggle(ele, tableName) {
var myTableDisplayDiv = document.getElementById("tableContainer").childNodes;
if (myTableDisplayDiv.length != 0) {
document.getElementById("tableContainer").innerHTML = "";
}
var myTableName = tableName.textContent;
var myTable = document.getElementById(myTableName);
myTable.classList.toggle("hide");
document.getElementById("tableContainer").appendChild(
document.getElementById(myTableName)
);
}
</script>
<style>
.hide {
display: none;
}
Explanations
"Why are my tables deleted if I'm only changing display option, not removing the child node?".
This destroys everything within:
document.getElementById("tableContainer").innerHTML = "";
This moves the chosen table to #tableContainer:
document.getElementById("tableContainer").appendChild(
document.getElementById(myTableName)
So in three clicks there's nothing left. Of course this is if the table can be identified correctly which it wasn't. The .textContent of .parentNode.firstChild reference was lost because this refers to a global context not the button. This is why on-event attributes (among other various reasons) are discouraged. Although not a critical issue as the ones previously mentioned, you should seriously have some variations to the names:
tableName
myTableName
myTable
myTableDisplayDiv
tableContainer
I'm pretty sure this naming scheme did not facilitate debugging.
Solutions
Before you place a table into #tableContainer where it gets destroyed, make a copy with .cloneNode().
Remove the onclick attributes and either use onclick property (like in the demo) or .addEventListener().
Register an ancestor element of both buttons (i.e. tbody), from there both buttons can be clicked and easily isolated and referenced by using event.target.
Now the reference to the clicked button (event.target) can now be referenced:
var tableName = event.target.parentNode.firstChild.textContent
And then the table can finally be referenced:
var table = document.getElementById(tableName)
Demo
document.querySelector('tbody').onclick = toggle;
function toggle(event) {
var clicked = event.target;
if (clicked.tagName === 'BUTTON') {
var genus = clicked.parentNode.firstChild.textContent;
var table = document.querySelector('#' + genus);
var display = document.getElementById("display");
display.innerHTML = "";
var clone = table.cloneNode(true);
display.appendChild(clone);
clone.classList.toggle('hide');
}
}
.hide {
display: none;
}
<table>
<tbody>
<tr>
<td>Genus</td>
<td>Benthobatis
<button>Click me</button></td>
</tr>
<tr>
<td>Genus</td>
<td>Diplobatis
<button>Click me</button></td>
</tr>
</tbody>
</table>
<!-- <======== div display container here ================>-->
<div id="display"></div>
<table id="Benthobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th>Benthobatis</th>
</tr>
<tr>
<td>Benthobatis kreffti</td>
<td>Brazilian Blind Electric Ray</td>
</tr>
</tbody>
</table>
<!-- <==================================-->
<table id="Diplobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th> Diplobatis </th>
</tr>
<tr>
<td>Diplobatis colombiensis</td>
<td>Colombian electric ray</td>
</tr>
</tbody>
</table>
Your code is kind of complex to understand but if you just want to toggle the table, I think this is the best way.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.hide {
display: none;
}
</style>
</head>
<body>
<div class="table-container">
<button class="toggle-btn">Click me</button>
<table>
<tr>
<td>Genus</td>
<td>Benthobatis</td>
</tr>
<tr>
<td>Genus</td>
<td>Diplobatis</td>
</tr>
</table>
</div>
<script>
const table = document.querySelector('table'),
btn = document.querySelector('.toggle-btn');
btn.addEventListener("click", () => {
table.classList.toggle("hide")
})
</script>
</body>
</html>

Two anchors and two tables, need to show and hide

I have two anchors and two tables, upon clicking anchor 1, I want table1 to appear and on clicking anchor2 table 1 must be closed and table 2 should appear.
My code in JavaScript for toggling between show and hide:
function setTable(what) {
if (document.getElementById(what).style.display == "block") {
document.getElementById(what).style.display = "none";
}
else if (document.getElementById(what).style.display == "none") {
document.getElementById(what).style.display = "block";
}
}
My two anchors:
<td>
I am
</td>
<td>
Photo
</td>
My two table:
<table id="aboutdialog" title="Me mE me!!" style="display:none;" >
<table width="100%" id="stab" style="display:none;width:58%;height: 60%;">
Now it works for me like, on clicking the anchor1 for the first time it shows table 1 and on second click hides table1. Same for anchor2.
But I want upon clicking anchor1 to close table 2 if opened and display table1 alone vice versa for anchor2.
Without jQuery
<td>
I am
</td>
<td>
Photo
</td>
then
function setTable(what, second) {
if (document.getElementById(what).style.display == "block") {
document.getElementById(what).style.display = "none";
} else if (document.getElementById(what).style.display == "none") {
document.getElementById(what).style.display = "block";
document.getElementById(second).style.display = "none";
}
}
Demo: Fiddle
A jQuery solution might look like
<table>
<tr>
<td>
<!--Add a class trigger to the anchor elements-->
I am
</td>
<td>
<!--Add a class trigger to the anchor elements-->
Photo
</td>
</tr>
</table>
<!--Add a class target to the tables elements-->
<table id="aboutdialog" title="Me mE me!!" style="display:none;" class="target">
<tr>
<td>1</td>
</tr>
</table>
<!--Add a class target to the tables elements-->
<table width="100%" id="stab" style="display:none;width:58%;height: 60%;" class="target">
<tr>
<td>2</td>
</tr>
</table>
then
//dom ready handler
jQuery(function () {
var $targets = $('.target');
$('.trigger').click(function () {
var id = $(this).attr('href');
//hide all other target elements
$targets.not(id).hide();
//toggle the display of current element
$(id).toggle()
})
})
Demo: Fiddle
Just replace the function
function setTable(what){
if(what=="aboutdialog"){
document.getElementById("aboutdialog").style.display="block";
document.getElementById("stab").style.display="none";
}
else if(what=="stab"){
document.getElementById("aboutdialog").style.display="none";
document.getElementById("stab").style.display="block";
}
}
You can do something like this:
$('#iam').click(function() {
$(this).closest('#aboutdialog').show().siblings('#stab').hide();
});
$('#photo').click(function() {
$(this).closest('#stab').show().siblings('#aboutdialog').hide();
});
Try using jquery
$(document).ready(function($) {
$('#iam').click(function(){
$('#aboutdialog').show();
$('#stab').hide();
});
$('#photo').click(function(){
$('#stab').show();
$('#aboutdialog').hide();
});
});
live example is here >>
Simple with the jquery library :
$('#iam').click(function(){
$('#aboutdialog').show().siblings('table').hide();
});
$('#photo').click(function(){
$('#newdialog').show().siblings('table').hide();
});
html
I am</td>
<td>Photo</td>
<table id="aboutdialog" title="Me mE me!!" style="display:none;" >
<tr><th>abc</th></tr>
</table>
<table id="newdialog" title="Me mE me!!" style="display:none;" >
<tr><th>yaskjd</th></tr>
</table>
$(document).ready(function() {
var options = {'iam': 'aboutdialog', 'photo': 'stab'};
$('#iam, #photo').on('click', function() {
$('#aboutdialog, #stab').hide();
$('#' + options.($(this).attr('id'))).show();
});
});

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>

Javascript table menu opens up with all tables already collapsed, why?

I have a simple menu with collapsing tables, working with Javascript. My problem is when I open it in the browser it comes up with all tables already collapsed! How can I open it with the menu sections "closed", to then collapse each section only onclick? I know it's in the Javascript but I'm new to it so bear with me... Thank you!
Here's the basic code:
<head>
<script>
function doCollapse(rowname)
{
theElement = document.getElementById(rowname);
if(theElement.style.display == 'none'){
theElement.style.display = '';
}else {
theElement.style.display = 'none';
}
return false;
}
</script>
</head>
<body>
<table>
<tr>
<td>
<p1 onClick=" doCollapse ('r1');">JQ</p>
</td></tr>
<tr>
<td id="r1">ver biografia</td></tr>
<tr>
<td>
<p2 onClick=" doCollapse ('r2');">Obras</p>
</td>
</tr>
<tr>
<td id="r2">lista</td></tr>
<tr>
<td>
<p3 onClick=" doCollapse ('r3');">Exposições</p>
</td>
</tr>
<tr>
<td id="r3">lista</td></tr>
</table>
</body>
</code>
Since you are using pure javascript and not a library like jquery, I'd suggest a couple of modification to easily target your elements. Try to put the items to show and hide inside a span so you can use document.getElementsByTagName and then add the Id to those spans rather than on td. My concern was that you have more td in your code, so you using document.getElementsByTagName would affect them as well, which is not what you need. However, you need to be careful that my solution would also suffer from that side effect if you have more spans in your code, which is likely, so you need to take this consideration before you implement this live. Here is the code and you can see a live demo here
<head>
<script>
function init(){
var numberOfRows = document.getElementsByTagName('span').length;
for (var i = 0; i < numberOfRows; i++){
document.getElementsByTagName('span')[i].style.display = 'none';
}
}
function doCollapse(rowname)
{
theElement = document.getElementById(rowname);
if(theElement.style.display == 'none'){
theElement.style.display = 'inline';
}else {
theElement.style.display = 'none';
}
return false;
}
</script>
</head>
<body onload="init()">
<table>
<tr>
<td>
<p onClick=" doCollapse ('r1');">JQ</p>
</td></tr>
<tr>
<td><span id="r1">ver biografia</span></td></tr>
<tr>
<td>
<p onClick=" doCollapse ('r2');">Obras</p>
</td>
</tr>
<tr>
<td><span id="r2">lista</span></td></tr>
<tr>
<td>
<p onClick=" doCollapse ('r3');">Exposições</p>
</td>
</tr>
<tr>
<td><span id="r3">lista</span></td></tr>
</table>

Categories