Okay I have list items, some have a span, some not.
On my event I want to add the span when they don\'t have any yet.
has() works fine, but
The accepted answer works well, if you don't want to filter out only those elements which do have the spans as direct children.
As the :has() and the .has() loop over all descendants, not just the children.
In that case, you have to use a function
$("li").not(function() {
// returns true for those elements with at least one span as child element
return $(this).children('span').length > 0
}).each(function() { /* ... */ })
$("a.add-span").click(function() {
$("li").each(function(index) {
if ($(this).children('span').length === 0){
$(this).append('<span class="spn">new span<\/span>');
}
})
})
With children() method, the length property is used to check whether or not a span already exits and if it doesn't, one is added/appended.
More Info:
You can use a combination of the :not and :has selectors like this
$("a.add-span").click(function() {
$("li:not(:has(span))").each(function(index) {
$(this).append('<span class="spn">new span<\/span>');
});
});
Here is a demo http://www.jsfiddle.net/xU6fV/
Try this,
$("a.add-span").click(function() {
$("li:not(:has(span))").each(function(index) {
$(this).append($("<span class='spn'>").html("Newly Added Span"));
});
});
This is the first link on Google when searching "jquery not has". The specific scenario I needed to solve was a little different to this one. I had to not items that have a specific DOM element, not simply based on a tag. This meant I couldn't use a selector which each solution above used.
jQuery's has() however does accept a DOM element! So I created a jQuery plugin to combine these two inbuilt functions.
I wanted to share it here because hopefully it will help others in my situation too. It also answers the original question.
The Plugin:
(function ( $ ) {
$.fn.extend({
not_has: function (param) {
return this.not(this.has(param));
}
});
}( jQuery ));
Implementation:
$("a.add-span").click(function() {
$("li").not_has("span")
.append('<span class="spn">new span<\/span>');
// Prevent the page from navigating away
return false;
});
https://jsfiddle.net/brjkg10n/1/
I was initially intending to find a jQuery function that would work like addBack() but using not instead. If you need something so complicated, then please feel free to use the following plugin.
(function ( $ ) {
$.fn.extend({
notBack: function () {
return this.prevObject.not(this);
}
});
}( jQuery ));
With this, the answer would be:
$("li").has("span").notBack()
.append('<span class="spn">new span<\/span>');
https://jsfiddle.net/2g08gjj8/1/