jQuery selector bug? composed selector vs. simple selector & find() - javascript

Something is very awkward about my situation... i have something like this:
<div id="selector">
<input type='radio' />
<input type='radio' />
<input type='radio' />
</div>
if I use $("#selector input[type=radio]") all three elements are found, but if I use $("#selector").find("input[type=radio]") or even find("input") only the first one is found.
Is this a bug in jQuery? Am I not using find() properly?
Clarification : I want to use find() to get all the inputs, but anything I try finds only the first one.
edit: i'm using jquery 1.3.2

What you really want is:
$("#selector > :radio")
As for why you're getting only one, I'd need to see the actual code that's being run because find() doesn't stop at one and will find all matches so it may be how you're using it afterwards that is the issue.

The two code fragments should return the same result.
Are you saying that when you run the following code, the first alert will show "3" and the second "1" ?
var a = $("#selector input[type=radio]");
var b = $("#selector").find("input[type=radio]");
alert(a.length);
alert(b.length);
Can you please verify?

Try
$("#selector").find("input[type=radio]")

See here
All the three returns the same result!
$(function() {
console.log($("#selector input[type=radio]")); // 3
console.log($("#selector").find("input[type=radio]")); // 3
console.log($("#selector").find("input")); // 3
});

$("#selector").children("input[#type=radio]")

Related

Selecting all checked checkbox return all checkbox instead using JQuery

Here is my code jsfiddle
JS file
$( document ).ready(function() {
$(".test").children().filter(function(index, elem){
console.log($(elem).children(":checked"));
});
})
HTML
<ul class="test">
<li><input type="checkbox" name="1"><label>something</label></li>
<li><input type="checkbox" name="2"><label>something</label></li>
<li><input type="checkbox" name="3"><label>something</label></li>
<li><input type="checkbox" name="4" checked><label>something</label></li>
</ul>
I am trying to select all checked checkbox, but if I filtered by :checked I get all checkbox instead.
What am I doing wrong?
To be more precise
var allChecked = $('.test input[type="checkbox"]:checked');
get you all checked checkboxes under as child of element having class test and to test if checkbox is checked you can use
var bool = $(selector).is(":checked");
// return true if checked false if not
//where selector can be any jQuery selector
To select the checked inputs you simply need to use:
var checked = $("input:checked");
See the updated fiddle
If it must be limited to inputs within that ul only, you can specify the class as well:
var checked = $(".test input:checked");
See this fiddle to select all checked inputs in a given ul.
Other answers suggest better ways to select the checked checkbox you want, and I agree that those are more straight-forward methods and are preferable to your filtering approach, but here I try to explain what you're actually seeing in your code as you have it.
Going to your fiddle and running it in the Chrome debugger, it looks like it's doing the right thing, and you simply may not be seeing what you expect due to the behavior of console.log()
I split your console.log line to take two separate steps — get the child(ren) that match the :checked selector, then log that variable; so it looks like:
$( document ).ready(function() {
$(".test").children().filter(function(index, elem) {
//console.log($(elem).children(":checked"));
boxen = $(elem).children(":checked");
debugger;
console.log(boxen);
});
})
updated fiddle
This loops making the call to the filter() function four times — one for each of the originally selected $(".test").children() elements. On the first call, index will be 0 (zero) and elem will be the first <li> element.
Calling boxen = $(elem).children(":checked"); will give you [] ... that is, an empty array, since none of the children of that first li are checked.
However, when you console.log(boxen) it gives you some "weird" output because this is jQuery... it's not a plain javascript array.
When you get to the fourth iteration, looking at the fourth selected element, index will be 3 and elem will be that fourth <li>
When you $(elem).children(":checked") on that one, you'll get something like [<input type=​"checkbox" name=​"4" checked>​] (how you see it will depend some on your javascript debugger) — so this time it is selecting the one checked input element.
If you select .children(":checked") into a variable you are indeed getting the one checkbox you want, but the console.log() output is deceiving you.

