How can I get the elements without a particular attribute by jQuery

I know how to get elements with a particular attribute:

$("#para [attr_all]")

But how can I get the elements WITHOUT a particular attribute? I try

 $("#para :not([attr_all])")

But it doesn't work. What is the correct way to do this?

Let me give an example:

<div id="para">
    <input name="fname" optional="1">
    <input name="lname">
    <input name="email">
</div>

jQuery:

$("#para [optional]") // give me the fname element  
$("#para :not([optional])") //give me the fname, lname, email (fname should not appear here)  

If your code example is the exact code you're using, I think the problem is an errant space.

$("#para :not([attr_all])")

should be

$("#para:not([attr_all])")

If you leave a space in there, it selects descendants of #para.


First thing that comes to my mind (maybe sub optimal) :

$('p').filter(function(){
    return !$(this).attr('attr_all');
});

However p:not([attr_all]) should work, so I think something else is going on in your code.


A faster way to do this is to first get all the elements with the ID para (which is invalid HTML if there is more than one, consider using a class instead) and use the filter (or find depending on how the HTML is constructed) method to only get the elements without the attribute like so:

$('#para').filter(':not([attr_all])');

Doing this you are having jQuery do much less work because you are only looping through a smaller subset of elements to get those without the attribute. Doing it with a single selector statement, eg $("#para :not([attr_all])"), will cause jQuery to get all elements without the attribute, then filter them for ones with the ID of para.


Try $("#para [attr!=val]").

Your :not really should work, though, which makes me suspect something else is going on.

For a full list of attribute selectors, see the jQuery Selectors docs.


Frank DeRosa's answer is about right, but since the OP does want to find the descendants, it's a bit off. Trying it myself, it seems like it should be working the way it is, but it's possible that whatever you're running doesn't like the ':' operator being used directly as a descendant. Try using

$("#para input:not([optional])")

Would have left a comment but can't yet.