I have this jQuery code:
$("#Filter ul input:checked").each(function () {
if (!$(this).prop("disabled") && !$(this).hasClass("ignoreInput")) {
Can this be written in only one selector? Right now I'm taking in too many elements to test with the if statement.
Is it also better to use .find(selector) instead of writing all in one selector?
$(document.body).find("#Filter ul ...)
You could use a combination of :not() along with the attribute selector, like this:
$("#Filter ul input:checked:not([disabled],.ignoreInput)").each(function () {
// your logic here
});
Is it also better to use .find(selector) instead of writing all in one selector?
This makes little to no performance difference.
Related
I want to do something like:
if($(this).hasClass("playButton"))
{
$(this).find("li").removeClass("active");
}
But instead of "this" in "if" statement I want to use any class selector. But I don't know how to get concrete DOM element, which corresponds to the condition.
So I need:
if($(.anyClass).hasClass("playButton"))
{
$(current element, which corresponds to
if condition).find("li").removeClass("active");
}
$(".playButton li").removeClass("active");
...?
You can select the elements using the ".anyClass" selector and then iterate through them using each. In the callback function of each, this will refer to the current DOM element.
$(".anyClass").each(function() {
if ($(this).hasClass("playButton")) {
$(this).find(".btn").removeClass("playButton");
}
});
However, for this particular scenario, you can reach your goal without using each. Simply target the element directly and manipulate it, as #Derek朕會功夫 suggested in his answer.
$(".playButton li").removeClass("active");
What is better to use, the each function it self or using some smart selectors to do the same thing.
Example:
EACH FUNCTION
$('nav#mainNav > ul > li > ul').each(function(){
$(this).closest('li').addClass('hasSub');
});
SELECTOR
var addClass = $('nav#mainNav > ul > li > ul').closest('li').addClass('hasSub');
Both of these do the same thing, however is there any point to doing one over the other?
Explicitly iteration (.each) should be used when applying logic that varies between elements. Otherwise, implicit iteration will do just fine.
Your code sample is almost exactly the same as the .each API page:
Note: most jQuery methods that return a jQuery object also loop
through the set of elements in the jQuery collection — a process known
as implicit iteration. When this occurs, it is often unnecessary to
explicitly iterate with the .each() method.
For example, instead of using a selector to select uls nested inside lis and traverse a level up, you can also use .each applying a logic test for lis that contain uls:
$('#mainNav > ul > li').each(function() {
if ($(this).children('ul').length) {
$(this).addClass('hasSub');
}
});
Though this is more verbose, it does essentially the same thing.
For code-golf purposes, as mentioned in the comments and Bergi's answer, li:has(ul) would be the shortest way of achieving this without requiring a .closest() call. Though :has is not essentially the same as the children selector - :has looks for descendants (various levels deep) while > looks for direct children (1 level deep) - I believe it should work as well for this specific use case.
You could use the jQuery .has() method instead which reads a lot better:
var addClass = $('nav#mainNav > ul > li').has('ul').addClass('hasSub');
Both of these do the same thing, however is there any point to doing one over the other?
Yes. The second one is shorter and more performant (since .each is called anyway internally from those methods). There is absolutely no reason to incorporate an each here - it's just as pointless as using .each(function(){ $(this).addClass(…); }).
Btw, maybe you're looking for the :has selector, which would shorten your expression even more:
$('#mainNav > ul > li:has(ul)').addClass('hasSub');
If you want to be sure that the ul is a direct child of the list item, you still may want to use the suggestion from the comments (the closest(li) is always the direct parent of the ul):
$('nav#mainNav > ul > li > ul').parent().addClass('hasSub');
Most jQuery methods will operate on a collection of elements, and automatically iterate as if you'd used .each(). So one does not normally use .each() in simple cases like that.
However, if you need to perform multiple operations based on each element, it may be necessary to use .each(). E.g.
$('nav#mainNav > ul > li > ul').each(function () {
$(this).closest('li').addClass('hasSub');
$(this).closest('.otherClass').removeClass('.otherClass');
});
You could write this without .each() by using .end():
$('nav#mainNav > ul > li > ul')
.closest('li').addClass('hasSub').end()
.closest('.otherClass').removeClass('.otherClass');
but I believe .each() makes the intent clearer (although indentation, like this, does a pretty good job as well).
In jQuery there are a few colon selectors like
:prev, :next, :last
My question is:
Are they truly part of jQuery, because they are actually used on DOM elements?
We seem to have equivalent methods as well in jQuery prev(), next(), last(). What is the purpose of having 2 different ways?
Any basic examples would be really great.
jQuery does not have :prev or :next selectors, I have no idea where you came across them. There is a :last selector, though, as well as :first, provided by the Sizzle selector library, used by jQuery. It is a non-standard selector, not part of CSS, and is thus implemented in JavaScript.
One purpose of the :last selector over the .last() method is so you can use it to filter elements in the middle of a selector sequence, like this (note that :last and :last-child are not the same):
$('.a > .b:last > .c')
Rather than having to write a chain of methods like this:
$('.a').children('.b').last().children('.c');
By the way, the "colon selectors" you refer to are called pseudo-classes (colloquially but incorrectly known as "pseudo-selectors").
Here is how I made a slider with all sorts of selectors and traversing of objects.
$('#next').click(function () {
if (!$('*').is(':animated')) {
if ($('div.display:visible').is(':nth-child(3)')) {
$('div.display:visible').fadeOut();
$('div.display:first').fadeIn(function () {
$(this).children().fadeIn();
});
} else {
$('div.display:visible').fadeOut().next().fadeIn(function () {
$(this).children().fadeIn();
});
}
}
});
$('#prev').click(function () {
if (!$('*').is(':animated')) {
if ($('div.display:visible').is(':nth-child(1)')) {
$('div.display:visible').fadeOut();
$('div.display:last').fadeIn(function () {
$(this).children().fadeIn();
});
} else {
$('div.display:visible').fadeOut().prev().fadeIn(function () {
$(this).children().fadeIn();
});
}
}
});
yes, they are in the documentation
sometimes you can't always include everything in the selector or want a subdivision of the selector.
e.g.
$(".mylist").each(function(){
$(this).css("color","red");
$(this).next().show();
})
The colon represents a filter like to get the selected option in a dropdown I would use $("select option:selected") or to get a checked radio box I would use $("input[type=radio]:checked");
There are no :prev and :next filters, but you can find a full list of filters here http://api.jquery.com/category/selectors/
I am trying to select elements of a (certain class || another class) with the same selector. How can I go about doing that?
Currently, I have:
$(".class1 .class2").each(function(idx, el) {... });
however, that only selects elements that match both classes, not one or the other.
How can I select elements that match one or both of the classes, with the same selector?
Try this
$(".class1,.class2")
http://api.jquery.com/multiple-selector/
$(".class1,.class2").each(function(idx, el) {... });
put a comma within the same selector string.
http://api.jquery.com/multiple-selector/
How can I select all elements that have a specific CSS property applied, using jQuery? For example:
.Title
{
color:red;
rounded:true;
}
.Caption
{
color:black;
rounded:true;
}
How to select by property named "rounded"?
CSS class name is very flexible.
$(".Title").corner();
$(".Caption").corner();
How to replace this two operation to one operation. Maybe something like this:
$(".*->rounded").corner();
Is there any better way to do this?
This is a two year old thread, but it was still useful to me so it could be useful to others, perhaps. Here's what I ended up doing:
var x = $('.myselector').filter(function () {
return this.style.some_prop == 'whatever'
});
not as succinct as I would like, but I have never needed something like this except now, and it's not very efficient for general use anyway, as I see it.
Thank you, Bijou. I used your solution, but used the jQuery .css instead of pure javascript, like this:
var x = $('*').filter(function() {
return $(this).css('font-family').toLowerCase().indexOf('futura') > -1
})
This example would select all elements where the font-family attribute value contains "Futura".
You cannot (using a CSS selector) select elements based on the CSS properties that have been applied to them.
If you want to do this manually, you could select every element in the document, loop over them, and check the computed value of the property you are interested in (this would probably only work with real CSS properties though, not made up ones such as rounded). It would also would be slow.
Update in response to edits — group selectors:
$(".Title, .Caption").corner();
Similar as Bijou's. Just a little bit enhancement:
$('[class]').filter(function() {
return $(this).css('your css property') == 'the expected value';
}
).corner();
I think using $('[class]') is better:
no need to hard code the selector(s)
won't check all HTML elements one by one.
Here is an example.
Here is a clean, easy to understand solution:
// find elements with jQuery with a specific CSS, then execute an action
$('.dom-class').each(function(index, el) {
if ($(this).css('property') == 'value') {
$(this).doThingsHere();
}
});
This solution is different because it does not use corner, filter or return. It is intentionally made for a wider audience of users.
Things to replace:
Replace ".dom-class" with your selector.
Replace CSS property and value with what you are looking for.
Replace "doThingsHere()" with what you want to execute on that
found element.
Good luck!
Custom CSS properties aren't inherited, so must be applied directly to each element (even if you use js to dynamically add properties, you should do it by adding a class), so...
CSS
.Title
{
color:red;
}
.Caption
{
color:black;
}
HTML
You don't need to define a rounded:true property at all. Just use the presence of the 'Rounded' class:
<div class='Title Rounded'><h1>Title</h1></div>
<div class='Caption Rounded'>Caption</div>
JS
jQuery( '.Rounded' ).corner();