Click elsewhere and checkbox is ticked/unticked [duplicate] - javascript

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 1 year ago.
So I have a piece of code to create a table with some data in it. The first column contains checkboxes, other columns are just regular data.
What I want is that when I click anywhere on a random row (except for header), that entire row's background is turning into yellow (initially white) and the checkbox in that row is ticked. If I click again, everything in the row back to its normal (white row and unticked checkbox).
When I click right at the checkbox, everything acts as expected. However, when I click elsewhere, only the background is changed. I have checked the checked attribute of the checkbox and it is changed whenever I click (which is like normal). I don't know why this happens. I have looked through many posts with similar issues but it is not helped. I am only a beginner at Javascript and HTML. Please help me with this. Thank you very much!
function changeColorRow(number) {
var elem = document.getElementsByTagName("tr")[number]
var curr_check = document.getElementsByClassName("checkbox").checked
if (!curr_check) {
elem.style.backgroundColor = "yellow"
document.getElementsByClassName("checkbox").checked = true
} else {
elem.style.backgroundColor = "white"
document.getElementsByClassName("checkbox").checked = false
}
}
<h1>List of companies</h1>
<table id="company">
<tr>
<th>Choose</th>
<th>ID</th>
<th>Company</th>
<th>Website</th>
</tr>
<tr onclick="changeColorRow(1)">
<td><input type="checkbox" class="checkbox"></td>
<td>1</td>
<td>ECOPRO Co., Ltd</td>
<td>http://www.ecoprovn.com</td>
</tr>
<tr onclick="changeColorRow(2)">
<td><input type="checkbox" class="checkbox"></td>
<td>2</td>
<td>WAVINA.COM</td>
<td>http://www.wavina.com</td>
</tr>
</table>

document.getElementsByClassName returns an array like structure, You have to use index to get that particular element at that index.
document.getElementsByClassName("checkbox")
You can get the index of the clicked row as
index = number - 1
const allCheckbox = document.getElementsByClassName("checkbox");
function changeColorRow(number) {
const index = number - 1;
var elem = document.getElementsByTagName("tr")[number]
var curr_check = document.getElementsByClassName("checkbox")[index].checked
if (!curr_check) elem.style.backgroundColor = "yellow"
else elem.style.backgroundColor = "white"
allCheckbox[index].checked = !allCheckbox[index].checked
}
[...allCheckbox].forEach(cb => {
cb.addEventListener("change", (e) => changeColorRow(parseInt(e.target.dataset.index)))
})
tr {
cursor: default;
user-select: none;
}
<h1>List of companies</h1>
<table id="company">
<tr>
<th>Choose</th>
<th>ID</th>
<th>Company</th>
<th>Website</th>
</tr>
<tr onclick="changeColorRow(1)">
<td><input type="checkbox" class="checkbox" data-index="1"></td>
<td>1</td>
<td>ECOPRO Co., Ltd</td>
<td>http://www.ecoprovn.com</td>
</tr>
<tr onclick="changeColorRow(2)">
<td><input type="checkbox" class="checkbox" data-index="2"></td>
<td>2</td>
<td>WAVINA.COM</td>
<td>http://www.wavina.com</td>
</tr>
</table>

Related

Adding a table stops js show/hide from working

I have a show/hide function on a web page where I want to improve the layout, but when I added a new table to put in headers for the data, the show/hide stopped working.
A snippet of the original code is:
<table id="cart-list">
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-12">
<tr class="cl-group">
<td class="cl-sh" title="Show [+] or Hide [-] this lists' products"> </td>
<td colspan="2">Cart List One:
<table id="cl-chg-1" class="cl-other cl-chg">
<tr>
<td>List Name:</td>
<td><input type="text" name="group_name[1]" value="Cart List One" maxlength="255" /></td>
</tr>
<tr>
<td>List Comments:</td>
<td><input type="text" name="group_comments[1]" maxlength="255" /></td>
</tr>
<tr>
<td><button type="button" onclick="cancelGroupEdit();">Cancel</button></td>
<td><button type="submit" name="change" value="1">Go</button></td>
</tr>
</table>
</td>
</tr>
</div>
<tr>
<td>Stuff Here</td>
</tr>
<tr>
<td>Stuff Here</td>
</tr>
</table>
And the js used is
var groups = document.getElementsByClassName("cl-sh");
if (groups) {
for (var i = 0; i < groups.length; i++) {
groups[i].onclick = function() {
this.classList.toggle('cl-a');
var productsDisplay = '';
if (this.classList.contains('cl-a')) {
productsDisplay = 'none';
}
var nextRow = this.parentNode.nextElementSibling;
while (nextRow) {
if (nextRow.classList.contains('cl-group')) {
break;
}
nextRow.style.display = productsDisplay;
nextRow = nextRow.nextElementSibling;
}
}
}
}
A fiddle can be seen here: https://jsfiddle.net/65j1nvpq/1/
The broken function with the additional table code added can be seen here: https://jsfiddle.net/cmgqeLf7/
I don't really understand why having an additional table is breaking the function.
Any suggestions on a fix for this?
What does your JS function do when you click on the +/- cell?
Firstly, it toggles whether the clicked cell contains the cl-a class. Then, it runs through all remaining rows in the same table, showing or hiding them as appropriate, until it finds a row with the class cl-group, or hits the end of the rows in that table.
Note the word same in the last paragraph.
In your first fiddle, you have one table. In your second fiddle, you have two, and the rows you wish to toggle the display of are not in the same table as the toggle button. This is why they are not showing/hiding when you click the toggle button.
I'm not sure exactly what your requirements for showing/hiding rows are, so I'm not going to propose a fix. However, understanding what the problem is may help you to find a fix for yourself.

