Hi guys I am having a problem with Events. I have a checkbox list and I have a main check box that checks all boxes. When I clickEvent some of my checkbox list items it should add data-id attr to the "selected obj". So in my case when I press main check box to check all others every thing is ok (it simply clicks all other elements). but when i do that it empties my array. I mean if i uncheck it will be the way it supposed to be but checked (when uncheck it fills when i check it empties).
......
var selected = {};
var reload = function(){
selected = {};
$('.checkbox_all').unbind('click');
$('.table_checkbox').unbind('click');
$('.checkbox_all').bind('click', checkAll);
$('.table_checkbox').bind('click', checkMe);
}
var checkMe = function(e){
var checkbox = $(e.target);
var id = checkbox.attr('data-id');
//console.log(id);
if(checkbox.attr('checked')){
selected[id] = id;
}else{
if(selected[id]) delete selected[id];
}
console.log(selected);
}
var checkAll = function(e){
if($(e.target).attr('checked')){
$('.table_checkbox').each(function(){
if($(this).attr('checked') === false){
$(this).click();
}
});
}else{
$('.table_checkbox').each(function(){
if($(this).attr('checked') === true){
$(this).click();
}
});
}
//console.log(selected);
}
.......
HTML:
<tr><th class="table-header-check"><input type="checkbox" class="checkbox_all"/></th></tr>
<tr class=""><td><input type="checkbox" data-id="5" class="table_checkbox"></td></tr>
<tr class="alternate-row"><td><input type="checkbox" data-id="6" class="table_checkbox"</td></tr>
<tr class="alternate-row"><td><input type="checkbox" data-id="8"
....ETC\
My problem is that when i click .checkbox_all it should click on all .table_checkbox(that r cheched or uncheched)... it just clicks all checkboxes like a main checkbox... it works fine, but i have an event all other checkboxes if i click em i add some data to array when i unclick em it removes data from array.... so when im clicking checkboxes sepperatly they add /remove data to array properly... but when im clicking on main checkbox... it clicks on right checkboxes but the data array is empty when all checked and full when all unchecked... it must be the opposite way
Could you instead go for a cleaner solution, and generate selected on the fly? See here for an example (and a JSFiddle for everyone else): http://jsfiddle.net/turiyag/3AZ9C/
function selected() {
var ret = {};
$.each($(".table_checkbox"),function(index,checkbox) {
if($(checkbox).prop("checked")) {
ret[$(checkbox).prop("id")] = true;
}
});
return ret;
}
** EDIT: **
If you're looking to have an array that is added to and removed from, then this JSFiddle (http://jsfiddle.net/turiyag/pubGb/) will do the trick. Note that I use prop() instead of attr(), in most cases, especially this one, you should use prop() to get the value you want.
To work with your own code you need to understand the order of events. When you programmatically call click() on the checkbox the javascript (checkMe() for children) executes before the state of each child checkbox is changed (e.g., adding attribute 'checked'). It is because of this reason that the checkMe() function was adding and removing ids in the selected array in the reverse order. You can confirm this by adding the following debug line in the checkMe function:
console.log('Checked state of checkbox id:' + id + ' is: ' + checkbox.prop('checked'));
Case1: Clicking checkAll when it is Unchecked; it calls checkMe() for each child checkbox but finds the 'checked' attribute as undefined. So it executes the delete code. After executing checkMe the 'checked' attribute is added on the checkbox.
Case2: Clicking checkAll when it is Checked; the checkMe() function finds the 'checked' attribute previously added and fills the array. Later an event is probably fired to remove the 'checked' attribute.
I changed the following lines to quickly test this and seems to be working:
Bind checkMe on change event instead of click in reload function:
$('.table_checkbox').bind('change', checkMe);
Change the condition for unchecked children in checkAll function when the .checkbox_all is checked:
if($(this).prop('checked') === false) {/*call child click*/}
//Use prop instead of attr because it takes care of 'undefined' cases as well. If you want to keep using attr because you're on an older version of jquery then add something like:
typeof $(this).attr('checked') == 'undefined'
and also the condition when .checkbox_all is unchecked:
if($(this).prop('checked') === true) {/*call child click*/}
Hope this helps. Here's a jsbin to play with..
Related
I am facing problem because I have a checkbox inside a div and I want to call a function in both the cases: if we change the checkbox value or click the div.
Now the problem is that, When I click the checkbox, The event is fired twice and I am not getting expected result.
<div ng-click="checkEntry(config.id)"><input type="checkbox" ng-model="modelCheckbox" ng-change="checkEntry(config.id)" ng-checked="someArray.indexOf(config.id) !== -1"></div>
$scope.checkEntry = function(id){
var idx = $scope.someArray.indexOf(id);
if(idx === -1){
$scope.someArray.push(id);
}else{
$scope.someArray.splice(idx, 1);
}
}
Now If i click div, it works fine and the checkbox gets selected. But if i click the checkBox, the function is called twice, and it doesn't work as expected.
Please help me with a solution
You don't need two event handler for two identical events.When you click on the input, the div will be clicked as well. so you just need to remove ng-change from your code.
<div ng-click="checkEntry(config.id)">test
<input type="checkbox" ng-model="modelCheckbox" ng-checked="checked">
and in your controller:
$scope.checked = true;
$scope.checkEntry = function(id){
$scope.checked = !$scope.checked;
}
Look at this plunker
Checkbox is situated inside of that div, so when you click checkbox you are actually clicking also on div.
Actually, in your case you can remove ng-change attribute from checkbox and it will still work, because function will be called via click on div anyway. But that is not correct way to work with checkboxes!
First question here is if you really need that div?
I would rather use label instead:
<label for="my-checkbox"><input id="my-checkbox" type="checkbox" ng-model="modelCheckbox" ng-change="checkEntry(config.id)" ng-checked="someArray.indexOf(config.id) !== -1"></label>
In such case it will work fine, you just need to write proper CSS to style that label correctly. This is the best and the most correct solution.
I am using this simple script provided from a friendly lad in #javascript to uncheck radio buttons:
$('.feed').on('click', 'input[type=radio]', function() {
var myParent = $(this).closest('div');
var ref = $(this);
if( myParent.data('val') == $(this).val() ){
var ref = myParent.find('.none input');
ref.prop('checked',true);
}
myParent.data('val',ref.val() )
});
Everything works fine, see this fiddle, but when I add the attribute 'checked' to one radio button you will actually have to click twice before you can uncheck it, see this fiddle. This got me thinking, is setting 'checked' as an attribute actually equal to checking the radio button by hand? Or why am I failing this?
This has nothing to do with adding an an attribute vs clicking, it's the additional code, specifically this line:
if (myParent.data('val') == $(this).val() ){
which says, if you clicked this before, then turn it off.
However, you're not telling the code that you've already (virtually) "clicked" it.
You can do this by adding the initial value to the 'myParent', one way is to add it to the html:
<div data-val='1'>
Updated fiddle: https://jsfiddle.net/8jh2k8u8/4/
An alternative is to initialise the parent via code by finding the radio that is selected (:checked):
var startup = $(".feed input[type=radio]:checked").first();
if (startup.length) {
startup.closest("div").data("val", startup.val())
}
Updated fiddle: https://jsfiddle.net/8jh2k8u8/5/
I'm creating a form with multiple checkboxes and I want to value of the checked checkboxes to be "yes" and the value of unchecked checkboxes to be "no". The site I'm hosting my form on does not let me add the hidden field with the same name and a different value so I have to find script that will add the hidden checkbox on submission and include the value of "no". Currently, when I submit the form the unchecked boxes are recorded as undefined but for data purposes I need it to be filled with "no".
Here is what I found:
$(document).ready($("#foo").submit(
function() {
// Add an event listener on #foo submit action...
// For each unchecked checkbox on the form...
$(this).find($("input:checkbox:not(:checked)")).each(
// Create a hidden field with the same name as the checkbox and a value of 0
// You could just as easily use "off", "false", or whatever you want to get
// when the checkbox is empty.
function(index) {
var input = $('<input />');
input.attr('type', 'hidden');
input.attr('name', $(this).attr("name")); // Same name as the checkbox
input.attr('value', "no"); // or 'off', 'false', 'no', whatever
// append it to the form the checkbox is in just as it's being submitted
var form = $(this)[0].form;
$(form).append(input);
} // end function inside each()
); // end each() argument list
return true; // Don't abort the form submit
} // end function inside submit()
));
Why is the script not working?
You need to check out the jQuery API documents
$(document).ready(function(){}); it takes function callback, which may not needed here.
$("#foo").submittakes function callback, which will be called right before the form is submitted.
No need to wrap selector in $.find
You need to figure out the context of this
The this in $(this).attr("name") is referring the input box
The this in $(this)[0].form is still the input box
I guess you are trying to get the reference of forms. You may use document.forms
You need to change the input with $(this). Within the .each function $(this) will refer to the checkbox itself.
It isn't normal to have severals input with same name you can put the value directly in checkbox
$(this).find($("input:checkbox:not(:checked)")).each(function(){
$(this).val($(this).is(':checked') ? "yes" : "no")
})
I was able to use this much simpler script. Works perfectly.
$('#foo').click(function () {
$(this).find('input[type="checkbox"]').each( function () {
var checkbox = $(this);
if( checkbox.is(':checked')) {
checkbox.attr('value','yes');
} else {
checkbox.after().append(checkbox.clone().attr({type:'hidden', value:'no'}));
}
});
});
Got this script that gets the value of a checked radio button and prints it out in another tag. It works perfectly when you click a radio button, but I've realized that I need to have some of the radio buttons checked by default.
How do I change this script so that it will output the values of already checked radio buttons on page load as well?
$("input[type='radio']").click(function(){
var radioValue = $(this).val();
if(radioValue){
$(this).closest('section').find('h2 .value').text(radioValue);
}
});
Fiddle: https://jsfiddle.net/tactics/bykf31e6/4/
You can use the :checked selector to find all the checked :radio elements on load, and the loop over them to set the value of the related .value element. Try this:
$(":radio:checked").each(function() {
$(this).closest('section').find('h2 .value').text(this.value);
});
Example fiddle
Note that you should use the change event for binding to radio and checkbox elements to cater for those who navigate websites using their keyboards. Also, if you remove the check that the radio element has a value (which is redundant as they should always have a value) you can simplify the code:
$("input[type='radio']").change(setText); // when user selects
$(":radio:checked").each(setText); // onload
function setText() {
$(this).closest('section').find('h2 .value').text(this.value);
}
Example fiddle
I would like to uncheck all checkboxes that have a specific class with the exception of the one just checked.
function PizzaToppings_OptionValueChanged(checkboxElement) {
if ($(checkboxElement).attr("checked")) {
if($(checkboxElement).hasClass('cheese_toppings'))
{
// This will uncheck all other "cheese_toppings" but I want the newly selected item "checkboxElement" to remain checked.
$('input:checkbox.cheese_toppings').attr('checked', false);
}
}
}
The code above will uncheck all "cheese_toppings" including the one just selected. I don't want to then recheck the one just selected or the event will be recalled.
I thought the best solution would be to remove "checkboxElement" from the list returned by $('input:checkbox.cheese_toppings') and then set the .attr('checked', false) to that list. But I'm not sure how to remove checkboxElement from the list.
$('input:checkbox.cheese_toppings').not(checkboxElement).attr('checked', false);
See the jQuery docs: .not()
try
$('input:checkbox.cheese_toppings').not( checkboxElement ).attr('checked', false)
//when the page is loaded
$(function() {
//select all checkboxes with class cheese_topping
var allToppingBoxes = $('input[type=checkbox].cheese_topping')
//when one of these is clicked
allToppingBoxes.click(function() {
//if the box was unchecked do nothing
if(!$(this).attr('checked'))
return;
//select all except this one that was clicked
allToppingBoxes.not(this)
.attr('checked', false); //uncheck all
});
});
Also note that you probably want to use jquery prop rather than attr.
You might also want to look at the :checked pseudoclass (IE8 down doesn't support it though)