JavaScript: Count inputfields in a Div

I have a <div id="inputform"> and in that div there are multiple <input type="text"> .
How can I count the number of <input> fields?
var inputFormDiv = document.getElementById('inputForm');
alert(inputFormDiv.getElementsByTagName('input').length);
Using jQuery you would be able to count the number of elements of a certain type, class, etc. using the following line of JavaScript
$("div#inputForm input").length
If you're not using jQuery, take a look at Brian's answer, it should do what you need it to.
$('#inputform input[type="text"]').length;

Cleanest way to query for parent class using JQuery

I'm having trouble coming up with a solution that pleases me.
I'm working with some composite components, and I don't have full control over them, and now I have to set values to them using JavaScript, and I thought JQuery would serve me well, as it did.
What happens is that the component's HTML output has a structure simlar to this:
<span id="externalSpan">
<span id="internalSpan">
<input type="text" class="component-value" />
</span>
</span>
So all I had to do was check the component-value input, and if it's empty, I set the default value to it.
I solved it like this:
$(document).ready(function(){
var defaultValue = $('#defaultValue').val();
$('.component-value').each(function(){
if(!$(this).val()){
$(this).val(defaultValue);
}
});
});
And that worked fine, but now there's a new condition I need to evaluate. If the component has the manualInput CSS class, I cannot set it's value, but the class is set on the externalSpan which is the input's grandfather component, and it looks like this:
<span id="externalSpan" class="manualInput">
<span id="internalSpan">
<input type="text" class="component-value" />
</span>
</span>
The simplest way that I found to do it was this:
if(!$(this).parent().parent().hasClass('manualInput')){ ... }
And it works, but it seems really smelly to me, another solution was to invoke parents() with a class selector and check the length, but it seems odd too.
Is there a cleaner way for me to do this? And if not, which of the 2 options described above is a better solution?
So add the check to the selector
$('span:not(.manualInput) > span > .component-value').each(function(){
Example JSFiddle
I would use closest :
if(!$(this).closest('#externalSpan').hasClass('manualInput')){ ... }
Source : http://api.jquery.com/closest/
You can do this --
if($(this).closest('.manualInput').length > 0){
// do your stuff
}
A much better solution, use a selector that avoids .component-value elements that are descendants of .manualInput:
$('.component-value:not(.manualInput .component-value)').each(...)
Ideally the grandparent element would have a consistent class such that you could call .closest():
if ($(this).closest('.component-value-grandfather').hasClass('manualInput')) {...}
Alternatively you could check to see if there is a .manualInput ancestor at all:
if ($(this).closest('.manualInput').length) {...}
I'd recommend the following
$('span:not(.manualInput) > span').find('.component-value:empty').each(function () {
$(this).val(defaultValue);
});
Or better yet,
$('.component-value:empty', 'span:not(.manualInput) > span').val(defaultValue);
Probably, the shorted piece of code to achieve what you desire.
Alternatively you could use
if ($(this).parents('.manualInput').length) {/*...*/}
See jquery documentation. I suppose this is the shortest way to find the parent(s) of a given element

jquery selector problem

I'm using this code:
$('fieldset input[type=checkbox]').each(function () {if($(this).attr('checked','checked')){
var switches = $(this).parent().find('.switch');
$(switches).attr('state','on')
$(switches).css({'left':"52px"});
$(switches).parent().css({'background-position': "147px -37px"});
}})
But somehow it sets all my checkboxes to checked="checked" Am I just stupid or is something else in the code interfering?
Thanks for your help :)
EDIT:
here is the HTML
<fieldset>
<input checked="checked" />
<label></label>
<div class="toggle_box">
<div class="switch" state="on"></div>
</div>
</fieldset>
<fieldset>
<input/>
<label></label>
<div class="toggle_box">
<div class="switch"></div>
</div>
</fieldset>
This piece of code is doing it...
$(this).attr('checked','checked')
...which returns the set in order for the cascade to work. An Object is always truthy in JavaScript.
Try...
this.checked
...which returns whether the checkbox is checked or not. If you wanted to do it the jQuery way, use $(this).is(':checked'). I wouldn't though, it's more verbose and less performant.
You're passing the checked value to attr() as the second argument. That causes it to be set. What's then returned is the jQuery object with that input, which is always a truthy value.
Your if condition should look like this (use the :checked pseudo-class instead):
if ($(this).is(':checked')) {
On a side note, your inner code can be refactored to this:
$(this).parent().find('.switch')
.attr('state', 'on')
.css({ 'left': "52px" })
.parent()
.css({ 'background-position': "147px -37px" });
If you have to use a cached variable (i.e. switches), you can, but don't wrap it in the jQuery function. It's a jQuery object itself, so needs not be wrapped.
The statement in the if statement is setting your checkboxes to checked. Particularly, this statement: $(this).attr('checked','checked').
Instead you can do if($(this).prop('checked'))
Read more about the jQuery Prop method.
Alternatively, you can do, this.checked which will access the DOM directly or with jQuery, $(this).is(':checked').
if($(this).attr('checked','checked')) would be your problem. You're assigning checked to each checkbox instead of checking if it's checked.
At first glance I see you're using .is('checked') when I beleive you want .is(':checked') The preceding colon being the difference.
UPDATE: I see you updated the code. The line
if ($(this).attr('checked', 'checked'))
is actually setting all 'input:checkbox' elements to checked. It should be:
if ($(this).is(':checked'))
$('fieldset input[type=checkbox]').each(function () {if($(this).attr('checked') == 'checked')){
var switches = $(this).parent().find('.switch');
$(switches).attr('state','on')
$(switches).css({'left':"52px"});
$(switches).parent().css({'background-position': "147px -37px"});
}})
There is actually a selector specifically for the checked boxes.
$('fieldset input[type=checkbox]:checked').each(function(){
var switches = $(this).parent().find('.switch');
$(switches).attr('state','on')
$(switches).css({'left':'52px'});
$(switches).parent().css({'background-position':'147px -37px'});
});
If you use that you won't have to do any of that logic by yourself.

Selecting child text with jQuery

I have a structure like the following:
<form>
<input type="text" />
<input type="text" />
...
<input type="radio" />
<input type="whatever" />
Here I have some text
</form>
I cannot change the structure of the HTML. I need to remove via Javascript the text inside the form, and the problem is to select it, since it is not wrapped inside any tag.
My solution (more a hack actually) using jQuery is the following
$('form').contents().filter(function(){
return (this.toString() == '[object Text]')
}).remove();
but it's not very robust. In particular it fails on IE (all versions), where this.toString() applied to a chunk of text returns the text itself. Of course I could try
$('form').contents().filter(function(){
return (this.toString() != '[object]')
}).remove();
but I'm looking for a better solution.
How am I supposed to remove the text?
Both a solution using jQuery or plain Javascript is good for me.
You filter for this.nodeType == Node.TEXT_NODE. Take a look at this answer.
Try this, instead of just "this.toString()":
return (Object.prototype.toString.call(this) == '[object Text]');
You could also check the node type, but I never can remember how to do that; I'll go look it up but somebody's going to beat me to it :-)
edit told ya!
If you use version 1.4 you can
var $temp= $('form').children().detach();
$('form').empty().append($temp);
It will remove all children elements, empty the form (the text..) and reinsert the elements..
the same in 1.3.x would require an additional step..
var $temp= $('<div />');
$('form').children().appendTo($temp);
$('form').empty().append($temp.children());
[Update] in regards to Andrea's comment
quoting jquery contents()
The .contents() and .children()
methods are similar, except that the
former includes text nodes as well as
HTML elements in the resulting jQuery
object.
How about:
$('form').contents().filter(function(){
return !this.outerHTML;
}).remove();

Categories

Resources