I have around 17 tables in my HTML document and want them to appear separately when I click on them through a separate button [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have 17 tables in my HTML document. I want them all under a separate button. So the table for the year 2000 under a button that says: Table for year 2000 below! I can do the first one. But when I try to apply the JavaScript code for the button on other tables I keep getting the first table.
This is my JavaScript code:
<script>
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
This is my HTML code for the tables, I'm just showing the first 2 tables because it's 17 times copy paste:
<!--Table for the year 2000 below-->
<button onclick="myFunction()">Table for the year 2000 below!</button>
<div id="myDIV" style="display:none;">
+<table>...
</table>
<br><br><br>
</div>
<!--Table for the year 2001 below-->
<button onclick="myFunction()">Table for the year 2001 below!</button>
<div id="myDIV" style="display:none;">
+<table>...
</table>
<br><br><br>
</div>
Alright so hear me out, I now with a quick Google search that getElementById can only hold one parameter. I got that. I tried to copy my JS code and change the ID in the function and the HTML code, but everytime I try that I can only show the latest table I applied that method to, doesn't matter which button I press.
I have also seen people on this forum use querySelectorAll but that didn't work out for me.
Could someone help me out with this? I expect my method to work, use the same function that works on the first table but keep changing the ID. But clearly it didn't.
Few inputs:
Id should be unique to an element
The event handler should be given some inputs to identity which element (table in this case) it has to work with.
To cover all these, a sample snippet is included to help you further.
Detailed breakdown:
We are attaching a click event handler to all the button elements
We try to identify all button elements using document.querySelectorAll
How do we identity which table to show on a click event? We can put that additional details in data-* attributes. Based on that we are selecting that specific table using document.getElementById
Detailed comments included in the code-base.
window.onload = function() {
// Get all the `button` elements
var buttons = document.querySelectorAll("button");
// To store the current `table`
var currentTable = null;
// Loop over each button element and attach an handler to `click` event
buttons.forEach((element, index, array) => {
element.addEventListener("click", function() {
// Get the associated table using the `data-table` attribute of this button
var tableId = element.getAttribute("data-table");
// Good to go?
if (tableId) {
// Hide the current `table` if we have any displayed
if (currentTable !== null) {
currentTable.style.display = "none";
}
// Store the current table and `display` it
currentTable = document.getElementById(tableId);
currentTable.style.display = "table";
}
});
});
}
table {
display: none;
}
#table1 {
border: 1px solid red;
}
#table2 {
border: 1px solid blue;
}
<button id="btnForTable1" data-table="table1">Show Table 1</button>
<button id="btnForTable2" data-table="table2">Show Table 2</button>
<!-- Table 1 -->
<table id="table1">
<tr>
<th>First name</th>
<th>Last name</th>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
</tr>
</table>
<!-- Table 2 -->
<table id="table2">
<thead>
<tr>
<th>Header content 1</th>
<th>Header content 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Body content 1</td>
<td>Body content 2</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Footer content 1</td>
<td>Footer content 2</td>
</tr>
</tfoot>
</table>

Selecting multiple rows of items in a table

