Reputation: 11
Please consider the following code :
<!DOCTYPE html>
<html>
<style>
p{ width:200px; }
</style>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<p><span>Hello</span>, how are you?</p>
<p>Me? I'm <span>good</span>.</p>
<script>
$(document).ready(function(){$("p").find($("*")).andSelf().css("background- color","blue"); });
</script>
</body>
</html>
The output is the whole document turning into blue color while I only wanted the paragraph and span inside it to turn blue.
If I use $("p").find(" * ") instead of $("p").find($(" * "))
then everything shows according to my need. Can anyone work out the difference between the two approach?Thanks!
Note: Please everyone note that I know there are easier methods to do this stuff,but I just want to know why this didn't work..
Upvotes: 1
Views: 3033
Reputation: 262919
Disclaimer: The other answers already suggest better selectors to achieve your goal, but I understand you want to know why
andSelf()
ends up matching all the elements in the document, so I'll try to explain that.
First, as you know, andSelf()
adds the previous set of elements on the stack to the current set. So, in your case, it seems it should add the <p>
elements to the set containing their descendants:
$("p") // match the paragraphs
.find($("*")) // match all the elements that descend from a paragraph
.andSelf() // add the paragraphs to the elements above
However, the above assumes that find($("*"))
is the previous set of elements, and that's simply not the case here. The first hint about this comes from the documentation for find():
As of jQuery 1.6, we can also filter the selection with a given jQuery collection or element. With the same nested list as above, if we start with:
var $allListElements = $('li');
And then pass this jQuery object to find:
$('li.item-ii').find( $allListElements );
This will return a jQuery collection which contains only the list elements that are descendants of item II.
The last sentence is particularly interesting: it seems to imply that the jQuery object passed to find()
is filtered in order to match the descendants of the elements in the original set. If that's indeed the case, the logic would be inverted, and the previous element set would end up being $allListElements
instead of the set returned by find()
.
A look at the jQuery source code shows that's exactly what happens:
find: function(selector) {
var self = this, i, l;
if (typeof selector !== "string") {
return jQuery(selector).filter(function() {
for (i = 0, l = self.length; i < l; i++) {
if (jQuery.contains(self[i], this)) {
return true;
}
}
});
}
// [...]
}
So, when you write:
var elements = $("p").find($("*")).andSelf();
You're actually writing the equivalent of:
var self = $("p"), i, l;
var elements = $("*").filter(function() {
for (i = 0, l = self.length; i < l; i++) {
if ($.contains(self[i], this)) {
return true;
}
}
}).andSelf();
As you can see, the previous element set is actually $("*")
instead of the set returned by find($("*"))
because of the logic inversion. Therefore, all the elements in the document end up being legitimately added to the current set by andSelf()
.
Upvotes: 1
Reputation: 26267
If you want to select all P's simply use
$(document).ready(function(){
$("p").css("background-color","blue");
});
No reason to complicate stuff
If you want to select the spans inside you can do something like
$(document).ready(function(){
$("p > span").css("background-color","blue");
});
** Update **
Your selector attribute in your find query is bad, you shouldn't have it like $("*")
but only "*"
. However the $("p").find("*")...
will only select any elements inside the <p>
tag so trailing the find method with an andSelf will make the selection ambiguous.
Upvotes: 0
Reputation: 457
The difference between $("p").find(" * ")
and $("p").find($(" * "))
is that in the second one you're passing find() a jquery object instead of a regular selector string.
EDIT: I just tried it out. Looks like adding the andSelf() makes it select the entire document somehow. The logical process would be select p > find all elems inside that match everything in the document > select self(p) > color, but it seems to be going wrong at the select self bit.
I think it(the andSelf()) just selects the object passed to find(), which is $('*'), and so selects everything.
Upvotes: 0
Reputation: 93424
You don't have to do any of that. Just do this.
$(function() { $("p").css('background-color', 'blue'); });
Note: $(function() {});
is the same as $(document).ready(function(){});
Edit: Since you have two, you may have to do this:
$(function() { $("p").each(item, function() { item.css('backround-color', 'blue'); })});
Edit2: Based on your comments, you want this:
$(function() { $("p").find('span').andSelf().css('background-color', 'blue'); });
Upvotes: 0
Reputation: 165961
The $("*")
has no context, so it selects every element in the document. You want to find all elements within the currently selected element, so you need to just pass the string to find
.
However, it's completely unnecessary and you could just apply the style to the p
(as the span
is a child you don't to apply it to that too):
$("p").css("background-color","blue");
Note that in that line above I've used background-color
with no spaces, unlike in your question. I'm guessing it was just a typo when you wrote the question, but it won't work if you put spaces in the property name.
Upvotes: 0
Reputation: 552
You just need
$("p").css("background-color","blue");
To change the color or all the p tags in the document. Is there some specific reason for the way you have done it?
Upvotes: 0