After browsing online for tutorials on Javascript show/hide I could only find examples on where all the columns were by default visible. I'm looking for a way to have some columns hidden by default (and allow them to be toggled on via a checkbox) and to have some columns shown by default (and allow them to be toggled off via a checkbox).
Is this possible?
For reference my table structure is as follows:
<table>
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mike</td>
<td>Dancer</td>
</tr>
</tbody>
</table>
Pure javascript:
HTML
<input type="checkbox" onclick="showhide(1, this)" checked="checked" /> Name<br />
<input type="checkbox" onclick="showhide(3, this)" checked="checked" /> Job<br />
JS
function showhide(column, elem){
if (elem.checked)
dp = "table-cell";
else
dp = "none";
tds = document.getElementsByTagName('tr');
for (i=0; i<tds.length; i++)
tds[i].childNodes[column].style.display = dp;
}
Pure JS fiddle example
Please consider using a javascript library as JQuery for such trivial things. You code could be as simple as:
HTML
<input type="checkbox" data-col="1" checked="checked" /> Name<br />
<input type="checkbox" data-col="2" checked="checked" /> Job<br />
jQuery JS:
$(function(){
$(':checkbox').on('change', function(){
$('th, td', 'tr').filter(':nth-child(' + $(this).data('col') + ')').toggle();
});
});
jQuery Fiddle example
Here's the toggle function (using jQuery):
function toggleColumns(column, state) {
var cells = $("table").find("th, td").filter(":nth-child(" + column + ")");
if (state)
cells.hide();
else
cells.show();
}
If you need that column hidden by default, you can call this function during onLoad.
Example http://jsfiddle.net/nynEd/
in your css you should have something like
.hidden{
display:none;
}
.shown{
display:block;
}
then in your html you should have something like
<table>
<thead>
<tr>
<th id="th1" class="shown">Name</th>
<th id="th2" class="shown">Job</th>
</tr>
</thead>
<tbody>
<tr>
<td id="td1" class="shown">Mike</td>
<td id="td2" class="shown">Dancer</td>
</tr>
</tbody>
</table>
you then have to implement a togle method that will change the visibility of the column
//id should be passhed as 1, 2, 3 so on...
function togleTable(id){
if(document.getElementById("th"+id).className == "shown"){
document.getElementById("th"+id).className = "hidden";
}
if(document.getElementById("td"+id).className == "shown"){
document.getElementById("td"+id).className = "hidden";
}
if(document.getElementById("th"+id).className == "hidden"){
document.getElementById("th"+id).className = "shown";
}
if(document.getElementById("td"+id).className == "hidden"){
document.getElementById("td"+id).className = "shown";
}
}
and then in the compobox onChange() event you should call the togleTable function passing as id the number of the row you want to show/hide
this is a good place to start i think.
Have fun
UPDATED
if you want to have more than one class for your rows dont forget you can also use this:
document.getElementById('id').classList.add('class');
document.getElementById('id').classList.remove('class');
There are many way out for this my option is using basic jquery functions like,
<input type="checkbox" id="opt1" checked/>col 1
<input type="checkbox" id="opt2"/>col 2
<table border="1" cellpadding="5">
<thead>
<tr>
<th>Name</th>
<th>Job</th>
<th id="col1">col 1</th>
<th id="col2">col 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mike</td>
<td>Dancer</td>
<td class="data1">data 1</td>
<td class="data2">data 2</td>
</tr>
</tbody>
</table>
This is your HTML code,
$(document).ready(function() {
if($("#opt1").is(":checked")){
$("#col1").show();
$(".data1").show();
}else{
$("#col1").hide();
$(".data1").hide();
}
if($("#opt2").is(":checked")){
$("#col2").show();
$(".data2").show();
}else{
$("#col2").hide();
$(".data2").hide();
}
$("#opt1").live('click', function() {
if($("#opt1").is(":checked")){
$("#col1").show();
$(".data1").show();
}else{
$("#col1").hide();
$(".data1").hide();
}
});
$("#opt2").live('click', function() {
if($("#opt2").is(":checked")){
$("#col2").show();
$(".data2").show();
}else{
$("#col2").hide();
$(".data2").hide();
}
});
});
This is a java-script code.
Please find working example
The columns which you want to hide should have attribute style="display:none" initially
Related
I have an admin users table on a web app I'm building, and I want the admins to be able to make other people admins, validate, and delete accounts. But to make it mobile friendly, I want to hide two columns on mobile, but also provide a button for the user with the option of seeing everything if they want to. The issue is, it takes three button pushes to reveal the whole table (when it should only be one), and the button won't let me reverse the action. Here is the JS code:
const showTable = document.getElementById("showTable");
showTable.addEventListener("click", function() {
const hiddens = document.getElementsByClassName("tableHide");
for (h of hiddens) {
if (h.classList.contains("tableHide")) {
h.classList.remove("tableHide");
showTable.innerText = "Hide Table";
} else {
h.classList.add("tableHide");
}
}
});
.tableHide {
display: none;
}
<button type='button' id='showTable'>Show Table</button>
<table>
<thead>
<th>First Name</th>
<th class='tableHide'>Last Name</th>
<th class='tableHide'>Username</th>
<th>Validated</th>
<th>Admin</th>
<th></th>
</thead>
<tbody>
<tr id='1'>
<td>Joe</td>
<td class='tableHide'>Bob</td>
<td class='tableHide'>joebob#gmail.com</td>
<td><input type='checkbox' id='validated'><label for='validated'></label></td>
<td><input type='checkbox' id='isadmin'><label for='isadmin'></label></td>
<td class='delButCont'><button type='button' class='deleteButtons'>Delete</button></td>
</tr>
<tr id='2'>
<td>Bob</td>
<td class='tableHide'>Joe</td>
<td class='tableHide'>bobjoe#gmail.com</td>
<td><input type='checkbox' id='validated'><label for='validated'></label></td>
<td><input type='checkbox' id='isadmin'><label for='isadmin'></label></td>
<td class='delButCont'><button type='button' class='deleteButtons'>Delete</button></td>
</tr>
</tbody>
</table>
And a working JS fiddle with the issue: https://jsfiddle.net/7oh6rch3/1/
Where did I mess up in my logic?
Your mistake was the way you selected the HTML Elements and the way you assigned / removed the CSS classes. I'd use two css classes to solve this:
const showTable = document.getElementById("showTable");
showTable.addEventListener("click", function() {
const hiddens = document.getElementsByClassName("tableHide");
for (h of hiddens) {
if (h.classList.contains("mobile")) {
h.classList.remove("mobile");
showTable.innerText = "Hide Table";
} else {
h.classList.add("mobile");
}
}
this.innerHTML = this.innerHTML == 'Show Table' ? 'Hide Table' : 'Show Table';
})
.mobile
{
display: none;
}
<button type='button' id='showTable'>Show Table</button>
<table>
<thead>
<th>First Name</th>
<th class='tableHide mobile'>Last Name</th>
<th class='tableHide mobile'>Username</th>
<th>Validated</th>
<th>Admin</th>
<th></th>
</thead>
<tbody>
<tr id='1'>
<td>Joe</td>
<td class='tableHide mobile'>Bob</td>
<td class='tableHide mobile'>joebob#gmail.com</td>
<td><input type='checkbox' id='validated'><label for='validated'></label></td>
<td><input type='checkbox' id='isadmin'><label for='isadmin'></label></td>
<td class='delButCont'><button type='button' class='deleteButtons'>Delete</button></td>
</tr>
<tr id='2'>
<td>Bob</td>
<td class='tableHide mobile'>Joe</td>
<td class='tableHide mobile'>bobjoe#gmail.com</td>
<td><input type='checkbox' id='validated'><label for='validated'></label></td>
<td><input type='checkbox' id='isadmin'><label for='isadmin'></label></td>
<td class='delButCont'><button type='button' class='deleteButtons'>Delete</button></td>
</tr>
</tbody>
</table>
also updated your fiddle:
https://jsfiddle.net/7oh6rch3/2/
That's because the result of document.querySelectorAll is a live collection, so every time you remove the class tableHide from an element - it is also removed from the collection, which makes for skip an additional element.
You could copy the elements to an array to preserve the result of selection (to make it no live):
const hiddens = [...document.getElementsByClassName("tableHide")];
I have an array of checkboxes in html with some data in table as following
<table border=1 id='products'>
<tr><td>item id</td><td>item Name</td><td>item Price</td></tr>
<tr><td><input type='checkbox' id='p[]' name='prices[]' onClick='getPrice()'></td><td>Rice</td><td>300</td></tr>
<tr><td><input type='checkbox' id='p[]' name='prices[]' onClick='getPrice()'></td><td>Sugar</td><td>200</td></tr>
<tr><td><input type='checkbox' id='p[]' name='prices[]' onClick='getPrice()'></td><td>Tea</td><td>100</td></tr>
</table>
how I can get the content of third cell in the same row of table for checked checkbox?
I create a function in javascript getPrice() but i don't know what i should to write in if statment
<script>
function getPrice()
{
if (document.getElementById('p[]').checked)
{
} else {
}
}
</script>
Firstly, I recommend using addEventListener over an onClick attribute - this will give us an event to work with that can be used to target the element without querying a selector.
I'd also recommend storing this data and accessing it in a different way than getting the content of an HTML tag - data attributes are a well supported standard.
I've taken the liberty of tidying up the table markup, too, so it has a semantically correct header and body:
<table border=1 id='products'>
<thead>
<tr>
<th>item id</th>
<th>item Name</th>
<th>item Price</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type='checkbox' data-product='rice' data-price='300'></td>
<td>Rice</td>
<td>300</td>
</tr>
<tr>
<td><input type='checkbox' data-product='sugar' data-price='200'></td>
<td>Sugar</td>
<td>200</td>
</tr>
<tr>
<td><input type='checkbox' data-product='tea' data-price='100'></td>
<td>Tea</td>
<td>100</td>
</tr>
</tbody>
</table>
With this, we can rewrite our JS to add an event listener to each of the inputs:
let inputs = document.querySelectorAll('input[type="checkbox"]')
for (let input of inputs) {
input.addEventListener('click', (event) => {
const product = event.target.dataset.product
const price = event.target.dataset.price
})
}
document.querySelectorAll returns an Array of all elements that match the selector on the page.
We can then iterate over this array to do the same thing to each input - in this case, apply an eventListener.
This eventListener will be for the 'click' event, and the second argument is the function that will be run when the event is triggered.
The argument of this second function is event, which contains all the information about the event. We can use event.target to get the element that was clicked, and then event.target.dataset to get all the data properties of that HTML element.
Using jQuery
let total = 0;
$('.item').on('change', function () {
let newTotal = total;
if ($(this).is(':checked')) {
newTotal = total + Number($(this).parent().parent().find('td:eq(2)').text())
} else {
newTotal = total - Number($(this).parent().parent().find('td:eq(2)').text())
}
total = Math.max(newTotal, 0);
$("#total").text(total);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border=1 id='products'>
<tr><td>item id</td><td>item Name</td><td>item Price</td></tr>
<tr><td><input type='checkbox' class="item"name='prices[]' ></td><td>Rice</td><td>300</td></tr>
<tr><td><input type='checkbox'class="item" name='prices[]' ></td><td>Sugar</td><td>200</td></tr>
<tr><td><input type='checkbox' class="item" name='prices[]' ></td><td>Tea</td><td>100</td></tr>
</table>
Total: <span id="total">0</span>
You need to get the event object (e). The event object target, is the clicked element. Get the checked property of the target for the if/else. If it's checked, using closest we can get to the tr, and find the requested child:
document.querySelectorAll('#products [type=checkbox]')
.forEach(function(input) {
input.addEventListener('click', getPrice);
});
function getPrice(e) {
if(e.target.checked) {
console.log(e.target.closest('tr').children[2].innerText);
} else {
console.log('not checked');
}
}
<table border=1 id='products'>
<tr>
<td>item id</td>
<td>item Name</td>
<td>item Price</td>
</tr>
<tr>
<td><input type='checkbox' id='p[]' name='prices[]'></td>
<td>Rice</td>
<td>300</td>
</tr>
<tr>
<td><input type='checkbox' id='p[]' name='prices[]'></td>
<td>Sugar</td>
<td>200</td>
</tr>
<tr>
<td><input type='checkbox' id='p[]' name='prices[]'></td>
<td>Tea</td>
<td>100</td>
</tr>
</table>
Here's my approach :
function getPrice()
{
var checkedValue=0;
var inputElements = document.getElementsByClassName('checkbox');
for(var i=0; inputElements[i]; ++i){
if(inputElements[i].checked){
checkedValue += parseFloat(inputElements[i].value);
}
}
alert(checkedValue);
}
<table border=1 id='products'>
<tr><td>item id</td><td>item Name</td><td>item Price</td></tr>
<tr><td><input class="checkbox" type='checkbox' id='p-1' name='prices[]' onClick='getPrice()' value="300" ></td><td>Rice</td><td>300</td></tr>
<tr><td><input class="checkbox" type='checkbox' id='p-2' name='prices[]' onClick='getPrice()' value="200"></td><td>Sugar</td><td>200</td></tr>
<tr><td><input class="checkbox" type='checkbox' id='p-3' name='prices[]' onClick='getPrice()' value="100"></td><td>Tea</td><td>100</td></tr>
</table>
since this uses querySelectorAll, this requires a relatively modern browser
first, get the checked checkbox and change it to Array so that we can map it:
var chk = Array.prototype.slice.call(document.querySelectorAll('[type=checkbox]:checked'));
then map it to get the neighboring td content
var vals = chk.map(function(c){
// c is the checkbox,
// its parent is the TD that contains the checkbox,
// the TD's parent is the TR that the checkbox reside
// the children of the TR is the TDs that we are looking for
// since you need to get the third column then get the third TD (start from 1, not 0)
// get the third textContent
return c.parentNode.parentNode.childNodes[3].textContent;
});
whit this, you get an array of the selected checkbox's third column
you can console.log(vals) to see the content
here's a sample https://jsfiddle.net/665ap2u7/3/
I'm using material desigin lite in my website
I have implemented this example:
http://www.getmdl.io/components/index.html#tables-section
<table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
<thead>
<tr>
<th class="mdl-data-table__cell--non-numeric">Material</th>
<th>Quantity</th>
<th>Unit price</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
<td>25</td>
<td>$2.90</td>
</tr>
<tr>
<td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
<td>50</td>
<td>$1.25</td>
</tr>
<tr>
<td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
<td>10</td>
<td>$2.35</td>
</tr>
</tbody>
</table>
my question is how to handle the check box in the table , they are added by the class : .mdl-data-table--selectable
there is no Id or class for them so what is the way to use them in javascript or sql server (deleting rows what i'm trying to implement)
You could check if they're are clicked with a jquery on method, why am not using the normal .click is to because of event delegation. Jquery docs do a perfect job explaining that.
Before I explain how I did it I will have a snippet that you can immediately play with under my explanation.
I basically used inspect element to look at the tables structure and it looked something like this
<tr>
<td>
<label>clickable checkbox code</label>
</td>
<td>Acrylic</td>
<td>25</td>
<td>$2.90</td>
With that information, we can do a lot. I personally used this to listen to clicks.
$(document).on("click",".mdl-checkbox__ripple-container.mdl-js-ripple-effect.mdl-ripple--center", function() { /* Code here*/ });
And with jquery parents & children methods we can achieve a lot, like read the content of all the table data with the following code in our click event listener
foo = $(this).parents().eq(2).children().text();
Or we can perhaps delete a whole row?
$(this).parents().eq(2).fadeOut();
What that would do is, look at the clicked checkbox using "this" as reference. Then go to levels up and remove a whole row.
<tr><!-- eq 2 -->
<td> <!-- eq 1 -->
<label>clickable checkbox code</label>
</td>
<td>Acrylic</td>
<td>25</td>
<td>$2.90</td>
Or we can check for the content of a specific child like this
var secondChildContent = $(this).parents().eq(2).children().eq(2).text();
Where secondChildContent will be return the content. You can always change the eq (The one after children) value to the desired child number you want. In the following case secondChildContent would return "Acrylic"
<tr>
<td> <!-- eq 1 -->
<label>clickable checkbox code</label>
</td>
<td>Acrylic</td> <!-- eq 2 -->
<td>25</td> <!-- eq 3 -->
<td>$2.90</td> <!-- eq 4 -->
$(document).ready(function() {
$(document).on("click", ".mdl-checkbox__ripple-container.mdl-js-ripple-effect.mdl-ripple--center", function() {
//Removing row
$(this).parents().eq(2).delay(500).fadeOut(300);
var secondChildContent = $(this).parents().eq(2/*child number*/).children().eq(2).text();
var allChildrenContent = $(this).parents().eq(2).children().text();
var parentID = $(this).parents().eq(2).attr('id');
//Removing table on click of first checkbox
if (parentID == "header") {
$("#mdlTable").fadeOut(1000);
$("#log").html("<b>Table removed!</b>");
} else {
//Don't pay attention to this
$("#log").html(
"<b>Second child content is: </b>" + secondChildContent +
"<br><b>All children content is: </b>" + allChildrenContent
)
}
});
});
#log,
#mdlTable {
margin: 1% 1% 1% 1%;
}
<!DOCTYPE html>
<html>
<head>
<title>Table</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.indigo-pink.min.css">
<script src="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
<table id="mdlTable" class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
<thead>
<tr id="header">
<th class="mdl-data-table__cell--non-numeric">Material</th>
<th>Quantity</th>
<th>Unit price</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
<td>25</td>
<td>$2.90</td>
</tr>
<tr>
<td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
<td>50</td>
<td>$1.25</td>
</tr>
<tr>
<td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
<td>10</td>
<td>$2.35</td>
</tr>
</tbody>
</table>
<div id="log"></div>
</body>
When a checkbox is selected, the tr gets the class "is-checked" with Material Design Lite.
So your jquery can be like this:
$("table").find("tr.is-checked").each(function(){
// Do some stuff!
});
Update: Just read that the class "mdl-data-table--selectable " is being deprecated... This is the article on github
You can use this OnClick API function.
It uses like Android onClickListener, but it is for JavaScript.
TablesOnClickListener = function() {
var fun;
this.setOnClickListener = function(listener) {
fun = listener;
$(document).on("click", ".mdl-checkbox__ripple-container.mdl-js-ripple-effect.mdl-ripple--center", function() {
//$(this).parents().eq(2).delay(500).fadeOut(300);
var secondChildContent = $(this).parents().eq(2 /*child number*/ ).children().eq(2).text();
var allChildrenContent = $(this).parents().eq(2).children().text();
var parentID = $(this).parents().eq(2).attr('id');
fun({
sen: secondChildContent,
text: allChildrenContent,
id: parentID
});
});
}
How to use:
Step 1: create new TablesOnClickListener
var tocl = new TablesOnClickListener()
Step 2: set Item OnClickListener
tocl.setOnClickListener(function(data){
console.log(data);
});
Now your Tables Item Listener are all set!
I have a table that I would like to dynamically hide/reveal rows in, based on checkboxes at the top.
I would like to do this without jQuery, just vanilla Javascript.
I have seen numerous methods on this site and others, but always snippets of code,not complete working examples.
I don't want to give each row a separate div name, or whatever, I am assuming there is a way I can do this with a common class for the 3 types of rows I want to hide/reveal.
Can anyone please show me a working example which allows checkboxes to hide/show multiple rows from a table with vanilla Javascript?
Given HTML like the following:
<table>
<thead>
<tr>
<td>
<label>
<input type="checkbox" class="show" value="north" checked />North</label>
</td>
</tr>
<tr>
<td>
<label>
<input type="checkbox" class="show" value="south" checked />South
</label>
</td>
</tr>
<tr>
<td>
<label>
<input type="checkbox" class="show" value="outOfArea" checked />Out of area
</label>
</td>
</tr>
</thead>
<tbody>
<tr class="north">
<td>North One</td>
</tr>
<tr class="north">
<td>North Two</td>
</tr>
<tr class="outOfArea">
<td>Out-of-area One</td>
</tr>
<tr class="south">
<td>South One</td>
</tr>
<tr class="south">
<td>South Two</td>
</tr>
<tr class="north">
<td>North Three</td>
</tr>
<tr class="north">
<td>North Four</td>
</tr>
<tr class="south">
<td>South Three</td>
</tr>
<tr class="outOfArea">
<td>Out-of-area Two</td>
</tr>
</tbody>
</table>
The following jQuery seems to do as you seem to describe:
$('thead input[type=checkbox]').change(function(){
var self = this;
$(self).closest('table').find('tbody tr').filter('.' + self.value).toggle(self.checked);
});
JS Fiddle demo.
As it seems that you'd prefer a plain-JavaScript approach, I'd suggest the following (to work on the same HTML as posted above):
function toggle (e) {
var self = e.target,
toggleClass = '.' + self.value,
toToggle = document.querySelectorAll(toggleClass);
for (var i = 0, len = toToggle.length; i < len; i++) {
toToggle[i].style.display = self.checked ? 'table-row' : 'none';
}
}
var thead = document.querySelector('thead');
thead.addEventListener('change', toggle);
JS Fiddle demo.
References:
jQuery:
Attribute-equals ([attribute="value"]) selector.
change().
closest().
find().
filter().
toggle().
Plain JavaScript:
document.querySelector().
document.querySelectorAll().
EventTarget.addEventListener().
Looks like you are describing something along the lines of this example
I have the following table. I want to copy Id value on the seleced row to the text box. If I click on link "Select" in the first row the text box value will 0001.
If the table needs modification to get result better and faster, please leave your suggestion.
<div>
<input id="selectedId" type="text" />
</div>
<table cellspacing="1" class="tablesorter" id="nameList">
<thead>
<tr>
<th class="header">Name</th>
<th class="header">Id</th>
<th class="header">Gender</th>
<th>Select</th>
</tr>
</thead>
<tbody>
<tr>
<td>Akom Smith</td>
<td>0001</td>
<td>M</td>
<td>Select</td>
</tr>
<tr>
<td>Amara Sahara</td>
<td>0002</td>
<td>F</td>
<td>Select</td>
</tr>
<tr>
<td>John Lache</td>
<td>0003</td>
<td>M</td>
<td>Select</td>
</tr>
</tbody>
</table>
try this,
$('a.click-to-select').click(function() {
var id = $(this).closest('tr').find('td').eq(1).text();
$('#selectedId').val(id);
return false;
});
simple cool demo
added notes for the comment below.
$('a.click-to-select').click(function() {
var id = $(this).closest('tr').find('td.id').text();
$('#selectedId').val(id);
return false;
});
updated demo
Well, you know your key is the second td in the row. You can use the :nth-child selector like this:
<script type="text/javascript">
var getUniqueId = function() {
return $('td:nth-child(2)').text();
}
</script>
Of course you need a way to identify the correct , but I assume the code is supposed to be called from each and there you can use the parent selector.
Otherwise I'd put an id attribute in each row to make selecting easier.