EDIT: I didn't have enough time to ask the question properly. I am rewriting the question with an image.
So, I have a table (shown below):
The data on each row are dynamically filled out.
However, if users want to delete the data (which they can), they have to delete them individually.
How can I implement the "Select" checkbox and apply the "Delete" (for example) action to the "Checked" items?
Thanks! =)
Something like this?
function inputChanged(event) {
event.target.parentElement.parentElement.className =
event.target.checked ? 'selected' : '';
}
function printSelected() {
var textArea = document.getElementsByTagName('textarea')[0];
textArea.value = '';
var selectedRows = document.getElementsByClassName('selected');
for (var i = 0; i < selectedRows.length; ++i) {
textArea.value += selectedRows[i].textContent.trim() + '\n';
}
}
.selected {
background-color: yellow;
}
<table>
<tr>
<td>
<input type="checkbox" onchange="inputChanged(event)" />
</td>
<td>Row 1</td>
</tr>
<tr>
<td>
<input type="checkbox" onchange="inputChanged(event)" />
</td>
<td>Row 2</td>
</tr>
</table>
<button onclick="printSelected()">Print selected rows</button>
<textarea></textarea>

jQuery: How to check if certain checkboxes are checked, and change styles accordingly?

I've been trying to figure this out, but am not sure in which way to approach it using jQuery. I have a table of classes, and according to the classes that are checked, I want to change the background of tbody to reflect that this requirements are met.
<tbody>
<tr class="active header">
<th colspan="5"><b>Math (3 Courses)</b></th>
</tr>
<tr>
<td>MAC2311</td>
<td>Calculus I w/ Analytic Geometry</td>
<td>4</td>
<td></td>
<td><input type="checkbox" name="math" value="MAC2311"></td>
</tr>
<tr>
<td>MAC2312</td>
<td>Calculus II w/ Analytic Geometry</td>
<td>4</td>
<td>MAC2311 or MAC2281</td>
<td><input type="checkbox" name="math"value="MAC2312"></td>
</tr>
<tr>
<td>MAC2281</td>
<td>Calculus for Engineers I</td>
<td>4</td>
<td></td>
<td><input type="checkbox" name="math" value="MAC2281"></td>
</tr>
<tr>
<td>MAC2282</td>
<td>Calculus for Engineers II</td>
<td>4</td>
<td>MAC2311 or MAC2281</td>
<td><input type="checkbox" name="math" value="MAC2282"></td>
</tr>
<tr>
<td>Math Elective</td>
<td>(Math Elective)</td>
<td>4</td>
<td>MAC2312 or MAC2282</td>
<td><input type="checkbox" name="math" value="math_elective"></td>
</tr>
</tbody>
so, for example, if MAC2311, MAC2312, and math_elective are checked, tbody's background color can change green to signify completion of the section.
You can select all of the checked inputs with the :checked selector:
$("input[type=checkbox]:checked")
To see if any of the checkboxes are checked:
var isAtLeastOneChecked = ($("input[type=checkbox]:checked").length > 0);
if (isAtLeastOneChecked) {
// color your tbody
}
You can use the change handler like
.selected {
background-color: green;
}
then
jQuery(function ($) {
$('input[name="math"]').change(function () {
var $tbody = $(this).closest('tbody');
$tbody.toggleClass('selected', $tbody.find('input[name="math"]:checked').length == 3)
})
})
Demo: Fiddle
Here we adds the class selected to the tbody if there is 3 checked checkboxes
$(document).ready(function(){
$("#youTableId input").click(function () {
//Now $(this) will point to the element that has raised the event
and you can do something like this
alert($(this).is(':checked'));
//Now you now $(this) is the element that raised the event.
//You can get all the attributes of the element like name, id value, whether its check or not etc by using attr() function.
$(this).attr("value");
});
}
You probably want to assign ID's to your input and td elements.
var MAC2311 = document.getElementById('idOfThatInput');
var 2311td = document.getElementById('idOftd');
if (MAC2311.checked)
("#2311td").css("background", "green");
or use an Array containing the elements desired to be checked, and do the comparison in a for loop instead of individually.

how can I prevent Nested tables inside ng-repeat from populating in every row?

OK, so I want to create a dynamic nested hierarchy of tables. I get they data no problem, but using ng-repeat at each level causes the parent table to insert child data for a specific row into each row of the parent table. I want to prevent this, I have tried using ng-repeat-start and ng-repeat-end, however, because of the table nesting I cannot add the end tag in an appropriate place to stop the repeat.
UPDATE
Let me clarify a bit here, I have 3 nested tables, the top level table has list of groups, the first child table is a list of all of the items that belong to a specific group in the parent table. When the user clicks the expand button, I populate the child table based on which row in the parent table was clicked, this is OK, however the child table now shows up in each of the parent table rows instead of just the row that was clicked.
Plunker Link
http://plnkr.co/edit/RVOnf9wBF3TzXauzvMfF
HTML:
<table id="sicGroupTable" class="RadGrid_Metro">
<thead>
<tr>
<td>Sic Code Group</td>
</tr>
</thead>
<tbody ng-repeat="group in sicCodeGroup">
<tr class="rgRow">
<td class="rgExpandCol"><img class="rgExpand" ng-click="expandRow(group.GroupId)" ng-model="hideTwoDigitSub" /></td>
<td><input type="checkbox" ng-model="SelectGroup" /></td>
<td>{{group.GroupName}}</td>
</tr>
<tr ng-hide="hideTwoDigitSub">
<td></td>
<td>
<table id="sic2DigitTable" class="RadGrid_Metro">
<thead>
<tr>
<th>2 digit sic Code</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="twoDigitSic in twoDigitSicCodes" class="rgRow">
<td class="rgExpandCol"><img class="rgExpand" ng-click="expandRow(twoDigitSic.SicCode)" /></td>
<td><input type="checkbox" ng-model="Select2DigitSicCode" /></td>
<td>{{twoDigitSic.SICCode2}} - {{twoDigitSic.Title}}</td>
</tr>
<tr>
<td></td>
<td>
<table id="sic4DigitTable" class="RadGrid_Metro">
<thead>
<tr>
<th>4 digit sic code</th>
</tr>
</thead>
<tbody>
<tr class="rgRow">
<td class="rgExpandCol"><img class="rgExpand" ng-click="expandRow(sicCode.SicCode)" /></td>
<td><input type="checkbox" ng-model="Select2DigitSicCode" /></td>
<td>{{sicCode.SicCode}} - {{sicCode.Title}}</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
JavaScript:
var app = angular.module("apptSetting", ['ngResource'])
app.factory('dataFactory',
function ($resource) {
return {
getSicGroups: $resource('../Packages/GetJsonSicCodeGroups'),
expandRow: $resource('../Packages/GetExpandedRowData')
}
});
app.controller('aPackageController', ['$scope', 'dataFactory', function ($scope, dataFactory) {
function init() {
$scope.hideTwoDigitSub = true;
$scope.hideFourdigitsub = true;
}
$scope.sicCodeGroup = dataFactory.getSicGroups.query({}, isArray = true);
$scope.twoDigitSicCodes = null;
$scope.expandRow = function (groupId, sicCode) {
if (groupId != undefined)
{
$scope.twoDigitSicCodes = dataFactory.expandRow.query({ GroupId: groupId }, isArray = true);
$scope.hideTwoDigitSub = false;
if (sicCode != null && sicCode != undefined && sicCode != "") {
if (sicCode.length == 2) {
$scope.hideTwoDigitSub = false;
$scope.twoDigitSicCodes = dataFactory.Get2DigitSicCodes.query({ GroupId: groupId }, isArray = true);
}
}
}
}
init();
}])
The issue is that you're using a single boolean hideTwoDigitSub to control all the trs created by your ngRepeat:
<tr ng-hide="hideTwoDigitSub">
So when you set $scope.hideTwoDigitSub = false; every ngHide within your ngRepeat gets that false and thus all the tr elements are shown.
Radio Button Fix
Instead of using a boolean I'd set hideTwoDigitSub to the groupId for the row you want to show (and maybe rename hideTwoDigitSub to showTwoDigitSub since the variable now indicates which row to show).
So inside your expandRow() function I'd set which row to show by changing:
$scope.hideTwoDigitSub = false;
to
$scope.hideTwoDigitSub = groupId;
And change the above tr to:
<tr ng-hide="hideTwoDigitSub != group.GroupId">
So the row will be hidden unless your control variable hideTwoDigitSub is not equal to the current groups GroupId.
Or it might be clearer to use ngShow (note I changed the hideTwoDigitSub to showTwoDigitSub in this example since it's clearer):
<tr ng-show="showTwoDigitSub == group.GroupId">
radio button plunker
Checkbox solution
This approach is easiest done switching hideTwoDigitSub to showTwoDigitSub- so everything below assumes that.
For this approach, inside init() I'd set your control variable to be an array:
$scope.showTwoDigitSub=[];
And then toggle the appropriate control inside expand:
$scope.showTwoDigitSub[groupId] = !$scope.showTwoDigitSub[groupId];
And use the array inside your html:
<tr ng-show="showTwoDigitSub[group.GroupId]">
checkbox plunker

Categories