jQuery find self
This may sound odd, but I'm working on a plugin that needs to find elements within a div, or the div itself.
The script finds an element based on a user selection, but the contents, including the markup i开发者_运维技巧s variable. So the script will look for the element as follows:
$('.block').find(selector); // selector set by user
but there isn't an easy way to have the selector select the '.block'. Selecting the parent before using find isn't a solution, as there are multiple '.block' elements.
I know extending the expr[":"]
selector won't work as it is only looking for children. But, I did figure out a way to "duck punch" this method, by making a ':self' selector:
(function($){
var orig = $.fn.find;
$.fn.find = function(sel){
return (sel === ':self') ? this : orig.call(this,sel);
}
})(jQuery)
But this seems a bit over the top. And it will slow jQuery processing a tiny bit with every find function. Is there another way to do this?
Thanks for the answers! But I ended up doing this:
var b = $('.block'),
el = (b.is(selector)) ? b : b.find(selector);
approach with find('*') would be much more CPU intensive and I would recommend:
$('.block').find(selector).add($('.block').filter(selector));
I came across this problem too. I solved it like this (basically Romans Malinovskis solution as a jquery plugin):
$.fn.findAll = function(selector) {
return this.find(selector).add(this.filter(selector));
};
EDITED:
You can use the all selector '*' combined with andSelf to get a selection containing an element with all its children and subchildren. Then you can filter() that selection on the chosen selector.
<style type="text/css">li {background-color: white;}</style>
<script type="text/javascript">
$(function () {
$('div').find('*').andSelf().filter(selector).css('background-color','blue');
}
</script>
<div>
This is a test
<ul>
<li class="test">This is a test</li>
<li>This is a test</li>
<li class="test">This is a test</li>
<li>This is a test</li>
<li class="test">This is a test</li>
<li>This is a test</li>
</ul>
</div>
Should change the backgrounds of all the .test objects, as well as the initial div that was selected, if it's appropriate. I'm not sure about the performance of my answer though.
Example: http://jsfiddle.net/7A9JJ/2/
EDIT Or you could just do $('div, div *').filter(selector);
Since 1.8 you can do
$('.block').find(selector).addBack(selector);
I'm not sure why this needs to be so complicated. This can all be done with a simple multiple selector:
$(selector + '.block, .block ' + selector);
No find
, filter
, nor add
to think about, plus it's more performant in many (most?) modern browsers (tested with jQuery 1.9).
Caveats:
- You may want to trim the user-supplied
selector
beforehand, since trailing spaces would have meaning here; - This solution is somewhat specific to the OP's question and would not work if the target div's selector began with an element name, i.e.
selector + 'th, th ' + selector
would not yield a valid selector; in such cases I would recommend using one of the more generic solutions; - You could still stick to the multiple-selector approach with an EXTREMELY HACKY, NOT AT ALL RECOMMENDED approach that involves using the
:not()
pseudoselector: see working demo and horrible, horrible performance.
I create jquery method findAll like below
$.fn.findAll = function ( selector ) {
if ( this.length === 0 ) {
return this;
} else if ( this.length === 1 ) {
return this.filter( selector ).add( this.find( selector ) );
} else {
var rtn = this.filter( selector );
this.each( function () {
rtn.add( $( this ).find( selector ) );
} );
return rtn;
}
}
you can use it like below
$resultSet.findAll(selector)
精彩评论