jquery issues with tr click changes checkbox - javascript

My condition: I have a checkbox inside <tr>, written in <asp:repeater> on an user control, placed in an aspx page.
My goal: when <tr> is clicked, JQuery changes (or specifically, toggles) the checkbox checked attribute as well as the css class of the <tr> itself.
I've tried several methods, and so far, only this one works for me: http://jsfiddle.net/xixonia/WnbNC/
, but unfortunately, all of the checkboxes are toggled instead of only the selected one, just like the example on jsfiddle.net. moreover, if I clicked on the checkbox itself, all of the other checkboxes are checked instead of the clicked one.
What I've done:
$(".moduleTableItem").click(function (e) {
// Toggles CSS
if (!$(this).closest('tr').hasClass("tr.active")) {
$(this).closest('tr').css('background-color', 'blue');
$(this).closest('tr').addClass("tr.active");
} else {
$(this).closest('tr').css('background-color', 'red');
$(this).closest('tr').removeClass("tr.active");
}
// Toggles Checkbox
$(':checkbox').prop('checked', function (i, value) {
return !value;
});
ASP:
<asp:Repeater ID="repModuleGeneral" runat="server" EnableViewState="true">
<ItemTemplate>
<tr id="trModuleGeneral" class="moduleTableItem" runat="server">
<td>
<input type="checkbox" id="cbxSelect" class="cbxSelect" runat="server" autopostback="false" /></td>
<td>
<asp:Label ID="lblNo" runat="server" /></td>
</tr>
</ItemTemplate>
</asp:Repeater>
This is my first question. Please let me know if my question is somewhat unclear. Any code snippets or working solution would be appreciated.
Thank you.

Change
$(':checkbox').prop('checked', function (i, value) {
To
$(this).find(':checkbox').prop('checked', function (i, value) {
this used here will point to the current clicked tr.
This wont work if you directly click on the checkbox. Why, you ask? Because the checkbox lies inside tr, to which you've assigned a click event to. So, when click on a checkbox which is unchecked, these two actions are triggered :
Checkbox selected because of default checkbox action - checkbox set to true.
The click on the tr is triggered. You've got a checkbox prop event there. Reverts the selection done by default action.
So its a basic counter action, which cancels the default actions of the checkbox. To rectify this, you'll have to check if the default target is NOT a checkbox and then run the prop function :
$(".moduleTableItem").click(function (e) {
// Toggles CSS
if (!$(this).closest('tr').hasClass("tr.active")) {
$(this).closest('tr').css('background-color', 'blue');
$(this).closest('tr').addClass("tr.active");
} else {
$(this).closest('tr').css('background-color', 'red');
$(this).closest('tr').removeClass("tr.active");
}
//check here
if (!$(e.target).is(":checkbox")) {
// Toggles Checkbox
$(this).find(':checkbox').prop('checked', function (i, value) {
return !value;
});
}
});
Demo : http://jsfiddle.net/hungerpain/Kph8M/
But, just as a side thought, if you have control over IDs generated over the checkboxes, you could assign the same id as the for attribute in the label. Your HTML would look like this :
<tr class="moduleTableItem">
<td>
<input type="checkbox" id="cbxSelect1" class="cbxSelect" />
</td>
<td>
<label for="cbxSelect1">Text</label>
</td>
</tr>
Not the id attribute of the checkbox and the for attribute of the label. A lot of hassle will be solved by this. And you could use the change event of the check box. Also, did some optimisations to your code. It would look something like this :
$(".moduleTableItem :checkbox").change(function (e) {
//cache this - you are using it more than once.
var $tr = $(this).closest('tr');
// check if class is active - I took away if..else and made it ternary
var bg = $tr.hasClass("tr.active") ? 'red': 'blue';
//set css and toggleClass. Anyway you're switching everytime. Why not use toggle?
$(this).closest('tr').css('background-color', bg).toggleClass("tr.active");
});
Demo : http://jsfiddle.net/hungerpain/Kph8M/4/

Related

How to check the checkbox in html table with checkbox id using jquery by clicking a button

Am trying to check the checkbox using jquery on button click by checkbox id. The table which is binded usng jquery only.
My code is like this
Jquery
for (var i = 0; i < data.d.length; i++)
{
a = data.d[i].Id;
$("#table").each(function () {
$('input[type="checkbox"]', '#' + a).prop('checked', true);
});
}
Whatever am passing the id and checkbox id is same. Am using this id to check the checkbox but am unable to check it.
please help me how to fix this.
Thanx in advance.
$('input#' + id).prop('checked', true);
Use this, to toggle checkbox in each row, if the button is inside the row
$("button").on("click",function(){
var check = $(this).closest("tr").find('input[type="checkbox"]');
check.prop("checked",!check.prop("checked");
});
html would look like
<tr> <td><button>Click</button></td> <td><input type="checkbox"></td> </tr>
in the loop, you should give set the id for each checkbox:
$('#check-' + a).prop('checked', true);

angularjs: Change checkbox to image on selection

I want to implement a functionality in which, whenever a user checks a checkbox, it will get replace with a check image. For example:
So if I select first option it should get replace with a check image.
I am able to replace the checkbox with image, but this new element looses the ng-click event.
Below is the code:
currentController.changeChoice = function ($event, value) {
if ($event.target.checked) {
currentController.selectedOptions.push(value);
$($event.target).replaceWith('<div ng-click="stock.changeChoice($event,option);"><img src="../images/check.png" alt="remove" ng-checked="stock.selectedOptions.indexOf(option) > -1" /> </div>');
}
else {
var index = currentController.selectedOptions.indexOf(value)
currentController.selectedOptions.splice(index, 1);
}
};
below is the html generated for the new element (image)
<div ng-click="stock.changeChoice($event,option);"><img src="../images/check.png" alt="remove" ng-checked="stock.selectedOptions.indexOf(option) > -1"></div>
If angular way you have to use ng-show(or ng-if) for hide or show image and checkbox depends of the state. They both have to use same on-click callback. Here is the basic idea on pseudocode
<input ng-show="!is_checked" ng-click="callback()" ... />
<img ng-show="is_checked" ng-click="callback()" ... />

Why does the browser stop displaying checkbox updates?

I'm using jQuery to help select a some matching checkbox elements in a form. The form is created dynamically, but here is a stripped down version of it that illustrated my point:
http://jsfiddle.net/phinor/qj7uj3rc/
This is the relevant JavaScript:
$(document).ready (function () {
$('.lessoncount').on ('click', tickAlike);
});
function tickAlike ()
{
var classes = $(this).attr('data-classes');
if ($(this).siblings ('.tick_' + classes).attr ('checked'))
{
console.log ('ticking');
$('.tick_' + classes).removeAttr ('checked');
}
else
{
console.log ('unticking');
$('.tick_' + classes).attr ('checked', true);
}
}
The idea is that checkboxes can be individually selected or, if the "label" is clicked on, all checkboxes with the same class will be selected or deselected to match the box next to it. Because I want two possible behaviours depending on whether they click on the box or the label, I cannot use the <label> tag. As a follow on from that, because of the independent selection, "toggling" is not viable.
This seems to work for one cycle of "ticks" and "unticks" and then stops. If I inspect the checkbox element in Chrome, I can see that the "checked" attribute is being added and removed appropriately, but the browser view is no longer updated and the ticks do not show.
This is consistent in the lastest versions of Chrome, Firefox and IE, so I'm guessing that I'm doing something wrong!
You should be using .prop() instead of .attr() when modifying boolean attributes, e.g. checked, disabled, readonly, selected and etc. Using .removeAttr() or .removeProp() will cause the attribute to be removed forever, and cannot be further manipulated. To understand the difference between .prop() and .attr(), there is actually a very good question (with a well-structured answer) asked on SO before.
To programmatically check a checkbox, simply use $selector.prop('checked',true). To uncheck, use $selector.prop('checked',false).
Also, to check if a checkbox is checked (no pun intended), you can use the .is() method to do so, i.e. $selector.is(':checked').
$(document).ready(function () {
$('.lessoncount').on('click', tickAlike);
});
function tickAlike ()
{
var classes = $(this).attr('data-classes');
if ($(this).siblings('.tick_' + classes).is(':checked'))
{
console.log('ticking');
$('.tick_' + classes).prop('checked', false);
}
else
{
console.log('unticking');
$('.tick_' + classes).prop('checked', true);
}
}
A working demo: http://jsfiddle.net/teddyrised/qj7uj3rc/5/
Even better: I can see that the <span> element containing the description for each checkbox is semantically unhinged from its accompanying checkbox, i.e. there is no way to give context to each checkbox. The <label> element is created for this purpose.
You might still want to style your descriptors independently, so we can keep them wrapped in <span>, but we can wrap all the content within each <td> with the <label> element, so that a click on both the text and the checkbox will trigger the same response.
A revised markup for the rows in the table body would look something like this:
<tr>
<td>1-Mo</td>
<td><label for="lesson_1_1"><input type="checkbox" name="lesson[1][1]" value="1" id="lesson_1_1" class="tick_1645_1646_1647_1648_1649_1650_2024"/> <span data-classes="1645_1646_1647_1648_1649_1650_2024" class="lessoncount">(7)</span></label></td>
<td><label for="lesson_1_2"><input type="checkbox" name="lesson[1][2]" value="1" id="lesson_1_2" class="tick_1582_1583_1584_1585_1586_1587"/> <span data-classes="1582_1583_1584_1585_1586_1587" class="lessoncount">(6)</span></label></td>
<td><label for="lesson_1_3"><input type="checkbox" name="lesson[1][3]" value="1" id="lesson_1_3" class="tick_1658_1673_1684_1700_1706_1736_1737_1769"/> <span data-classes="1658_1673_1684_1700_1706_1736_1737_1769" class="lessoncount">(8)</span></label></td>
<td><label for="lesson_1_4"><input type="checkbox" name="lesson[1][4]" value="1" id="lesson_1_4" class="tick_1602_1603_1604_1605_1618_1628"/> <span data-classes="1602_1603_1604_1605_1618_1628" class="lessoncount">(6)</span></label></td>
<td><label for="lesson_1_5"><input type="checkbox" name="lesson[1][5]" value="1" id="lesson_1_5" class="tick_"/> <span>(0)</span></label></td>
<td><label for="lesson_1_6"><input type="checkbox" name="lesson[1][6]" value="1" id="lesson_1_6" class="tick_1659_1674_1701_1738_1755_1756"/> <span data-classes="1659_1674_1701_1738_1755_1756" class="lessoncount">(6)</span></label></td>
<td><label for="lesson_1_7"><input type="checkbox" name="lesson[1][7]" value="1" id="lesson_1_7" class="tick_1719_1720_1721_1722_1723_2003"/> <span data-classes="1719_1720_1721_1722_1723_2003" class="lessoncount">(6)</span></label></td>
<td>detail | clear</td>
</tr>
With a slightly modified script to listen to the click even on the wrapping <label> element instead of a text span:
$(document).ready(function () {
$('table tbody label').on('click', tickAlike);
});
function tickAlike ()
{
var classes = $(this).find('span.lessoncount').attr('data-classes');
if ($(this).find('input[type="checkbox"]').is(':checked'))
{
console.log('ticking');
$('.tick_' + classes).prop('checked', false);
}
else
{
console.log('unticking');
$('.tick_' + classes).prop('checked', true);
}
}
See alternative working demo: http://jsfiddle.net/teddyrised/pb68gk2n/
The problem is that you should not manipulate with attributes when you want to toggle properties checked.
Here is updated and simplified code:
$(document).ready(function () {
$('.lessoncount').on('click', tickAlike);
});
function tickAlike() {
var classes = $(this).data('classes');
var $checkbox = $(this).siblings('.tick_' + classes).click();
$('.tick_' + classes).prop('checked', $checkbox.is(':checked'));
}
Demo: http://jsfiddle.net/qj7uj3rc/6/
However this is still not ideal: note how clicking on checkbox itself does nothing. So it can be improved. You need to use label instead of span and wrap checkboxes into those labels. So HTML should be this:
<label data-classes="1645_1646_1647_1648_1649_1650_2024" class="lessoncount">
<input type="checkbox" name="lesson[1][1]" value="1" id="lesson_1_1" class="tick_1645_1646_1647_1648_1649_1650_2024" /> (7)
</label>
and after that bind onchange event on checkboxes instead of spans:
$(document).ready(function () {
$('.lessoncount :checkbox').on('change', tickAlike);
});
function tickAlike() {
var classes = $(this).parent().data('classes');
$('.tick_' + classes).not(this).prop('checked', this.checked);
}
Use "is(':checked')" for the conditional and use ".prop ('checked', false)" and ".prop ('checked', true)" in order to make changes in the check input.
Here is the link https://jsfiddle.net/qj7uj3rc/7/
if ($(this).siblings ('.tick_' + classes).is(':checked'))
{
console.log ('ticking');
$('.tick_' + classes).prop ('checked', false);
}
else
{
console.log ('unticking');
$('.tick_' + classes).prop ('checked', true);
}
If your form is created dynamically then it might behave differently than static. Use bind or live instead of click for dynamically created elements:
$(".lessoncount" ).live( "click", function() {
tickAlike();
});

Radio Buttons clear check when clicked again

I have a set of three radio buttons and they have mutual exclusion in them, as I implemented group name property, but the problem is, in the initial stage, none of the radio button is selected,
But when I select any of the radio button, then I cannot deselect the same, although mutual exclusion is in progress, but I want them to deselect as well.
My code aspx is:
<td>
<asp:RadioButton ID="AChk" runat="server" CssClass="itemRightAlign" GroupName="A"/>
</td>
<td>
<asp:RadioButton ID="DChk" runat="server" CssClass="itemRightAlign" GroupName="A"/>
</td>
<td>
<asp:RadioButton ID="WChk" runat="server" CssClass="itemRightAlign" GroupName="A"/>
</td>
You have both a code problem and a misunderstanding.
The misunderstanding is about how the mutual exclusion radio buttons work (or are supposed to work) (or are expected by the users to work).
The code problem is that in a mutually exclusion radio buttons group you need to initially select one of them.
So, I believe there are two ways of solving the problem:
Keep the radio buttons groud. Add a "none" button to the set, so that it works as if none of the other three are selected. And initially select this "none" button.
change the radio buttons to check boxes, so the user might select and deselect each of them. Then implement your own exclusion logic. I don't recommend this one.
You would need to use javascript...
doing binding in jquery, it's easier, and the name= should match your rendered groupname "name=" attribute...
var lastChecked = null;
$('input[name=A]').click(function(){
if (lastChecked == this) {
this.checked = false;
lastChecked = null;
}
lastChecked = this;
});
Use this to deselect:
var radios = document.getElementsByName('A');
for(var i=0; i<radios.length; i++)
{
radios[i].checked = false;
}
You can deselect a radio button by using the attribute ondblclick.
<input type="radio" name="RadioGroup1
" value="1" ondblclick="uncheckRadio();">
Apple</label>
When you double click on the radio button, just call a javascript function to set the checked property to false.
function uncheckRadio() {
var choice = document.form1.RadioGroup1;
for (i = 0; i < choice.length; i++) {
if ( choice[i].checked = true )
choice[i].checked = false;
}
}
Here is a similar implementation using the attribute ondblclickand jQuery. Also, this will allow you to include this functionality within controls with a dynamically generated client ID.
Code behind:
foreach (ListItem li in rbl.Items)
li.Attributes.Add("ondblclick", string.Format("clearCurrentRadioButtonSelection(\"{0}\")", rbl.UniqueID));
ASPX page
function clearCurrentRadioButtonSelection(controlName) {
var id = "input[name=" + controlName + "]";
$(id).each(function () {
$(this).attr('checked', false);
});
}

One function that will work with multiple elements

I have about 50 RadioButtonList on a form with a checkbox next to them. When you check the checkbox the radioButtonList gets enabled. I have the code to make it work for one but I am looking for a way to write one function that will work for all 50 RadioButtonList instead of writing fifty different functions. The checkboxes and RadioButtonLists are in a table. Thanks in advance
<script type="text/javascript">
function dis() {
var controlObject = document.getElementById('MainContent_RadioButtonList1');
controlObject.removeAttribute('disabled')
RecursiveDisable(controlObject);
return false;
}
function RecursiveDisable(control) {
var children = control.childNodes;
try { control.removeAttribute('disabled') }
catch (ex) { }
for (var j = 0; j < children.length; j++) {
RecursiveDisable(children[j]);
//control.attributes['disabled'].value = '';
}
}
function able() {
var controlObject = document.getElementById('MainContent_RadioButtonList1');
controlObject.setAttribute('disabled')
RecursiveDisable2(controlObject);
return false;
}
function RecursiveDisable2(control) {
var children = control.childNodes;
try { control.setAttribute('disabled') }
catch (ex) { }
for (var j = 0; j < children.length; j++) {
RecursiveDisable2(children[j]);
//control.attributes['disabled'].value = '';
}
}
function disable() {
var checkbox = document.getElementById('MainContent_CheckBox1');
if (
checkbox.checked == true)
dis();
else
able();
}
</script>
<table>
<tr>
<td><asp:CheckBox ID="CheckBox1" runat="server" OnClick="return disable();" /></td>
<td>
<asp:RadioButtonList ID="RadioButtonList1" runat="server" Enabled="false">
<asp:ListItem value="1">ListItem 1</asp:ListItem>
<asp:ListItem value="2">ListItem 2</asp:ListItem>
<asp:ListItem value="3">ListItem 3</asp:ListItem>
</asp:RadioButtonList>
</td>
</tr>
<tr>
<td><asp:CheckBox ID="CheckBox2" runat="server" OnClick="return disable();" /></td></td>
<td>
<asp:RadioButtonList ID="RadioButtonList2" runat="server" Enabled="false">
<asp:ListItem value="1">ListItem 1</asp:ListItem>
<asp:ListItem value="2">ListItem 2</asp:ListItem>
<asp:ListItem value="3">ListItem 3</asp:ListItem>
</asp:RadioButtonList>
</td>
</tr>
</table>
REWRITE
I believe that the action you want to perform is to toggle the enabled/disabled state of a drop down list that matches a given radio button. The radio buttons and drop down lists are stored in a table. If a radio button is "checked", you want the drop down list enabled. Otherwise, you want it disabled.
Create a custom attribute in the markup that binds the checkbox to its target drop-down list. For example, modify the markup like this:
<asp:CheckBox ID="CheckBox1"
runat="server"
target="DropDownList1" />
Then, iterate over all the checkboxes on the form using a piece of JavaScript and set an event handler for them.
(I chose target as my attribute name below, you can use whatever you like to save keystrokes, so long as it doesn't collide with an established DOM attribute.)
function setCheckBoxHandlers()
{
var boxes = document.getElementsByTagName("input");
for (box in boxes)
{
// Only bind those that have a target attribute; leave all
// others alone.
if (box.getAttribute("type").toLowerCase() == "checkbox" &&
box.getAttribute("target") != null)
{
// Set up the onclick handler.
box.onclick = toggleCheckBox;
}
}
}
function toggleCheckBox(e)
{
// Mozilla browsers pass the event source as argument zero. Microsoft
// doesn't; get it from the window.
e = e || window.event.source;
var target = document.getElementById(e.getAttribute("toggleTarget"));
if (e.checked)
{
target.removeAttribute("disabled");
}
else
{
target.setAttribute("enabled");
}
}
As this is a drop-down list, I see no need to enable/disable the idividual ListItems within it.
Your HTML looks like it might actually be generated (if not, it's likely a candidate for it), so this should work pretty well provided that I've understood the problem correctly.
UPDATE
I have it working, but you're right: ASP.NET's funky table-based layouts wreak havoc with what you want to do. Good news is, it CAN be done. :)
You can find the working solution at http://jsfiddle.net/tyrantmikey/RxY5s/. Note the following:
During document load, you need to call setCheckBoxHandlers.
I had to split the function into two parts. One for the on click handler, the other for the tree traversal.
The checkbox should include a TARGET attribute that points to its matching radiobuttonlist. (Its value should be the ID of the radio button list.)
You don't need to set the onclick handler in the tag; this will happen automatically when you call setCheckBoxHandlers. This is a nice solution, as it makes it easier to add new rows to your table later.
Hope this does the trick for you!
<asp:CheckBox ID="CheckBox1" runat="server" OnClick="return disable(this);" />
function disable(c) {
return c.checked ? dis() : able();
}

Categories