Problem adding and removing in array with jquery and checkboxes - javascript

I got a problem when I try to create an array of checked checkboxes.
The checkboxes are generated dynamically with an "onChange" attribute that calls the javascript function to add or remove in the array. The function gets "talla" that it is the value to add or remove.
This is my javascript code for the function: (arrayTallas is global)
function checkbox_marcado(talla)
{
if(jQuery('#id_talla').is(':checked') == true)
{
arrayTallas.push(talla);
}
else //elimina posicion del array al deseleccionar un checkbox
{
var index = arrayTallas.indexOf(talla);
arrayTallas.splice(index,1);
}
}
The problem is that the first checkbox work fine, but the others are not deleted.
For example. If a have 3 checkboxes with values "1" "2" "3" if I click on the first one, it is added normally, and if I click again on it, it is deleted normally too... but if I click on the first one, and then on the second one, when I click again on the second one to delete it from the array, when I print the array this is what I get: 1 2 2
Thanks

If you're using jQuery anyway, why not use a function like this:
$('#tallas').live('click', function(){
$(':checkbox:checked').map(function() {
return this.value;
}).get().join(',');
});

I think you mean to say:
jQuery('#id_' + talla)
where you're saying:
jQuery('#id_talla')
Also check to make sure you don't have multiple checkboxes with the same id attribute.

Related

Understanding jQuery .change event

I have some issue understanding the jQuery().change() behavior.
The HTML is basically a lot of input elements - checkboxes ( each with ID of id^='o99-post-visible-XXX' - and they are pure CSS images as Checkboxes, but this is irrelevant ) and I have another checkbox ("#o99-check-all") to "check all" and a text input field ('#o99-post-visible-ids') that receives the IDs of the selected boxes.
The jQuery code is as follows:
jQuery(document).ready(function() {
jQuery("#o99-check-all").change(function () {
jQuery("input:checkbox[id^='o99-post-visible-']").prop('checked', jQuery(this).prop("checked")).trigger('change');
});
var checkboxes = jQuery("input.o99-cbvu-posts-checkbox:checkbox");
checkboxes.on('change', function() {
// get IDS from all selected checkboxes and make a comma separated string
var ids = checkboxes.filter(':checked').map(function() {
return this.value;
}).get().join(',');
// put IDS inside a text input field
jQuery('#o99-post-visible-ids').val(ids);
// console.log(ids);
});
});
Now, more or less everything works now, but that is not the issue.
at first , the first chunk of code was:
jQuery("#o99-check-all").change(function () {
// without .trigger('change') chained
jQuery("input:checkbox[id^='o99-post-visible-']").prop('checked', jQuery(this).prop("checked"));
});
and it did not work ( why?? ) - meaning the boxes were selected as expected but the '#o99-post-visible-ids' input field was not receiving the IDs - until I chained a .trigger('change') event - when suddenly it works well.
my confusion is with the following ( which perhaps for my little understanding of jQuery internal works is counter-intuitive )
after chain adding .trigger('change') - isn't it somehow an endless loop where a chain() event is trigger inside a listener of change() ? and if not why?
Why is the code functioning now and did not function correctly before? because again, for my understanding, there was a change, even if not triggered by direct user click. Why would I need to trigger it manually?
I'm not sure I understand what you mean. What is happening now, is that whenever you change the all checkbox, the other checkboxes will be checked/unchecked the same as all, and then the change event is triggered.
Because you added a listener for change, that function will then fire. I.e. this function will run:
function() {
// get IDS from all selected checkboxes and make a comma separated string
var ids = checkboxes.filter(':checked').map(function() {
return this.value;
}).get().join(',');
// put IDS inside a text input field
jQuery('#o99-post-visible-ids').val(ids);
// console.log(ids);
}
Without your .trigger("change") (or .change() in short), you only change a property of the inputs. So the object changes, indeed, but that does not mean the change event is triggered. It does sound counter-intuitive, but events are only triggered by user actions or if you call the event explicitly - in no other way do events get triggered.
its because you have written jQuery('#o99-post-visible-ids').val(ids); inside a function which happens only when the change event done on the inputs, assigning prop directly through .prop does not trigger the change event and so the result handler wont run
Now if I understand you correctly...
...because you're giving every check box the same ID? If you wish to apply it to more than a single element, it is best practice to use a class selector instead.
jQuery(".o99-check-all").change(function () {
// without .trigger('change') chained
jQuery(".o99-check-all").prop('checked', jQuery(this).prop("checked"));
});
See link
https://api.jquery.com/change/

