HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Do not select elements that contain data attributes

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
elementscontaindataattributesthatselectnot

Problem

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.

Solution

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...
});

Code Snippets

$('a[href^="#"]').filter(function () {
    return $.isEmptyObject( this.dataset );
})
jQuery.expr[':']['has-data'] = function (el) {
    return ! $.isEmptyObject( $(el).data() );
    // If you don't care about IE:
    // return ! $.isEmptyObject( el.dataset );
};
$('a[href^="#"]:not(:has-data)').click(function (event) {
    // Your code here...
});

Context

StackExchange Code Review Q#25241, answer score: 4

Revisions (0)

No revisions yet.