I am trying to use the text attribute as a selector, but I can't quite grasp the behaviour, would really appreciate if someone could explain. For example given <span class="span_class"><a class="a_class">text</a></span>
, $('a.a_class').text()
gives "text" as expected. However $('a.a_class[text]')
wouldn't match any elements, and neither would $('span.span_class > a.a_class[text]')
, but $('span.span_class* > a.a_class[text]')
would (although not in IE).
The only workaround I can think of for IE, is loop through all anchors contained in a span, use .text() on each and match it against a certain criteria, but it seems slower than using in-built selectors. Anyone have better ideas?
views:
57answers:
2
+2
A:
This is because 'text' in this case is not an attribute. It is the content of the element.
You're looking for the :contains()
selector:
$('a.a_class:contains(text)');
http://api.jquery.com/contains-selector/
Keep in mind that this selector will match any part of the string. contains(foo)
will match "foo bar" as well.
If you want an exact match of the entire text string, you could use filter()
$('a.a_class').filter(function() {
return $(this).text() == "text";
});
EDIT:
To find elements whose content starts with a value, you could use a regular expression inside the filter()
:
$('a.a_class').filter(function() {
return $(this).text().indexOf( "tex" ) >= 0;
});
EDIT: Updated to use indexOf()
instead of regex as recommended by @Nick.
patrick dw
2010-06-17 10:37:50
Hmm ok. What I was looking for was "Starts with" though, and `$('span.span_class* > a.a_class[text^="tex"]')` was working great, until I tested it with IE.
Shagglez
2010-06-17 10:48:31
@Shagglez - I didn't realize that would work at all. I guess I'd use the `filter()` option with regex to figure out if the text start with "tex".
patrick dw
2010-06-17 10:57:48
@Shagglez - You can use what @patrick has, just replace `return $(this).text() == "text";` with `return $(this).text().indexOf("text") ===0;` for a "start-with" check.
Nick Craver
2010-06-17 11:00:29
Unless you *need* a regular expression, use `.indexOf()`, it's *much* faster, and when you're talking about selectors, especially on potentially large numbers of elements, speed matters.
Nick Craver
2010-06-17 11:02:15
@Nick - Thanks for the pointer. :o)
patrick dw
2010-06-17 11:04:38
+2
A:
what about using a custom selector
$(document).ready(function(){
$.extend($.expr[':'], {
notext: function(elem, i, attr){
return( $(elem).text() === "" );
}
});
});
Synopsis
$('span:notext').remove();
you might even want to create a selector that handles Regular Expressions like
$.extend($.expr[':'], {
'content': function(elem, i, attr){
return( RegExp(attr[3]).test($(elem).text()) );
}
});
Synopsis
$('span:content(^api_)').remove();
would select and remove all spans which text begins with api_
jAndy
2010-06-17 10:45:35
I'll leave the same comment here: Unless you *need* a regular expression, use `.indexOf()`, it's *much* faster, and when you're talking about selectors, especially on potentially large numbers of elements, speed matters.
Nick Craver
2010-06-17 11:02:52
@Nick: I wanted to create it like so, a selector which uses regular expressions.
jAndy
2010-06-17 11:13:54
Probably better to use `$.text(elem)` instead of `$(elem).text()` -- the former is much faster because it avoids constructing a new jQ instance.
J-P
2010-06-17 11:14:15
@J-P - `$.text()` operates on an array, it'd actually be `$.text([this])`, but good point on performance :)
Nick Craver
2010-06-17 11:16:48