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();
});
I have the following piece of jQuery in my jQuery Mobile application where I am selecting the child checkbox when the li is clicked. This works fine, however it breaks the default functionality of the checkbox itself in the way that it makes it impossible to deselect the checkbox when clicking the box directly.
How can I target the li but not the checkboxes with the code?
var page = $.mobile.activePage
page.on('vclick', '.item_boxes_wrapper li:not(.item_checkbox)', function(e) {
var checkbox = $(this).find(':input');
checkbox.prop('checked', checkbox.is(':checked') ? null: 'checked');
});
<ul class="item_boxes_wrapper">
<li class="item_container selected_item">
<img src="http://www.wrestlemaniamainevent.com/Image/984043-64-1.jpg" class="product_image">
<input type="checkbox" checked="checked" value="98404364099" class="item_checkbox" name="items[]">
</li>
</ul>
You could use:
page.on('vclick', '.item_boxes_wrapper li:not(.item_checkbox)', function(e) {
if($(e.target).is(':checkbox')) return; // add this check here
var checkbox = $(this).find(':checkbox'); // or .find('input[type=checkbox]')
checkbox.prop('checked', !checkbox.is(':checked'));
});
PS: doesn't seem relevant selector .item_boxes_wrapper li:not(.item_checkbox), i guess you want '.item_boxes_wrapper li'. Or maybe .item_boxes_wrapper li:not(:has(.item_checkbox))???
jQuery:
$('.clickhere').click(function(e){
e.preventDefault();
$(this).closest('.row').children('.abc').hide(); // working
$(this).closest('.row').children('.abc').children('input').value = ''; // not working
$(this).closest('.bookingrow').children('.addressbox').children('input').value(''); // alternative - not working
});
html
<div class="row">
<div class='abc'>
<input type='text' class='unknown' />
</div>
<div class="clickhere">hide</div>
</div>
my target is if i click the "clickhere" class, content under "abc" class will hide and whatever content added by customer on those input box, they will be clear.
same html used multiple time on the same form. that's why using "$(this)".
any solution? what i am doing wrong?
Thanks in advance.
You need to use .val() to set the value, jQuery methods normally will return a jQuery object not a dom element reference so you would not have a properly called .value.
$(this).closest('.row').find('.abc input').val('');
So
$('.clickhere').click(function (e) {
e.preventDefault();
//cache the value of .row since it is used multiple times
var $row = $(this).closest('.row');
$row.children('.abc').hide(); // working
$row.find('.abc input').val('');
});
I have a label , that shows dynamic values based on user actions.
For example 1 or 2.
I would like to show div element with id="charts_div" if the label value is "1"
I would like to hide div element, if the value is "2"
This example is simplified as possible, so I could get basic idea where i am stuck
HTML
<label id="label"></label>
<div id="chart1_div" style="width:100%; height:200px"></div>
<div id="chart2_div" style="width:100%; height:200px"></div>
JQUERY
$(document).ready( function() {
$('#label').bind('change', function (e) {
if ($('#label').text() == "1")
{
$('#chart1_div').show();
$('#chart2_div').hide();
}
else if $('#label').text()=="2")
{
$('#chart1_div').hide();
$('#chart2_div').show();
}
}).trigger('change');
});
You can't bind change event to an element that doesn't have that kind of event. Put this change logic inside the event that is actually doing the changing of the label's text.
As it was said, you can't bind a change event to a label. Make whatever is changing your label also change the divs being shown. Supposing it's a button, do something like this:
HTML
<label id="myLabel">1</label>
<button id ="myButton">Toggle between 1 and 2</button>
<div id="chart1_div" style="width:100%; height:200px">a</div>
<div id="chart2_div" style="width:100%; height:200px">b</div>
JS
$(document).ready( function() {
$("#myButton").click(function(){
if ($('#myLabel').text() == '1')
{
$("#myLabel").text('2');
$('#chart1_div').show();
$('#chart2_div').hide();
} else if ( $('#myLabel').text()=='2')
{
$("#myLabel").text('1');
$('#chart1_div').hide();
$('#chart2_div').show();
}
});
});
Check out a live example on this jsfiddle ;)
I'm using this function with an unordered list (<ul>) in order to replicate the functionality of a Select dropdown element. The function correctly shows the user's selected values in the designated container when they are checked, but it isn't removing them when an item is unchecked.
I've included the relevant snippet below, and posted a working example with the complete code here: http://jsfiddle.net/chayacooper/GS8dM/7/
JS
$(document).ready(function () {
$(".dropdown_box").click(function () {
$("#select_colors").show();
});
$(".dropdown_container ul li").click(function () {
var text = $(this.children[0]).find("input").val();
var currentHtml = $(".dropdown_box span").html();
$(".dropdown_box span").html(currentHtml.replace('Colors', ''));
$(".dropdown_box span").append(', ' + text);
});
});
HTML
<div class="dropdown_box"><span>Colors</span></div>
<div class="dropdown_container">
<ul id="select_colors">
<li><label><input type="checkbox" name="color[]" value="Black" />Black</label></li>
</ul>
</div>
You should give the container id to the function. Then, before you add the text of the selection, you should make sure that it is not in the text. If it is, delete it.