I have created a JQuery routine to check all the checkboxes on a page using a master checkbox.
I am generally happy with this function and it is serving me well but it is not very generic and I have now copy/pasted it into a number of pages in my solution.
I also have a couple of pages where I have copy/pasted it twice because I have two groups of checkboxes on one page that need to be controlled independently. This is not good!
I would really love to genericise this and stuff it away in my main .js script file but I do not know where to start! I would love to be able to use a system of classes to tell JQuery which set of checkboxes is controlled by which master checkbox.
Can you help please? I feel that a solution would boost my jquery ability massively!
(n.b. please excuse the classes in tags, that is down to the nasty way that asp.net renders checkboxes)
$(function () {
$(".checkAllLeft").click(function () {
if ($(".checkAllLeft").is(':checked')) {
$(".LeftCheckbox").each(function () {
var checkbox = $(this).find("input")
if (checkbox.prop("disabled") == false) { checkbox.prop("checked", true); }
});
} else {
$(".LeftCheckbox").each(function () {
var checkbox = $(this).find("input")
if (checkbox.prop("disabled") == false) { checkbox.prop("checked", false); }
});
}
});
});
$(function () {
$(".checkAllRight").click(function () {
if ($(".checkAllRight").is(':checked')) {
$(".RightCheckbox").each(function () {
var checkbox = $(this).find("input")
if (checkbox.prop("disabled") == false) { checkbox.prop("checked", true); }
});
} else {
$(".RightCheckbox").each(function () {
var checkbox = $(this).find("input")
if (checkbox.prop("disabled") == false) { checkbox.prop("checked", false); }
});
}
});
});
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<table border=1>
<tr>
<td>Check All Left<br /><input type="checkbox" class="checkAllLeft"></td>
<td>Check All Right<br /><input type="checkbox" class="checkAllRight"></td>
</tr>
<tr>
<td><span class="LeftCheckbox"><input type="checkbox" ></span></td>
<td><span class="RightCheckbox"><input type="checkbox" ></span></td>
</tr>
<tr>
<td><span class="LeftCheckbox"><input type="checkbox" ></span></td>
<td><span class="RightCheckbox"><input type="checkbox" ></span></td>
</tr>
<tr>
<td><span class="LeftCheckbox"><input type="checkbox" ></span></td>
<td><span class="RightCheckbox"><input type="checkbox" ></span></td>
</tr>
</table>
</body>
To achieve this you can use DOM traversal to find all the checkboxes within the same container (ie. the same column) as the 'check all' option, then set them to the same value. Something like this:
$(".check-all").change(function() {
var tdIndex = $(this).closest('td').index() + 1;
$('table tr td:nth-child(' + tdIndex + ') :checkbox').prop('checked', this.checked);
});
table,
th,
td {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<table>
<tr>
<td>Check All Left<br /><input type="checkbox" class="check-all" /></td>
<td>Check All Right<br /><input type="checkbox" class="check-all" /></td>
</tr>
<tr>
<td><span><input type="checkbox" /></span></td>
<td><span><input type="checkbox" /></span></td>
</tr>
<tr>
<td><span><input type="checkbox" /></span></td>
<td><span><input type="checkbox" /></span></td>
</tr>
<tr>
<td><span><input type="checkbox" /></span></td>
<td><span><input type="checkbox" /></span></td>
</tr>
</table>
There's a couple of other things to note. Firstly, you don't need to use a document.ready event per function call; you can place all logic within a single one. Secondly the border attribute on table elements is very outdated. Use CSS instead.
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 2 years ago.
I have a function that changes a table in a list, so far so good, but when the function changes in js it stops working, if I reload the page it works but if I change the DOM nothing. Can you help me?
$(document).ready(function() {
$('#table-list tbody tr').click(function(event) {
if(event.target.type == 'checkbox'){
}else{
$(':checkbox', this).trigger('click');
}
});
$('#ul-list li').click(function(event) {
var checkbox_type = $(event.target).find("input[type='checkbox']").attr('name');
if(checkbox_type){
$(':checkbox', this).trigger('click');
}
});
});
These are the two events that should always be active. But if I change the table to ul not it works
So let me explain better, I have a table like this:
<table id="table-list">
<tbody>
<tr>
<td><input type="checkbox" name="1" /></td>
</tr>
<tr>
<td><input type="checkbox" name="3" /></td>
</tr>
</tbody>
</table>
Then by clicking on a button I convert it to a list by removing the table from the DOM and inserting this:
<ul id="ul-list">
<li>
<input type="checkbox" name="1" />
</li>
<li>
<input type="checkbox" name="3" />
</li>
</ul>
Now I want if I try to click on the list this function should start:
$('#ul-list li').click(function(event) {
var checkbox_type = $(event.target).find("input[type='checkbox']").attr('name');
if(checkbox_type){
$(':checkbox', this).trigger('click');
}
});
instead no.
If you rewrite the DOM, you need to DELEGATE
$('#ul-list').on("click","li",function(event) {
I though you might need this - see the stopPropagation when the target is one of the checkboxes itself:
function findCheck(e) {
const tgt = e.target;
if (tgt.type && tgt.type === "checkbox") {
e.stopPropagation()
} else {
const $row = $(e.currentTarget);
$row.find("[type=checkbox]").each(function() {
$(this).click();
//$(this).attr("checked", !$(this).attr("checked"))
});
}
}
$(function() {
let $ul = $("<ul/>", {
id: "ul-list"
});
const $tbl = $("#table-list");
$tbl.find("tr").each(function() {
let $li = $("<li/>")
$("td",this).each(function() {
$li.append($(this).html())
})
$ul.append($li);
})
$tbl.replaceWith($ul)
$('#ul-list').on("click", "li", findCheck)
})
tr {
background-color: red
}
li {
background-color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table-list">
<tbody>
<tr>
<td>1</td>
<td><input type="checkbox" name="1" /></td>
<td><input type="checkbox" name="2" /></td>
</tr>
<tr>
<td>2</td>
<td><input type="checkbox" name="3" /></td>
</tr>
</tbody>
</table>
I have a simple table as following which has checkboxes in the first and last columns of each row.
<table style="width:100%">
<tr>
<td><input type="checkbox" /></td>
<td>Smith</td>
<td><input type="checkbox" /></td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>Jackson</td>
<td><input type="checkbox" /></td>
</tr>
</table>
Problem:
When I check/uncheck the last column's checkbox in the first row, the first column's checkbox in the same row should be checked/unchecked. Similarly, if I check/uncheck the first column's checkbox, the corresponding last column checkbox should be checked/unchecked.
How can I achieve this in javascript? Any help or pointers would be really appreciated.
Here is the fiddle which I have created: Fiddle
Thank you.
Use :checkbox selector to select input type checkbox elements.
Try this:
$(':checkbox').on('change', function() {
$(this).closest('tr').find(':checkbox').prop('checked', this.checked);
});
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table style="width:100%">
<tr>
<td>
<input type="checkbox" />
</td>
<td>Smith</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Jackson</td>
<td>
<input type="checkbox" />
</td>
</tr>
</table>
Using JavaScript:
Use querySelectorAll('[type="checkbox"]') to find checkbox elements.
Try this:
var checkboxes = document.querySelectorAll('[type="checkbox"]');
[].forEach.call(checkboxes, function(checkbox) {
checkbox.onchange = function() {
var currentRow = this.parentNode.parentNode;
var cbElems = currentRow.querySelectorAll('[type="checkbox"]');
[].forEach.call(cbElems, function(cb) {
cb.checked = this.checked;
}.bind(this))
};
});
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
<table style="width:100%">
<tr>
<td>
<input type="checkbox" />
</td>
<td>Smith</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Jackson</td>
<td>
<input type="checkbox" />
</td>
</tr>
</table>
One possible Javascript solution to toggle Checkboxes on Table Row click is shown below:
HTML
<table id = "Table1">
<tr>
<td><input type="checkbox" /></td>
<td>John Smith</td>
<td><input type="checkbox" /></td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>Anna Warner</td>
<td><input type="checkbox" /></td>
</tr>
</table>
CSS
table, th, td{
border: 1px solid #c0c0c0;
border-collapse: collapse;
}
table{width:100%;}
Javascript
// row click will toggle checkboxes
row_OnClick("Table1")
function row_OnClick(tblId) {
try {
var rows = document.getElementById(tblId).rows;
for (i = 0; i < rows.length; i++) {
var _row = rows[i];
_row.onclick = null;
_row.onclick = function () {
return function () {selectRow(this);};
}(_row);
}
}
catch (err) { }
}
function selectRow(row) {
row.cells[0].firstChild.checked = !row.cells[0].firstChild.checked;
row.cells[2].firstChild.checked = row.cells[0].firstChild.checked;
}
Working jsfiddle demo at: https://jsfiddle.net/t6nsxgnz/
Practical implementation at: http://busny.net
You can further customize this solution pertinent to your task by modifying the selectRow(row) function:
function selectRow(row) {
row.cells[0].firstChild.checked = // add your code for the 1st CheckBox
row.cells[2].firstChild.checked = // add your code for the 2nd CheckBox
}
Another variation of this functionality coded in jQuery can be found in online pop-quiz engine (http://webinfocentral.com), implemented via the follwoing code snippet:
// toggle Checkboxes on row click
$(Table1 tr').click(function (event) {
// find the checkbox in the row
var _chk = $(this).find('input:checkbox');
if (!($(event.target).is("checkbox"))) {
$(_chk).prop('checked', !$(_chk).prop('checked'));
}
});
In this case, Row Click (at any place of the Row) or CheckBox Click events will toggle the state of that particular CheckBox. The state of other CheckBoxes can be synchronized with this one (by using "siblings" property, for example).
Hope this may help.
Script:
$(document).ready(function() {
$(function(){
$("#result").dataTable({
"scrollX" : true,
"ordering" : true,
"order": [[ 1, "asc" ]],
"info" : true,
});
});
$("#all").click(function () {
if ($("#all").is(':checked')) {
$(".checkboxclass").each(function () {
$(this).prop("checked", true);
});
} else {
$(".checkboxclass").each(function () {
$(this).prop("checked", false);
});
}
});
});
HTML:
<table class="tg" id="result" style="width: 100%">
<thead>
<tr>
<th class="tg" style="text-align: center"><input type="checkbox" id="all"
onclick="toggle(this);" /></th>
</tr>
</thead>
<tbody>
<tr th:each="map : ${listID}">
<td class="tg bg" align="center"><input type="checkbox" class="checkboxclass" name="check"
th:id="${map['ID']}" th:value="${map['ID']}" /></td>
</tr>
</tbody>
</table>
Checking on one check box selects all but only limited to current page. It is not working for rest of the pages in pagination
Can anyone help on this issue. Thanks.
Quite likely, you have duplicate IDs; if you have more than one element with the same ID, for example id="all", that gives rise to invalid HTML and you cannot predict how different browsers may handle that. Most will usually pick the first, and ignore the rest of the elements.
Please change:
<input type="checkbox" id="all" onclick="toggle(this);" />
To:
<input type="checkbox" class="all" ....
So that your code would be:
$(".all").on('change', function () {
$(this).closest('table').find('.checkboxclass').prop('checked', this.checked );
});
UPDATE
Thanks for clarifying; I'll leave the above so that your comments where you've clarified this may remain relevant
Here is how you may resolve that issue:
$(function(){
var table = $("#result").dataTable({
"scrollX" : true,
"ordering" : true,
"order": [[ 1, "asc" ]],
"info" : true,
});
});
$("#all").on('click', function () {
var cells = table.api().cells().nodes();
$( cells ).find('.checkboxclass').prop('checked', this.checked);
});
});
//source: https://www.datatables.net/forums/discussion/22728/datatables-1-10-select-all-checkbox-and-hidden-rows-pages
Please note that $(document).ready(function() { .... }); and $(function() { .... }); are different ways of writing the same thing -- no need to nest them.
This worked for me.
if ($("#all").is(':checked')) {
$(".checkboxclass", table.fnGetNodes()).each(function () {
$(this).prop("checked", true);
});
else {
$(".checkboxclass", table.fnGetNodes()).each(function () {
$(this).prop("checked", false);
})
}
you have declared on click toggle function but it is not used. please find the code snippet it helpful to sort out ur issue.
<table class="tg" id="result" style="width: 100%">
<thead>
<tr>
<th class="tg" style="text-align: center">
<input type="checkbox" id="all" />
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tg bg" align="center"><input type="checkbox" class="checkboxclass" name="check" /></td>
<td class="tg bg" align="center"><input type="checkbox" class="checkboxclass" name="check" /></td>
<td class="tg bg" align="center"><input type="checkbox" class="checkboxclass" name="check" /></td>
<td class="tg bg" align="center"><input type="checkbox" class="checkboxclass" name="check" /></td>
</tr>
</tbody>
</table>
$("#all").click(function () {
if (this.checked) {
$('.checkboxclass').each(function () {
this.checked = true;
})
}
else {
$('.checkboxclass').each(function () {
this.checked = false;
})
}
})
I have a table with some row colored as green.Each row have a checkbox.
When I click submit button i need to validate that only green colored row whose checkboxes are not checked should be checked.
No other colored rows and just the green one(#47A347).
Below is my html.Can anyone help me getting the solution.
<form method="post" action="test2.html">
<table>
<tr bgcolor="#47A347" class="rowb">
<td>Hello</td>
<td><input type="checkbox" id="chk" class="linebox"></td>
</tr>
<tr bgcolor="#47A347" class="rowb">
<td>Hello 1</td>
<td><input type="checkbox" id="chk1" class="linebox"></td>
</tr>
<tr class="rowb">
<td>Hello 2</td>
<td><input type="checkbox" id="chk1" class=""></td>
</tr>
<tr>
<td><input type="submit" id="btn" value="Submit"></td>
</tr>
</table>
</form>
I have tried below jquery code.Though it works it fails sometimes.
<script>
jQuery(document).on('click', '#btn', function (event)
{
var rv = true;
$(".rowb").each(function()
{
if($(this).css("background-color") == "rgb(71, 163, 71)")
{
var ischk = 0;
var row = $(this);
if (row.find('input[class="linebox"]').is(':checked') )
{
ischk++;
}
if(ischk==0)
{
rv=false;
}
}
});
if (!rv)
{
alert('Please check');
event.preventDefault();
}
});
</script>
Try this snippet. Should give you an alert for each green checkbox that has not been checked on click of the submit 'btn'. If there is a green row checkbox that has not been checked, the default submit action will be stopped.
$(document).ready(function(){
$('#btn').on('click', function(){
var i = 1;
var error = false;
$(".rowb").each(function() {
ischk = 0;
if($(this).attr("bgcolor") == "#47A347") {
if (!$(this).find('input.linebox').is(':checked') )
{
alert('Please check green checkbox #' + i);
error = true;
}
i++;
}
});
if (error){
event.preventDefault();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form method="post" action="test2.html">
<table>
<tr bgcolor="#47A347" class="rowb">
<td>Hello</td>
<td><input type="checkbox" id="chk" class="linebox"></td>
</tr>
<tr bgcolor="#47A347" class="rowb">
<td>Hello 1</td>
<td><input type="checkbox" id="chk1" class="linebox"></td>
</tr>
<tr class="rowb">
<td>Hello 2</td>
<td><input type="checkbox" id="chk1" class=""></td>
</tr>
<tr>
<td><input type="submit" id="btn" value="Submit"></td>
</tr>
</table>
</form>
Instead of asserting in background-color try checking for bgcolor attribute.
//if($(this).css("background-color") == "rgb(71, 163, 71)")
if( $(this).attr("bgcolor") == "#47A347" )
Here's the full refactored code:
jQuery(document).on('click', '#btn', function (event)
{
var rv = true;
$(".rowb").each(function()
{
if($(this).attr("bgcolor") == "#47A347")
{
if ( !$(this).find('.linebox').is(':checked') )
{
rv = false;
return false
}
}
});
if (!rv)
{
alert('Please check');
event.preventDefault();
}
});
$('#btn').on('click', function(){
var data = {};
var form = $(this).closest('form');
$('[bgcolor="#47A347"]', form).each(function(){
data[this.id] = $(this).find('input').val();
})
});
Note: you didn't provide name attribute for inputs. With name attribute provided you can use jQuery's serialize method to gather form data automatically. To filter out unneeded fields you can temporarily set them to disabled state.
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