Selecting from a list of previously selected elements via jQuery - javascript

I'm having a bit of a brain fart here, and hoping someone can help me find a 1-line solution to this problem, without having to call .each().
So I get a list of all checkboxes within a container like this:
var checkboxes = $(':checkbox', '#surveyModal');
At some point later, I need to find out if any (or none) of the checkboxes are checked within that list.
I expected something like these to work:
$(':checked', checkboxes)
// or
checkboxes.attr(':checked')
// or
$(checkboxes).attr(':checked')
But it doesn't. The only thing I've had success with is calling each() and then checking each individually. But that means I'll have to keep a separate variable (.e.g. someAreChecked at a higher-level scope, which I don't feel is optimal.
checkboxes.each(function () {
if ($(this).attr('checked')) {
someAreChecked = true;
}
});
I was hoping that I can easily in a single line do such a check:
if (checkboxes.('get checked count') == 0)
{
}
Thanks in advance.

The filter function is what you're looking for :)
checkboxes.filter(':checked').length;

.attr returns the value of an attribute, and you have to pass the attribute's name to it, not a selector.
Just use .is instead.
Description: Check the current matched set of elements against a
selector, element, or jQuery object and return true if at least one of
these elements matches the given arguments.
$(checkboxes).is(':checked')

This should do it:
$("input[type=checkbox][checked]").length

Related

Why the execution does not get into the $('input[type="checkbox"]').each?

First time using $('input[type="checkbox"].each function. This is a snapshot taken from firefox debugger.
At the left, the code. At right, the watch window with the value of the array of input-checkbox elements. Execution jumps from line 4th to 7th, what would be ok if the array was empty.
Can anybody tell me why the execution does not get into the loop?
The loop has been executed. You can see in the tooltip that the array has 140 entities within it. The problem is because they are all undefined.
This is because jQuery objects don't have an id property. You need to get that from the Element instead, using either prop() or this.id:
if (this.value)
ids.push(this.id);
That being said you can make the code more succinct by using map() to build the array instead of each():
$('#seguent').on('click', function() {
var ids = $(':checkbox').map((i, el) => el.value ? el.id : null);
$.post('llista_cursos', { ids: ids });
});
Final note, this retrieves all checkboxes regardless of whether they were checked or not. You may want to include :checked in the selector.

Traverse XML with jQuery to get element value

I have some XML that looks like so:
<closure1>
<topClosure>
<ellipsoidalHead>
<standardComponentData>
<variousElements>
<idNumber>234567</idNumber>
<nominalThickness units="in">0.3750</nominalThickness>
</standardComponentData>
</ellipsoidalHead>
</topClosure>
</closure1>
<shell>
<standardComponentData>
<various_elements>
<nominalThickness units="in">0.6250</nominalThickness>
<idNumber>123456</idNumber>
</standardComponentData>
</shell>
<nozzle>
<standardComponentData>
<various_elements>
<attachedToidNumber>123456</attachedToidNumber>
</standardComponentData>
<nozzle>
In my JS code, I already have the <nozzle> element bomNode as a jQuery set, i.e.
var bomNode = $("nozzle");
So, for each nozzle element, I need to
Get the value of <attachedToidNumber> in the <nozzle> element.
Find the element that contains the <idNumber> that matches
<attachedToidNumber> (<shell> in this case).
Get the value in the <nominalThickess>
element.
As you can see, the depth of the desired <idNumber> element can vary. This is also a very small subset of the whole XML structure, so it can be very large.
I've tried something like this:
var attachedToElement = bomNode.parents().find('idNumber').text() === attachedToId;
but I get false returned. What's the easiest way to get the desired idNumber value? I'm sure it's something simple, but I'm just missing it.
Thanks.
UPDATE: I realized that bomNode is at the top level, I don't need to go up. a level. Doing something like this
var attachedToElement = bomNode.parents().siblings().find('idNumber')
gives me a list of children elements that have an <idNumber> element. So, I need to find the one that has the desired value. My thought is to use .each(). However, that value is defined outside of the .each() function, so I don't have anything to match against. Once I have the list of matches, what's the easiest way to get the set that has the <idNumber> value I want?
You were right - you missed a simple thing:
shell is not a parent of nozzle. They are siblings. Try this:
var attachedToElement = bomNode.siblings().find('idNumber').text() === attachedToId;
But this would return true (if true) - not the actual value.

How to get jquery selector seeing updated dom in change handler

I'm fairly new to javascript and jQuery. I've searched for answers to this question, but have had no luck, though I bet there are some in here. So advance apologies if this is a dup.
Markup has 3 checkboxes with different classes, and one class in common. I want to notice when the number of boxes checked in either of two classes changes, or rather when there is a transition between at least one box in two of the classes being checked or unchecked. The two interesting classes are named "professional" and "vendor", and the class in common is "account_type_checkbox".
When the page is ready, I count the number of checked "professional" and "vendor" boxes with:
jQuery("input.professional[checked='checked'], input.vendor[checked='checked']").length
This appears to work correctly. I have a "change" event handler on checkboxes in the common class that does the same count when it triggers. But when the event triggers, it gets the same count as it did on page load - i.e. it doesn't see the updated DOM with the modified checked attribute.
I've put a jsfiddle for this at http://jsfiddle.net/cm280s9z/1
Could someone please help me fix this, and/or explain why my code doesn't work the way I expected it to?
http://jsfiddle.net/cm280s9z/3/
Use alert($(":checkbox:checked").length); to get the sum of all marked checkboxes.
There are several other ways of doing this too, as pointed out in this thread, such as doing it by classes on a checkbox:
calculate the number of html checkbox checked using jquery
Maybe you will find this useful: http://jsfiddle.net/cm280s9z/6/
Here's a cleaned up version (not saying it's the best ever) of what you had, showing the :checked.
Reasons why this code is good:
storing the jQuery object checkboxes means it won't have to re-jquery-objectify it every time.
grabbing objects by certain [vague or lengthy] selectors can be more strenuous on jQuery. Grabbing by this class means it'll be more specific as well. We can further filter out checked using .filter. Extra Tip: If traversing the DOM, I like to grab a container that's fairly unique and use .find() to help me get at the descendants.
functions can bring some order and organization to what you're doing.
comments are your friend.
Hope this helps!
var GLOB = GLOB || {};
jQuery(document).ready(function () {
// Define
var checkboxes = jQuery('.account_type_checkbox');
var get_checkbox_count = function(checkboxes){
return checkboxes.filter(':checked').length;
};
var do_business = function(){
alert('transitioned to business');
};
var do_personal = function(){
alert('transitioned to personal');
};
// Initialize
GLOB.business_count = get_checkbox_count(checkboxes);
alert('GLOB.business_count = ' + GLOB.business_count);
// Events
checkboxes.change(function(){
var cur_count = get_checkbox_count(checkboxes);
var add_business = (cur_count > 0);
var no_business = (GLOB.business_count < 1);
// If any are selected it's business, where previously none were checked.
var transition_business = (add_business && no_business);
// If none are selected it's personal, if previously any were checked.
var transition_personal = (!add_business && !no_business)
if (transition_business)
do_business();
if (transition_personal)
do_personal();
});
});