how to remove redundant value of two different genere

If you click this link you can see the code.Problem is when i click on action it is removing redundant data but if i click on another checkbox (i.e family) then it will give the value. but if i put same value as first checkbox (i.e action) then it is showing that value.My aim is if i select two different checkbox it will show only one value
[
{title:'Meet the Robinsons', genre:'action'},
{title:'Meet the Robinsons', genre:'action'},
{title:'MSD', genre:'family'}
]
http://jsfiddle.net/Bw77D/669/
You just need to replace push by splice and remove if (unique):
this.out.splice(0, 1, value);
If I understood right, your problem is when having multiple movies, it only shows the first.
To show all of them you need to remove the condition if (unique) and leave only this.out.push(value);
To show the last item of the list you need to remove the condition if (unique) and replace this.out.push(value); by this.out.splice(0,1,value);
That should fix it.
http://jsfiddle.net/Bw77D/717/

function to push value to array on checkbox OR radio change

I have a function like this:
$('input:checkbox').change(function() {
array = [];
$('input:checkbox:checked').each(function() {
array.push($(this).val()); // push checked checkbox values to array
});
$('input:radio:checked').each(function() {
array.push($(this).val()); // push checked radio values to array
});
someOtherFunction();
});
... which collects values from checkboxes and radio buttons in one array. At the moment it runs when a checkbox changes but I want it to run when a radio button changes too.
As a noob I have no idea where to start so have tried very little. And I didn't find the answer after a good search.
Thanks in advance.
Try with
$('input:checkbox, input:radio').change(function() {
The problem is that your current selector is only applicable for checkboxes.

jQuery loop giving all <select> options instead of option:selected

There is a table that I need to loop through and get the values from, then store them in an array. Right now this loop is giving me all the values, however when it encounters an HTML < select> element it returns the selected option then it gives me all of the select options. I only want the selected option, not the entire list.
This is much easier to explain by showing you. So here is the fiddle and here is the jQuery code
var saveEdits = [];
$('#save').click(function () {
$('.projects_editable_tbody tr').each(function () {
$('.projects_editable_content_td, option:selected', this).each(function () {
var $input = $("input", this);
if ($input.length) {
saveEdits.push($input.val());
} else saveEdits.push($(this).text());
});
});
$.each(saveEdits, function (index, value) {
console.log(index + ': ' + value);
});
});
As you can see from the fiddle the array is populating almost exactly like I want it to. Any help is appreciated. If you need more info/code just let me know.
It's giving you the text from the td that contains the select, because you've specified .projects_editable_content_td. You need to exclude the .projects_editable_content_td that contain a select. See the code I posted to your question from yesterday.
Perhaps I misunderstood the question, but I tinkered with your code to push the current selected value of each select, instead the select itself. I also edited the content of the select boxes to use "selected" prop.
$('.projects_editable_content_td', this).each(function () {
if(jQuery(this).children().val()) {
saveEdits.push($(this).children().val());
} else {
saveEdits.push(jQuery.trim($(this).text()) );
}
});
You can see in this jsfiddle
http://jsfiddle.net/amenadiel/WNSBk/29/
The first row is edited and it returns a correct array. The second one was left as it was and still has the problem.
In your scenario it would probably be better if you enclosed each line in tags and harvest the data using the serialize() method of the form. For this you would need to make every field an input. For example, you could put a hidden field next to text elements.

Jquery click event with binded event

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..

Categories