I have a selector that pulls in all anchor tags that start with the #
symbol. I am trying to add a :not
selector of some form for elements that have a data
attribute. I know I could do the following...
$('a[href^="#"]:not([data-known])')
But the problem is that I don't know what the data
attribute will be called. I have resorted to doing the following.
$('a[href^="#"]').click(function(event){
if($.isEmptyObject($(this).data())){
//custom code here
}
});
Is there a way to avoid the if
statement and add the :not
to the original selector? Is there a better way of doing this period?
Here is a FIDDLE I have been playing in.
1 Answer 1
Very good question. I'm pretty sure this can't be done within the selector.
However, instead of checking the data
every time it's clicked, filter
the collection before applying the event listener:
$('a[href^="#"]').filter(function () {
return $.isEmptyObject( $(this).data() );
}).click(function (event) {
// Your code here...
});
If you don't care about IE, you can check the dataset
property directly, which is much faster and much more reliable, since $(this).data()
also contains any arbitrary data that might have been set (possibly by a plugin):
$('a[href^="#"]').filter(function () {
return $.isEmptyObject( this.dataset );
})
If you find that you have to do this a lot, you can abstract it into a custom filter, which you can then use in your selectors:
jQuery.expr[':']['has-data'] = function (el) {
return ! $.isEmptyObject( $(el).data() );
// If you don't care about IE:
// return ! $.isEmptyObject( el.dataset );
};
Then just use it throughout your code:
$('a[href^="#"]:not(:has-data)').click(function (event) {
// Your code here...
});
-
\$\begingroup\$ This is great! This solves the main issue I was facing with it having to call
$.isEmptyObject()
on every click. \$\endgroup\$Blake Plumb– Blake Plumb2013年04月18日 23:01:27 +00:00Commented Apr 18, 2013 at 23:01
isEmptyObject
under the hood, but with a lot of extra code that's not needed in this case. \$\endgroup\$hasData
simply won't work at all.hasData
only checks for data that has been set via.data()
. It doesn't automatically pull in the HTML5data-*
attributes. \$\endgroup\$