Javascript array not working as expected

I'm pretty new to js/jquery. For each checkbox with the ID of check$ (where $ is a sequential number), I want to toggle the class "agree" of the surrounding span that uses the same check$ (but as a class). I don't want to have to hard-code the list of matching checkboxes, as this may vary.
Here's my code. This function works as expected:
agree = function (checkbox, span) {
$(checkbox).change(function(){
$(span).toggleClass('agree');
});
};
This is what I'm trying to pass to the above function, which does not work:
$(function() {
var elemid = 'check',
checks = Array($('[id^='+elemid+']').length);
console.log(checks);
for (i=0; i < checks; i++) {
agree('#'+elemid+checks[i], "."+elemid+checks[i]);
}
});
console.log(checks) returns [undefined × 4]. The number of elements is correct, but I don't know why it's undefined, or whether that is even significant.
The following code works as expected, but as I say, I'd rather not have to specify every matched element:
$(function() {
var checks = ["check1", "check2", "check3", "check4"];
for (i=0; i < checks.length; i++) {
agree('#'+checks[i], "."+checks[i]);
}
});
Thanks.
Edit: Thanks to Jack, I was overlooking the most simple method. I added the same class to all checkboxes and spans, and solved the problem with this:
$('input.check').change(function(){
$(this).closest('span.check').toggleClass('agree');
});
I might be totally missing something, but I'm pretty sure you are just trying to attach a change handler to each checkbox. In this case you can give them all the same class. I'm also guessing at your html structure for the span.
For reference:
http://api.jquery.com/closest/
http://docs.jquery.com/Tutorials:How_jQuery_Works
$('.yourcheckboxclass').change(function(){ //grab all elements with this class and attach this change handler
$(this).closest('span').toggleClass('agree');
});
The reason that the array is full of undefined values, is that you are just getting the number of items in the jQuery object, and create an array with that size. The jQuery object is discarded.
Put the jQuery object in the variable instead:
var elemid = 'check', checks = $('[id^='+elemid+']');
checks.each(function(){
agree(this, "."+elemid+checks[i]);
});

How to select empty inputs (value="") using jQuery

How can I check for empty values of (required) input fields within a section, and then add a class to them on an event, using jQuery? So far, I have tried:
jQuery("#sender_container input.required").val("").addClass("error");
But that seems to SET the value, rather than checking it. Any ideas?
jQuery("#sender_container input.required").filter(function() {
return !this.value;
}).addClass("error");​
Why you have to use filter and not [value=""] you can see in this DEMO
The reason is: attribute selectors check the initial state of the element, not the current state. (note that you can change the "initial" state with the attr function, but it's bad practice, you should always use prop)
So if you change the input value, the current value won't effect the attribute selector. not wise... :)
Notes:
.val() returns the value of the form element, and breaks the jQuery chain,
$('selector').val().addClass('foo') Error, the return value is a string\ number
.val(valueToSet) sets the value of the form element and doesn't break the jQuery chain.
$('selector').val("some value").addClass('foo') - Valid, the returned value is a jQuery
$('input:text[value=]','#sender_container').addClass('error');
DEMO
$('#sender_container input.required[value=""]').addClass('error')
jQuery('#sender_container input.required[value=""]').addClass("error");
You can try this:
$('input:not([value!=""])').addClass('error');
DEMO
Note: This answer should not be used, and the only reason it wasn't deleted is so it can be learned from.
$field = $("#sender_container input.required");
if( ! $field.val())
{
$field.addClass("error");
}
this simple way may work.
If you only need to select based on the initial attribute value of the input then the following will do:
var elements = $('#sender_container input.required[value=""]')
But be aware that this won't work if the value attribute isn't present. It also won't work for the current input value if it has been changed by user or script.
If you'd like to get the current input value you can use jquery's filter function:
var elements = $('#sender_container input.required').filter(function() {
return this.value === '';
// alternatively for "no value":
// return !this.value;
})
After you've selected the jquery elements you can add your class:
elements.addClass('error');
to get all fields inspected this might help.
$('#sender_container [required]').each(function(index)
{
if (!($(this).val())) $(this).addClass('error');
}
});

Categories

Resources